@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,106 +0,0 @@
1
- import { style } from "@vanilla-extract/css";
2
- import { fadeIn } from "../animations.css.ts";
3
-
4
- export const container = style({
5
- display: "flex",
6
- alignItems: "center",
7
- justifyItems: "center",
8
- flexDirection: "column",
9
- blockSize: "100%",
10
- });
11
-
12
- export const safariPrompt = style({
13
- backgroundColor: "white",
14
- borderRadius: "1rem",
15
- maxWidth: "38rem",
16
- padding: "clamp(1rem, 5vw, 3rem)",
17
- margin: "auto",
18
- });
19
-
20
- export const safariLogo = style({
21
- maxWidth: "4rem",
22
- marginInline: "auto",
23
- marginBlockEnd: "1rem",
24
- aspectRatio: "1",
25
- });
26
-
27
- export const safariPromptHeader = style({
28
- marginBlockEnd: "clamp(1.5rem, 4cqw, 2rem)",
29
- });
30
-
31
- export const safariPromptActions = style({
32
- display: "grid",
33
- gap: "0.5rem",
34
- gridTemplateColumns: "repeat(auto-fill, minmax(12rem, 1fr))",
35
- marginBlock: "1.5rem",
36
- });
37
-
38
- export const safariDismissArea = style({
39
- textAlign: "center",
40
- marginBlock: "2rem 3rem",
41
- });
42
-
43
- export const compatCheckLoaderContainer = style({
44
- maxInlineSize: "16rem",
45
- margin: "auto",
46
- });
47
-
48
- export const indicator = style({
49
- marginInline: "auto",
50
- });
51
-
52
- export const compatCheckLoaderText = style({
53
- fontStyle: "italic",
54
- color: `hsl(0 0% 0% / 0.5)`,
55
- animation: `${fadeIn} 300ms 150ms both`,
56
- marginBlockStart: "0.5rem",
57
- textAlign: "center",
58
- });
59
-
60
- export const emptyStateHeading = style({
61
- textAlign: "center",
62
- marginBlockEnd: "0.5rem",
63
- });
64
-
65
- export const appIcon = style({
66
- aspectRatio: "1",
67
- borderRadius: "20%",
68
- boxShadow: "0 0.125rem 0.25rem hsl(0 0% 0% / 0.2)",
69
- width: "3rem",
70
- height: "auto",
71
- marginInline: "auto",
72
- marginBlockEnd: "1rem",
73
- });
74
-
75
- export const dialog = style({
76
- padding: "2rem",
77
- textAlign: "center",
78
- });
79
-
80
- export const heading = style({
81
- fontSize: "1.25rem",
82
- });
83
-
84
- export const intro = style({
85
- marginBlockStart: "0.5rem",
86
- });
87
-
88
- export const steps = style({
89
- marginBlock: "2rem",
90
- borderBlockStart: "1px solid hsl(0 0% 0% / 0.1)",
91
- textAlign: "left",
92
- });
93
-
94
- export const step = style({
95
- borderBlockEnd: "1px solid hsl(0 0% 0% / 0.1)",
96
- listStyle: "decimal",
97
- listStylePosition: "inside",
98
- paddingBlock: "0.75rem",
99
- });
100
-
101
- export const icon = style({
102
- display: "inline-block",
103
- position: "relative",
104
- inlineSize: "1.25rem",
105
- top: "0.125em",
106
- });
@@ -1,53 +0,0 @@
1
- import { type ReactNode, useEffect } from "react";
2
-
3
- /**
4
- * This component handles the installation of a service worker.
5
- *
6
- * Currently it doesn't do much, but, eventually, it should provide context
7
- * to nested components communicating the status of the service worker installation.
8
- */
9
- export function ServiceWorkerHandler(props: {
10
- children: ReactNode;
11
- path: string;
12
- }) {
13
- useEffect(() => {
14
- async function registerWorker() {
15
- // Although modern browsers all support service workers, native app's
16
- // web views (eg. the Facebook app's embedded browsers) do not.
17
- if ("serviceWorker" in navigator) {
18
- try {
19
- const registration = await navigator.serviceWorker.register(
20
- props.path,
21
- );
22
- console.info("Service worker registration obtained.");
23
-
24
- registration.addEventListener("updatefound", () => {
25
- const worker = registration.installing;
26
- console.info("Installing new service worker.");
27
-
28
- worker?.addEventListener("statechange", ({ target }) => {
29
- if (target instanceof ServiceWorker) {
30
- console.info(
31
- `Service worker state changed: '${target.state}'.`,
32
- );
33
- }
34
- });
35
- });
36
- } catch (error) {
37
- // In rare cases, service worker installation can fail, e.g. due to network
38
- // connectivity. There is no need to report the error as there is nothing
39
- // that can be done to prevent this from occassionally happening.
40
- console.error(error);
41
- }
42
- }
43
- }
44
-
45
- void registerWorker();
46
-
47
- // Note that it is not necessary to 'cleanup' the registration in
48
- // the useEffect hook. Calling register() multiple times is a no-op.
49
- // See https://web.dev/articles/service-workers-registration#subsequent_visits
50
- }, [props.path]);
51
-
52
- return <>{props.children}</>;
53
- }
@@ -1,58 +0,0 @@
1
- import preview from "../../.storybook/preview.tsx";
2
- import { ShareButton } from "./ShareButton.tsx";
3
- import { test } from "./test.css.ts";
4
-
5
- const meta = preview.meta({
6
- title: "Components/Share Button",
7
- component: ShareButton,
8
- tags: ["autodocs"],
9
- args: {
10
- shareLabel: "Share data",
11
- copyLabel: "Copy to clipboard",
12
- shareData: { url: "https://example.com", title: "Example URL" },
13
- },
14
- });
15
-
16
- /**
17
- * The default case.
18
- */
19
- export const Default = meta.story({
20
- args: {},
21
- });
22
-
23
- /**
24
- * Enforce use of copy to clipboard.
25
- */
26
- export const WebShareDisabled = meta.story({
27
- args: {
28
- webShare: false,
29
- },
30
- });
31
-
32
- /**
33
- * Allows overriding revert after milliseconds timer.
34
- */
35
- export const RevertAfterOverride = meta.story({
36
- args: {
37
- revertAfterMs: 5000,
38
- },
39
- });
40
-
41
- /**
42
- * Manually supplying disabled overrides internal button state.
43
- */
44
- export const Disabled = meta.story({
45
- args: {
46
- disabled: true,
47
- },
48
- });
49
-
50
- /**
51
- * Passes along arbitrary props to the underlying button component.
52
- */
53
- export const PassesProps = meta.story({
54
- args: {
55
- className: test,
56
- style: { fontFamily: "cursive", padding: "1rem 2rem" },
57
- },
58
- });
@@ -1,153 +0,0 @@
1
- import { Button, type ButtonProps } from "@ariakit/react";
2
- import { useState, type ReactNode } from "react";
3
- import { useRevertingState } from "../use-reverting-state.ts";
4
-
5
- type AriakitButtonProps = Omit<ButtonProps, "children" | "onClick" | "value">;
6
-
7
- export type CopyToClipboardButtonProps = AriakitButtonProps & {
8
- value: string | null;
9
- children: ReactNode;
10
- revertAfterMs: number;
11
- };
12
-
13
- export function CopyToClipboardButton(props: CopyToClipboardButtonProps) {
14
- const { children, value, revertAfterMs, disabled, ...buttonProps } = props;
15
- const [copiedTimestamp, setCopiedTimestamp] = useRevertingState<
16
- number | null
17
- >(null, revertAfterMs);
18
-
19
- return (
20
- <Button
21
- {...buttonProps}
22
- disabled={disabled || !value}
23
- onClick={async () => {
24
- if (value) {
25
- await navigator.clipboard.writeText(value);
26
- setCopiedTimestamp(Date.now());
27
- }
28
- }}
29
- >
30
- {copiedTimestamp ? "Copied!" : children}
31
- </Button>
32
- );
33
- }
34
-
35
- export type WebShareButtonProps = AriakitButtonProps & {
36
- children: ReactNode;
37
- shareData: ShareData | null;
38
- revertAfterMs: number;
39
- };
40
-
41
- export function WebShareButton(props: WebShareButtonProps) {
42
- const { shareData, children, revertAfterMs, disabled, ...buttonProps } =
43
- props;
44
-
45
- // Tracking sharing state to prevent duplicate invocations of
46
- // the share dialog.
47
- const [sharing, setSharing] = useState(false);
48
-
49
- const [copiedTimestamp, setCopiedTimestamp] = useRevertingState<
50
- number | null
51
- >(null, revertAfterMs);
52
-
53
- return (
54
- <Button
55
- {...buttonProps}
56
- disabled={disabled || !shareData || sharing}
57
- onClick={async () => {
58
- if (shareData) {
59
- try {
60
- setSharing(true);
61
-
62
- await navigator.share(shareData);
63
- setCopiedTimestamp(Date.now());
64
- } catch {
65
- console.info("Not shared");
66
- } finally {
67
- setSharing(false);
68
- }
69
- }
70
- }}
71
- >
72
- {copiedTimestamp ? "Shared!" : children}
73
- </Button>
74
- );
75
- }
76
-
77
- export type ShareButtonProps = AriakitButtonProps & {
78
- /**
79
- * Button label to use when copy to clipboard is used.
80
- */
81
- copyLabel: string;
82
-
83
- /**
84
- * Button label to use when web share is used.
85
- */
86
- shareLabel: string;
87
-
88
- /**
89
- * Data to be shared by the button.
90
- *
91
- * If using copy to clipboard, only the URL value will be used.
92
- */
93
- shareData: ShareData | null;
94
-
95
- /**
96
- * How long should the confirmation message be shown within the button?
97
- *
98
- * @default 1500
99
- */
100
- revertAfterMs?: number;
101
-
102
- /**
103
- * Should web share be used instead of copy to clipboard?
104
- *
105
- * By default, web share will be used if the browser supports it.
106
- *
107
- * @default !!navigator.share
108
- */
109
- webShare?: boolean;
110
- };
111
-
112
- /**
113
- * An unstyled button that is pre-configured to either copy provided share data
114
- * to clipboard, or to use web share, depending on which feature is detected
115
- * in the browser where the button is running.
116
- *
117
- * Props that are not consumed by the Share Button itself are passed to the
118
- * underlying Ariakit Button component.
119
- *
120
- * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/share
121
- */
122
- export function ShareButton(props: ShareButtonProps) {
123
- const {
124
- copyLabel,
125
- shareLabel,
126
- shareData,
127
- revertAfterMs = 1500,
128
- webShare = !!navigator.share,
129
- ...buttonProps
130
- } = props;
131
-
132
- if (webShare) {
133
- return (
134
- <WebShareButton
135
- {...buttonProps}
136
- shareData={shareData}
137
- revertAfterMs={revertAfterMs}
138
- >
139
- {shareLabel}
140
- </WebShareButton>
141
- );
142
- }
143
-
144
- return (
145
- <CopyToClipboardButton
146
- {...buttonProps}
147
- revertAfterMs={revertAfterMs}
148
- value={shareData?.url ?? null}
149
- >
150
- {copyLabel}
151
- </CopyToClipboardButton>
152
- );
153
- }
@@ -1,3 +0,0 @@
1
- import { style } from "@vanilla-extract/css";
2
-
3
- export const test = style({ backgroundColor: "rebeccapurple", color: "wheat" });
@@ -1,23 +0,0 @@
1
- import {
2
- Letterhead,
3
- LetterheadHeading,
4
- LetterheadParagraph,
5
- } from "../Letterhead/index.tsx";
6
- import * as css from "./style.css.ts";
7
- import type { ViewContent } from "./SubscribeByPledgeCard.tsx";
8
-
9
- export function LetterheadInfoCard(props: ViewContent) {
10
- return (
11
- <Letterhead>
12
- <LetterheadHeading className={css.card.heading}>
13
- {props.title}
14
- </LetterheadHeading>
15
-
16
- {typeof props.description === "string" ? (
17
- <LetterheadParagraph>{props.description}</LetterheadParagraph>
18
- ) : (
19
- props.description
20
- )}
21
- </Letterhead>
22
- );
23
- }
@@ -1,69 +0,0 @@
1
- import { http, HttpResponse } from "msw";
2
- import preview from "../../.storybook/preview.tsx";
3
- import { LetterheadParagraph } from "../Letterhead/index.tsx";
4
- import { sleep } from "../sleep.ts";
5
- import { SubscribeByEmailCard } from "./SubscribeByEmailCard.tsx";
6
-
7
- const handlers = {
8
- subscribe() {
9
- return http.post(
10
- "http://mock.api/v1/newsletters/changelog/subscriptions",
11
- async () => {
12
- await sleep(2000);
13
-
14
- return HttpResponse.json(
15
- { tokenId: "1", message: "Ok" },
16
- { status: 201 },
17
- );
18
- },
19
- );
20
- },
21
- confirm() {
22
- return http.put(
23
- "http://mock.api/v1/newsletters/changelog/newsletter-signup-tokens/:tokenId",
24
- async () => {
25
- await sleep(2000);
26
-
27
- return HttpResponse.json({ message: "Ok" }, { status: 201 });
28
- },
29
- );
30
- },
31
- };
32
-
33
- const meta = preview.meta({
34
- title: "Newsletter/Subscribe By Email Card",
35
- component: SubscribeByEmailCard,
36
- tags: ["autodocs"],
37
- args: {
38
- content: {
39
- SUBSCRIBE: {
40
- title: "Space Gits on Indie Tabletop Club",
41
- description: (
42
- <LetterheadParagraph>
43
- Space Gits is getting a fancy <strong>gang builder</strong> and{" "}
44
- <strong>smart rules</strong> in late 2025 in collaboration with
45
- Indie Tabletop Club. Subscribe to ITC&apos;s{" "}
46
- <em>at‑most‑one‑a‑month</em> newsletter and be among the first to
47
- gain early access. It&apos;s gonna be rad.
48
- </LetterheadParagraph>
49
- ),
50
- },
51
- SUBSCRIBE_SUCCESS: {
52
- title: "Subscribed!",
53
- description:
54
- "Thank you for being awesome. Once Space Gits is available for " +
55
- "early access, you will be among the first to know!",
56
- },
57
- },
58
- },
59
- parameters: {
60
- msw: {
61
- handlers: {
62
- subscribe: handlers.subscribe(),
63
- confirm: handlers.confirm(),
64
- },
65
- },
66
- },
67
- });
68
-
69
- export const Default = meta.story({});
@@ -1,183 +0,0 @@
1
- import { Form } from "@ariakit/react";
2
- import {
3
- getSubmitFailureMessage,
4
- Letterhead,
5
- LetterheadFormActions,
6
- LetterheadHeader,
7
- LetterheadHeading,
8
- LetterheadParagraph,
9
- LetterheadSubmitButton,
10
- LetterheadSubmitError,
11
- LetterheadTextField,
12
- useForm,
13
- validEmail,
14
- } from "@indietabletop/appkit";
15
- import {
16
- useState,
17
- type Dispatch,
18
- type ReactNode,
19
- type SetStateAction,
20
- } from "react";
21
- import { useAppConfig, useClient } from "../AppConfig/AppConfig.tsx";
22
- import { LetterheadInfoCard } from "./LetterheadInfoCard.tsx";
23
- import * as css from "./style.css.ts";
24
-
25
- type SetStep = Dispatch<SetStateAction<SubscribeStep>>;
26
-
27
- function SubscribeView(
28
- props: ViewContent & {
29
- setStep: SetStep;
30
- },
31
- ) {
32
- const { placeholders } = useAppConfig();
33
- const { title, description, setStep } = props;
34
-
35
- const client = useClient();
36
- const { form, submitName } = useForm({
37
- defaultValues: {
38
- email: "",
39
- },
40
- validate: {
41
- email: validEmail,
42
- },
43
- async onSubmit({ values }) {
44
- const result = await client.subscribeToNewsletterByEmail(
45
- "changelog",
46
- values.email,
47
- );
48
-
49
- return result.mapFailure(getSubmitFailureMessage);
50
- },
51
- async onSuccess({ tokenId }, { values }) {
52
- setStep({ type: "SUBMIT_CODE", email: values.email, tokenId });
53
- },
54
- });
55
-
56
- return (
57
- <Form store={form} resetOnSubmit={false}>
58
- <Letterhead>
59
- <LetterheadHeader>
60
- <LetterheadHeading className={css.card.heading}>
61
- {title}
62
- </LetterheadHeading>
63
-
64
- {description}
65
- </LetterheadHeader>
66
-
67
- <LetterheadTextField
68
- name={form.names.email}
69
- label="Your email"
70
- placeholder={placeholders.email}
71
- autoComplete="email"
72
- required
73
- />
74
-
75
- <LetterheadFormActions>
76
- <LetterheadSubmitError name={submitName} />
77
- <LetterheadSubmitButton>Subscribe</LetterheadSubmitButton>
78
- </LetterheadFormActions>
79
- </Letterhead>
80
- </Form>
81
- );
82
- }
83
-
84
- function SubmitCodeStep(props: {
85
- tokenId: string;
86
- setStep: SetStep;
87
- email: string;
88
- }) {
89
- const { tokenId, email, setStep } = props;
90
- const client = useClient();
91
-
92
- const { form, submitName } = useForm({
93
- defaultValues: {
94
- code: "",
95
- },
96
- async onSubmit({ values }) {
97
- const op = await client.confirmNewsletterSignup(
98
- "changelog",
99
- tokenId,
100
- values.code,
101
- );
102
-
103
- return op.mapFailure((failure) => {
104
- return getSubmitFailureMessage(failure, {
105
- 404: "🚫 This code is incorrect or expired. Please try again.",
106
- });
107
- });
108
- },
109
- onSuccess() {
110
- setStep({ type: "SUBSCRIBE_SUCCESS" });
111
- },
112
- });
113
-
114
- return (
115
- <Form store={form} resetOnSubmit={false}>
116
- <Letterhead>
117
- <LetterheadHeader>
118
- <LetterheadHeading>Confirm subscription</LetterheadHeading>
119
- <LetterheadParagraph>
120
- We've sent a one-time code to <em>{email}</em>. Please, enter the
121
- code in the field below to confirm your newsletter subscription.
122
- </LetterheadParagraph>
123
- </LetterheadHeader>
124
-
125
- <LetterheadTextField
126
- name={form.names.code}
127
- label="Code"
128
- placeholder="E.g. 123123"
129
- autoComplete="one-time-code"
130
- required
131
- />
132
-
133
- <LetterheadFormActions>
134
- <LetterheadSubmitError name={submitName} />
135
- <LetterheadSubmitButton>Confirm</LetterheadSubmitButton>
136
- </LetterheadFormActions>
137
- </Letterhead>
138
- </Form>
139
- );
140
- }
141
-
142
- type SubscribeStep =
143
- | { type: "SUBSCRIBE" }
144
- | { type: "SUBMIT_CODE"; email: string; tokenId: string }
145
- | { type: "SUBSCRIBE_SUCCESS" };
146
-
147
- type ViewContent = {
148
- title: ReactNode;
149
- description: ReactNode;
150
- };
151
-
152
- /**
153
- * Allows users to sign up to the newsletter using an arbitrary email.
154
- *
155
- * Signups are verified using an one-time code, which is sent to the supplied
156
- * email address.
157
- */
158
- export function SubscribeByEmailCard(props: {
159
- content: Record<Exclude<SubscribeStep["type"], "SUBMIT_CODE">, ViewContent>;
160
- }) {
161
- const { content } = props;
162
- const [step, setStep] = useState<SubscribeStep>({ type: "SUBSCRIBE" });
163
-
164
- switch (step.type) {
165
- case "SUBSCRIBE": {
166
- return <SubscribeView {...content[step.type]} setStep={setStep} />;
167
- }
168
-
169
- case "SUBMIT_CODE": {
170
- return (
171
- <SubmitCodeStep
172
- email={step.email}
173
- tokenId={step.tokenId}
174
- setStep={setStep}
175
- />
176
- );
177
- }
178
-
179
- case "SUBSCRIBE_SUCCESS": {
180
- return <LetterheadInfoCard {...content[step.type]} />;
181
- }
182
- }
183
- }