@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,214 +0,0 @@
1
- import { useCallback, useSyncExternalStore } from "react";
2
- import { Failure, Pending, Success } from "./async-op.ts";
3
- import { isNullish } from "./typeguards.ts";
4
-
5
- type RulesetLike = { version: string };
6
-
7
- type GetRemoteRuleset<R extends RulesetLike, F> = (
8
- version: string,
9
- ) => Promise<Success<R> | Failure<F>>;
10
-
11
- type RulesetResolverProps<R extends RulesetLike, F> = {
12
- /**
13
- * The initial ruleset that will be available to all users immediately at
14
- * app start.
15
- */
16
- initialRuleset: R;
17
-
18
- /**
19
- * A function that should return a Result with an instance of
20
- * a Ruleset for the given game.
21
- */
22
- getRemoteRuleset: GetRemoteRuleset<R, F>;
23
- };
24
-
25
- /**
26
- * Encapsulates ruleset caching and retrieval logic.
27
- *
28
- * Usually you want to instantiate this class and immediately pass it to
29
- * {@link createRulesetResolverBindings} so that you can use it from within
30
- * React components with proper re-renders.
31
- *
32
- * @example
33
- * ```ts
34
- * import { createRulesetResolverBindings, RulesetResolver } from "@indietabletop/appkit";
35
- *
36
- * // Instantiate a resolver and export it for any potential use
37
- * export const resolver = new RulesetResolver({
38
- * initialRuleset: new Ruleset({ ... }),
39
- * async getRemoteRuleset(version) {
40
- * // Get ruleset from a remote location somehow
41
- * return new Ruleset({ ... });
42
- * },
43
- * });
44
- *
45
- * // Generate resolver-bound hooks for use within React components
46
- * export const { useResolveRuleset, useLatestRuleset } =
47
- * createRulesetResolverBindings(resolver);
48
- * ```
49
- */
50
- export class RulesetResolver<R extends RulesetLike, F> {
51
- getRemoteRuleset: GetRemoteRuleset<R, F>;
52
- rulesets: Map<string, Success<R> | Failure<F>>;
53
-
54
- constructor(props: RulesetResolverProps<R, F>) {
55
- this.getRemoteRuleset = props.getRemoteRuleset;
56
- this.rulesets = new Map([
57
- [props.initialRuleset.version, new Success(props.initialRuleset)],
58
- ]);
59
- }
60
-
61
- get latest() {
62
- const sortedRulesets = Array.from(this.rulesets.values())
63
- .filter((result) => result.isSuccess)
64
- .map((result) => result.value)
65
- .sort((left, right) => left.version.localeCompare(right.version));
66
-
67
- if (sortedRulesets.length === 0) {
68
- throw new Error(
69
- `Could not resolve latest ruleset. Ruleset resolver doesn't include any succesfully resolved ruleset versions.`,
70
- );
71
- }
72
-
73
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
74
- return sortedRulesets.at(-1)!;
75
- }
76
-
77
- requests = new Map<string, Promise<Success<R> | Failure<F>>>();
78
-
79
- /**
80
- * Resolves a ruleset version if it is currently in memory.
81
- *
82
- * Otherwise, initiates ruleset resolution from a remote source in the
83
- * background and returns `null`. If you want to know when the freshly
84
- * requested ruleset will be resolved, you must use the {@link subscribe}
85
- * method (possibly using a hook returned from {@link createRulesetResolverBindings}).
86
- */
87
- resolve(version: string) {
88
- const ruleset = this.rulesets.get(version);
89
- if (ruleset) {
90
- return ruleset;
91
- }
92
-
93
- void this.resolveFromRemote(version);
94
- return null;
95
- }
96
-
97
- /**
98
- * Resolves a ruleset from a remote source, deduplicating requests to
99
- * identical rulesets.
100
- */
101
- async resolveFromRemote(version: string) {
102
- const ongoingRequest = this.requests.get(version);
103
- if (ongoingRequest) {
104
- return await ongoingRequest;
105
- }
106
-
107
- const remoteRulesetPromise = this.getRemoteRuleset(version);
108
- this.requests.set(version, remoteRulesetPromise);
109
-
110
- const newRuleset = await remoteRulesetPromise;
111
- this.rulesets.set(version, newRuleset);
112
- this.notify();
113
-
114
- // Clear requests cache to allow for potential retries
115
- this.requests.delete(version);
116
-
117
- return newRuleset;
118
- }
119
-
120
- listeners = new Set<() => void>();
121
-
122
- subscribe(callback: () => void) {
123
- this.listeners.add(callback);
124
- }
125
-
126
- unsubscribe(callback: () => void) {
127
- this.listeners.delete(callback);
128
- }
129
-
130
- notify() {
131
- for (const notifyListener of this.listeners) {
132
- notifyListener();
133
- }
134
- }
135
- }
136
-
137
- /**
138
- * Given a RulesetResolver, creates bound React hooks that trigger re-renders
139
- * when new rulesets are resolved by the resolver.
140
- *
141
- * Usually you will create these hooks in their own module and export them
142
- * for further use.
143
- *
144
- * @example
145
- * ```ts
146
- * export const resolver = new RulesetResolver({ ... });
147
- *
148
- * export const { useResolveRuleset, useLatestRuleset } =
149
- * createRulesetResolverHooks(resolver);
150
- * ```
151
- */
152
- export function createRulesetResolverBindings<
153
- Ruleset extends RulesetLike,
154
- Failure,
155
- >(resolver: RulesetResolver<Ruleset, Failure>) {
156
- // Pending state with stable identity — necessary so that
157
- // useSyncExternalStore doesn't enter an infinite loop.
158
- const pending = new Pending();
159
-
160
- /**
161
- * Returns a ruleset result compatible with the provided version.
162
- *
163
- * If a ruleset is not currently in memory, it will be requested in the
164
- * background and the component using this hook will be re-rendered once
165
- * the request is completed.
166
- *
167
- * Note that requests are deduplicated, so it is safe to use this hook
168
- * in loops/lists where multiple components might request identical
169
- * ruleset verions.
170
- */
171
- function useResolveRuleset(version: string | null | undefined) {
172
- const subscribe = useCallback((callback: () => void) => {
173
- resolver.subscribe(callback);
174
-
175
- return () => {
176
- resolver.unsubscribe(callback);
177
- };
178
- }, []);
179
-
180
- const getSnapshot = useCallback(() => {
181
- if (!isNullish(version)) {
182
- return resolver.resolve(version) ?? pending;
183
- }
184
-
185
- return pending;
186
- }, [version]);
187
-
188
- return useSyncExternalStore(subscribe, getSnapshot);
189
- }
190
-
191
- /**
192
- * Returns the latest ruleset available in memory.
193
- */
194
- function useLatestRuleset() {
195
- const subscribe = useCallback((callback: () => void) => {
196
- resolver.subscribe(callback);
197
-
198
- return () => {
199
- resolver.unsubscribe(callback);
200
- };
201
- }, []);
202
-
203
- const getSnapshot = useCallback(() => {
204
- return resolver.latest;
205
- }, []);
206
-
207
- return useSyncExternalStore(subscribe, getSnapshot);
208
- }
209
-
210
- return {
211
- useLatestRuleset,
212
- useResolveRuleset,
213
- };
214
- }
@@ -1,99 +0,0 @@
1
- import { http, HttpResponse } from "msw";
2
- import preview from "../../.storybook/preview.tsx";
3
- import { sleep } from "../sleep.ts";
4
- import { SafariCheck } from "./SafariCheck.tsx";
5
-
6
- function Content() {
7
- return (
8
- <div>
9
- <h1>Safari Check passed</h1>
10
- <button
11
- onClick={() => {
12
- localStorage.clear();
13
- window.location.reload();
14
- }}
15
- >
16
- Clear local storage
17
- </button>
18
- </div>
19
- );
20
- }
21
-
22
- function userAgentResponse(params: { browserName: string }) {
23
- return http.get("http://mock.api/ua", async () => {
24
- await sleep(1500);
25
- return HttpResponse.json({
26
- browser: { name: params.browserName },
27
- device: params.browserName.includes("Mobile") ? { type: "mobile" } : {},
28
- });
29
- });
30
- }
31
-
32
- const meta = preview.meta({
33
- title: "Components/SafariCheck",
34
- component: SafariCheck,
35
- tags: ["autodocs"],
36
- decorators: [
37
- (Story) => (
38
- <div style={{ height: "100svh", display: "grid" }}>
39
- <Story />
40
- </div>
41
- ),
42
- ],
43
- parameters: {
44
- msw: {
45
- handlers: {
46
- ua: userAgentResponse({ browserName: "Safari" }),
47
- },
48
- },
49
- },
50
- });
51
-
52
- export const SafariDesktop = meta.story({
53
- args: {
54
- children: <Content />,
55
- },
56
- parameters: {
57
- msw: {
58
- handlers: {
59
- ua: userAgentResponse({ browserName: "Safari" }),
60
- },
61
- },
62
- },
63
- });
64
-
65
- export const SafariMobile = meta.story({
66
- args: {
67
- children: <Content />,
68
- },
69
- parameters: {
70
- msw: {
71
- handlers: {
72
- ua: userAgentResponse({ browserName: "Safari Mobile" }),
73
- },
74
- },
75
- },
76
- });
77
-
78
- export const OtherBrowser = meta.story({
79
- args: {
80
- children: <Content />,
81
- },
82
- parameters: {
83
- msw: {
84
- handlers: {
85
- ua: userAgentResponse({ browserName: "Chrome" }),
86
- },
87
- },
88
- },
89
- });
90
-
91
- /**
92
- * The check behaviour has been disabled.
93
- */
94
- export const Disabled = meta.story({
95
- args: {
96
- children: <Content />,
97
- performCheck: false,
98
- },
99
- });
@@ -1,273 +0,0 @@
1
- import { Button, DialogDisclosure, DialogDismiss } from "@ariakit/react";
2
- import { useCallback, useMemo, useState, type ReactNode } from "react";
3
- import { number } from "superstruct";
4
- import useImmutableSWR from "swr/immutable";
5
- import { Link } from "wouter";
6
- import { useAppConfig, useClient } from "../AppConfig/AppConfig.tsx";
7
- import { Failure, Pending, Success } from "../async-op.ts";
8
- import { interactiveText } from "../common.css.ts";
9
- import { createSafeStorage } from "../createSafeStorage.ts";
10
- import { DialogTrigger } from "../DialogTrigger/index.tsx";
11
- import {
12
- LetterheadFooter,
13
- LetterheadHeading,
14
- LetterheadParagraph,
15
- } from "../Letterhead/index.tsx";
16
- import { button } from "../Letterhead/style.css.ts";
17
- import { LoadingIndicator } from "../LoadingIndicator.tsx";
18
- import { ModalDialog } from "../ModalDialog/index.tsx";
19
- import { swrResponseToResult } from "../result/swr.ts";
20
- import { useCurrentUser } from "../store/index.tsx";
21
- import type { FailurePayload } from "../types.ts";
22
- import { useIsInstalled } from "../use-is-installed.ts";
23
- import addToDockUrl from "./addToDock.svg";
24
- import addToHomeScreenUrl from "./addToHomeScreen.svg";
25
- import safariUrl from "./safari.svg";
26
- import shareIconUrl from "./shareIcon.svg";
27
- import * as css from "./style.css.ts";
28
-
29
- function InstallAppDialog({ isMobile }: { isMobile?: boolean }) {
30
- const config = useAppConfig();
31
-
32
- const shareIcon = <img src={shareIconUrl} alt="" className={css.icon} />;
33
- const addIcon = <img src={addToHomeScreenUrl} alt="" className={css.icon} />;
34
- const addToDockIcon = <img src={addToDockUrl} alt="" className={css.icon} />;
35
-
36
- const steps = [
37
- <>
38
- Open the <strong>Share</strong> menu {shareIcon}
39
- </>,
40
-
41
- isMobile ? (
42
- <>
43
- Tap <strong>Add to Home Screen</strong> {addIcon}
44
- </>
45
- ) : (
46
- <>
47
- Click <strong>Add to Dock</strong> {addToDockIcon}
48
- </>
49
- ),
50
-
51
- isMobile ? (
52
- <>
53
- Tap <strong>Add</strong> in the top right corner
54
- </>
55
- ) : (
56
- <>
57
- Click <strong>Add</strong>
58
- </>
59
- ),
60
- ];
61
-
62
- return (
63
- <ModalDialog size="small" className={css.dialog}>
64
- <img
65
- src={config.app.icon}
66
- alt=""
67
- width="512"
68
- height="512"
69
- className={css.appIcon}
70
- />
71
-
72
- <LetterheadHeading className={css.heading}>
73
- Install {config.app.name}
74
- </LetterheadHeading>
75
-
76
- <LetterheadParagraph className={css.intro}>
77
- To install this app, follow these 3 steps:
78
- </LetterheadParagraph>
79
-
80
- <ol className={css.steps}>
81
- {steps.map((step, index) => {
82
- return (
83
- <li className={css.step} key={index}>
84
- {step}
85
- </li>
86
- );
87
- })}
88
- </ol>
89
-
90
- <div>
91
- <DialogDismiss className={interactiveText}>Dismiss</DialogDismiss>
92
- </div>
93
- </ModalDialog>
94
- );
95
- }
96
-
97
- function SafariPrompt(props: { onDismiss: () => void; isMobile?: boolean }) {
98
- const { hrefs } = useAppConfig();
99
-
100
- const delete_your_local_data = <strong>delete your local data</strong>;
101
-
102
- const install_the_app = <strong>install the app</strong>;
103
-
104
- const creating_an_account = <strong>creating an account</strong>;
105
-
106
- return (
107
- <div className={css.safariPrompt}>
108
- <div className={css.safariPromptHeader}>
109
- <img
110
- src={safariUrl}
111
- alt=""
112
- width="64"
113
- height="64"
114
- className={css.safariLogo}
115
- />
116
-
117
- <LetterheadHeading className={css.emptyStateHeading}>
118
- Heads up Safari users!
119
- </LetterheadHeading>
120
- </div>
121
- <LetterheadParagraph>
122
- Safari — unlike other browsers — will {delete_your_local_data} after 7
123
- days of inactivity, unless you have installed the app.
124
- </LetterheadParagraph>
125
- <LetterheadParagraph>
126
- To prevent accidental data loss, you can either {install_the_app}, make
127
- sure all your data is safely backed up by {creating_an_account}, or use
128
- a different browser.
129
- </LetterheadParagraph>
130
-
131
- <div className={css.safariPromptActions}>
132
- <DialogTrigger>
133
- <InstallAppDialog isMobile={props.isMobile} />
134
-
135
- <DialogDisclosure className={button()}>Install App</DialogDisclosure>
136
- </DialogTrigger>
137
-
138
- <Link className={button()} href={hrefs.join()}>
139
- Create Account
140
- </Link>
141
- </div>
142
-
143
- <div className={css.safariDismissArea}>
144
- <LetterheadParagraph align="center">
145
- <Button className={interactiveText} onClick={props.onDismiss}>
146
- I don’t mind if my data gets deleted
147
- </Button>
148
- </LetterheadParagraph>
149
- </div>
150
-
151
- <LetterheadFooter />
152
- </div>
153
- );
154
- }
155
-
156
- function useUserAgent(props: { performFetch: boolean }) {
157
- const client = useClient();
158
-
159
- const swr = useImmutableSWR(
160
- props.performFetch ? "/ua" : null,
161
- useCallback(() => client.userAgent(), []),
162
- );
163
-
164
- return swrResponseToResult(swr);
165
- }
166
-
167
- const storage = createSafeStorage({ safariInstallPromptDismissedAt: number() });
168
-
169
- function useInstallPromptState() {
170
- const [dismissedAt, setState] = useState(() =>
171
- storage.getItem("safariInstallPromptDismissedAt"),
172
- );
173
-
174
- return {
175
- dismissedAt,
176
- setDismissed: useCallback(() => {
177
- const timestamp = Date.now();
178
-
179
- setState(timestamp);
180
- storage.setItem("safariInstallPromptDismissedAt", timestamp);
181
- }, []),
182
- };
183
- }
184
-
185
- type SafariCheckResult =
186
- | Success<{ showPrompt: boolean; isMobile?: boolean }>
187
- | Failure<FailurePayload>
188
- | Pending;
189
-
190
- function useSafariCheck({ performCheck }: { performCheck: boolean }) {
191
- const isAuthenticated = !!useCurrentUser();
192
- const isInstalled = useIsInstalled();
193
- const { dismissedAt, setDismissed } = useInstallPromptState();
194
- const installedOrDismissed = isInstalled || !!dismissedAt;
195
- const userAgentResult = useUserAgent({
196
- performFetch: performCheck && !isAuthenticated && !installedOrDismissed,
197
- });
198
-
199
- const result = useMemo((): SafariCheckResult => {
200
- return isAuthenticated || installedOrDismissed || !performCheck
201
- ? // If the safari prompt was previously dismissed, the app is already
202
- // installed, or check was disabled explicitly, we skip the prompt.
203
- new Success({ showPrompt: false })
204
- : // Otherwise, we want to check whether the name includes Safari (could be
205
- // Safari or Safari Mobile), and we also report whether this is a mobile
206
- // device to allow for more targeted install instructions for the user.
207
- userAgentResult.mapSuccess((value) => {
208
- return {
209
- showPrompt: value.browser?.name?.includes("Safari") ?? false,
210
- isMobile: value.device?.type === "mobile",
211
- };
212
- });
213
- }, [installedOrDismissed, userAgentResult, performCheck, isAuthenticated]);
214
-
215
- return { result, setDismissed };
216
- }
217
-
218
- /**
219
- * Checks whether the browser which is running the app is Safari/Safari Mobile
220
- * and warns the user that their data might be deleted due to inactivity.
221
- *
222
- * The warning will be shown if:
223
- *
224
- * - The check has not been explicitly disabled via `performCheck: false`
225
- * - The warning has not been previously dismissed (as reported by localStorage)
226
- * - The app is not installed (Safari behaves differently in that case)
227
- * - The user is not already logged in (as data will be safely backed up that way)
228
- */
229
- export function SafariCheck(props: {
230
- children: ReactNode;
231
-
232
- /**
233
- * Optionally opt out of the check.
234
- *
235
- * This can be useful in cases where, e.g. the user already has some content
236
- * in the app and we want to avoid checking the user agent, but it is
237
- * impractical to entirely avoid rendering this component.
238
- */
239
- performCheck?: boolean;
240
- }) {
241
- const { result, setDismissed } = useSafariCheck({
242
- performCheck: props.performCheck ?? true,
243
- });
244
-
245
- if (result.isPending) {
246
- return (
247
- <div className={css.container}>
248
- <div className={css.compatCheckLoaderContainer}>
249
- <LoadingIndicator className={css.indicator} />
250
-
251
- {/* Intentionally not using Letterhead Paragraph to pick up the default
252
- font size and style. */}
253
- <p className={css.compatCheckLoaderText}>Checking compatibility...</p>
254
- </div>
255
- </div>
256
- );
257
- }
258
-
259
- // Get the success value. Note that if the UA check is a failure we don't
260
- // want to bother the user with any failure messages. In that case, we just
261
- // keep rolling as if the showPrompt was false.
262
- const value = result.valueOrNull();
263
- if (value?.showPrompt) {
264
- return (
265
- <div className={css.container}>
266
- <SafariPrompt onDismiss={setDismissed} isMobile={value.isMobile} />
267
- </div>
268
- );
269
- }
270
-
271
- // We're all good, render children.
272
- return <>{props.children}</>;
273
- }
@@ -1,13 +0,0 @@
1
- <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <g clip-path="url(#clip0_277_21)">
3
- <rect width="16" height="16" fill="none"/>
4
- <rect x="1.5" y="3" width="13" height="10" rx="1" stroke="black"/>
5
- <path d="M2 5H14" stroke="black"/>
6
- <rect x="3.5" y="9.5" width="9" height="2" rx="0.5" fill="black"/>
7
- </g>
8
- <defs>
9
- <clipPath id="clip0_277_21">
10
- <rect width="16" height="16" fill="none"/>
11
- </clipPath>
12
- </defs>
13
- </svg>
@@ -1,12 +0,0 @@
1
- <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <g clip-path="url(#clip0_276_9)">
3
- <rect width="16" height="16" fill="none"/>
4
- <rect x="2.5" y="2.5" width="11" height="11" rx="2" stroke="black"/>
5
- <path d="M5 8H8M8 8H11M8 8V11M8 8V5" stroke="black"/>
6
- </g>
7
- <defs>
8
- <clipPath id="clip0_276_9">
9
- <rect width="16" height="16" fill="none"/>
10
- </clipPath>
11
- </defs>
12
- </svg>
@@ -1,32 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="66.165833mm" height="65.803795mm" viewBox="0 0 66.165833 65.803795">
3
- <defs>
4
- <linearGradient id="b">
5
- <stop offset="0" stop-color="#06c2e7"/>
6
- <stop offset=".25000015" stop-color="#0db8ec"/>
7
- <stop offset=".5000003" stop-color="#12aef1"/>
8
- <stop offset=".75000012" stop-color="#1f86f9"/>
9
- <stop offset="1" stop-color="#107ddd"/>
10
- </linearGradient>
11
- <linearGradient id="a">
12
- <stop offset="0" stop-color="#bdbdbd"/>
13
- <stop offset="1" stop-color="#fff"/>
14
- </linearGradient>
15
- <linearGradient xlink:href="#a" id="d" x1="412.97501" x2="412.97501" y1="237.60777" y2="59.392235" gradientTransform="translate(206.79018 159.77261) scale(.35154)" gradientUnits="userSpaceOnUse"/>
16
- <filter id="f" width="1.0418189" height="1.0446756" x="-.02090938" y="-.0223378" color-interpolation-filters="sRGB">
17
- <feGaussianBlur stdDeviation=".95767362"/>
18
- </filter>
19
- <filter id="c" width="1.096" height="1.096" x="-.048" y="-.048" color-interpolation-filters="sRGB">
20
- <feGaussianBlur stdDeviation="3.5643107"/>
21
- </filter>
22
- <radialGradient xlink:href="#b" id="e" cx="413.06128" cy="136.81819" r="82.125351" fx="413.06128" fy="136.81819" gradientTransform="translate(194.54473 155.58044) scale(.38143)" gradientUnits="userSpaceOnUse"/>
23
- </defs>
24
- <path d="M502.08277 148.5a89.107765 89.107765 0 0 1-89.10777 89.10777A89.107765 89.107765 0 0 1 323.86724 148.5 89.107765 89.107765 0 0 1 412.975 59.392235 89.107765 89.107765 0 0 1 502.08277 148.5Z" filter="url(#c)" opacity=".52999998" paint-order="markers stroke fill" transform="matrix(.33865 0 0 .3261 -106.76956 -14.47833)"/>
25
- <path fill="url(#d)" stroke="#cdcdcd" stroke-linecap="round" stroke-linejoin="round" stroke-width=".09301235" d="M383.29373 211.97671a31.325188 31.325188 0 0 1-31.32519 31.32519 31.325188 31.325188 0 0 1-31.32518-31.32519 31.325188 31.325188 0 0 1 31.32518-31.32519 31.325188 31.325188 0 0 1 31.32519 31.32519z" paint-order="markers stroke fill" transform="translate(-318.88562 -180.59501)"/>
26
- <path fill="url(#e)" d="M380.83911 211.97671a28.870571 28.870571 0 0 1-28.87057 28.87057 28.870571 28.870571 0 0 1-28.87057-28.87057 28.870571 28.870571 0 0 1 28.87057-28.87057 28.870571 28.870571 0 0 1 28.87057 28.87057z" paint-order="markers stroke fill" transform="translate(-318.88562 -180.59501)"/>
27
- <path fill="#f4f2f3" d="M33.08292 4.01671c-.23319 0-.42092.18772-.42092.42092V9.2928c0 .2332.18773.42092.42092.42092.2332 0 .42092-.18772.42092-.42092V4.43763c0-.2332-.18772-.42092-.42092-.42092zm-2.75367.17404c-.0279-.003-.0566-.003-.0856.00035-.23194.0242-.39917.2304-.37495.46234l.21218 2.03119c.0242.23194.23041.39918.46233.37496.23195-.0242.39919-.2304.37496-.46234l-.212-2.03118c-.0212-.20295-.18177-.35637-.37695-.37532zm5.5266.002c-.19519.0188-.35578.17221-.37714.37513l-.21363 2.03102c-.0244.23192.14285.43831.37478.4627.23191.0244.43811-.14268.46251-.3746l.21364-2.03119c.0244-.23192-.14286-.43814-.37478-.46252-.029-.003-.0575-.003-.0854-.00052zm-8.3553.4082c-.028.00022-.0565.003-.085.009-.22814.0483-.37294.27089-.32464.49903l1.00552 4.74981c.0483.22814.27088.37293.49902.32464.22814-.0483.37294-.27072.32465-.49886l-1.00552-4.74998c-.0423-.19963-.21792-.33543-.41401-.3339zm11.18382.004c-.19609-.002-.3718.13394-.41419.33353l-1.00897 4.74925c-.0485.22811.0962.45076.32427.49922.22811.0485.45076-.0962.49921-.32428l1.00897-4.74926c.0485-.2281-.0962-.45076-.32427-.49921-.0285-.006-.057-.009-.085-.009zM24.801 5.36212c-.0545-.005-.11077.001-.16622.0194-.22178.0721-.34238.3085-.27031.53028l.6311 1.94236c.0721.22179.30868.34238.53046.27032.22179-.0721.3422-.30868.27013-.53046l-.63109-1.94236c-.054-.16634-.20059-.27568-.36407-.28958zm16.56765.001c-.16348.0139-.30999.12324-.36406.28957l-.63147 1.94218c-.0721.22177.0484.45837.27014.53046.22178.0721.45837-.0484.53047-.27013l.63146-1.94236c.0721-.22178-.0484-.45837-.27014-.53046-.0554-.018-.11191-.0239-.1664-.0193zm-19.23721.9759c-.0547.001-.11004.013-.16331.0367-.21298.0947-.30836.34244-.21364.55553l1.97197 4.43662c.0947.21308.34244.30836.55553.21364.21298-.0947.30854-.34244.21382-.55553l-1.97216-4.43662c-.071-.15983-.22817-.25351-.39221-.25033zm21.93693.0149c-.16403-.003-.32132.0901-.39257.24979l-1.97798 4.4339c-.095.21296-.00004.46088.21292.55589.21297.095.46088.00005.5559-.21291L44.4446 6.9467c.095-.21297.00005-.46089-.21291-.5559-.0532-.0237-.10864-.0357-.16332-.0369zM19.65353 7.6501c-.0808-.006-.16406.012-.23979.0558-.20196.1166-.27065.37302-.15406.57497l1.02115 1.76869c.1166.20196.373.27065.57496.15405.20195-.1166.27065-.37301.15406-.57497L19.9887 7.85996c-.0729-.12623-.20047-.20041-.33517-.20983zm26.85877 0c-.13468.009-.26211.0836-.33498.20983l-1.02133 1.76868c-.1166.20196-.0477.45837.15424.57497.20196.1166.45837.0479.57497-.15405l1.02114-1.76869c.1166-.20195.0479-.45837-.15406-.57497-.0757-.0437-.15916-.0614-.23998-.0558zM17.24739 9.15083c-.081.003-.16211.029-.2329.0803-.18875.13693-.23048.39911-.0935.58787l2.85086 3.92995c.13693.18876.39929.23049.58805.0936.18876-.13693.23049-.39911.0935-.58787l-2.85104-3.92995c-.0856-.11798-.22004-.17847-.35497-.17386zm31.70122.0214c-.13493-.005-.26941.0555-.35516.17331l-2.8563 3.92614c-.1372.18857-.0958.45086.0928.58805.18858.13718.45087.0959.58806-.0926l2.85613-3.92614c.13718-.18858.0957-.45086-.0928-.58805-.0707-.0514-.15176-.0778-.23272-.0807zm-33.85196 1.78231c-.10744-.006-.21708.0299-.30374.10791-.17332.15602-.18725.42109-.0312.59441l1.36648 1.51799c.15601.17332.42109.18726.59441.0312.17332-.15602.18726-.42127.0312-.59459l-1.3663-1.51781c-.078-.0867-.18339-.13351-.29085-.13916zm35.97562.003c-.10745.006-.21282.0525-.29084.13915l-1.36648 1.51763c-.15606.1733-.14224.43855.0311.59459.17329.15604.43837.14205.59441-.0312l1.36666-1.51762c.15605-.17331.14205-.43856-.0312-.59459-.0867-.078-.19611-.11354-.30357-.10791zm-38.03696 1.97705c-.10745.006-.21266.0525-.29067.13916-.15602.17332-.14207.43839.0312.59441l3.60841 3.24834c.17332.15603.43839.14207.5944-.0312.15603-.17331.14226-.43839-.0311-.59441l-3.60858-3.24834c-.0867-.078-.1963-.11356-.30376-.10791zm40.10831.0142c-.10745-.006-.21722.0298-.30393.10773l-3.61059 3.24581c-.17342.15589-.18768.42097-.0318.5944.1559.17342.42117.18751.59459.0316l3.61077-3.2458c.17342-.1559.1875-.42098.0316-.59441-.078-.0867-.18322-.13361-.29066-.13933zm-41.8225 2.18998c-.13494-.005-.26949.0558-.35515.17367-.13707.18866-.0955.4508.0932.58787l1.65224 1.20044c.18866.13708.45079.0957.58786-.093.13708-.18866.0956-.45098-.093-.58805l-1.65224-1.20044c-.0707-.0514-.15193-.0776-.23289-.0805zm43.53505.0153c-.081.003-.16211.0289-.23289.0803l-1.65297 1.19936c-.18875.13694-.2305.39929-.0936.58805.13695.18875.39912.23031.58787.0934l1.65316-1.19935c.18875-.13694.23031-.39912.0934-.58787-.0856-.11797-.22004-.17847-.35497-.17385zM9.7192 17.48992c-.13469.009-.26211.0836-.33499.20982-.1166.20195-.0479.45837.15405.57497l4.20463 2.42758c.20195.1166.45837.0479.57497-.15405.1166-.20195.0479-.45837-.15405-.57497l-4.20463-2.42759c-.0757-.0437-.15917-.0614-.23998-.0558zm46.72744 0c-.0808-.006-.16425.012-.23998.0558l-4.20463 2.42759c-.20195.1166-.27065.37302-.15405.57497.1166.20195.37302.27065.57497.15405l4.20482-2.42758c.20195-.1166.27064-.37302.15404-.57497-.0729-.12622-.20048-.20041-.33517-.20982zm-47.9386 2.50606c-.16403-.004-.32133.0899-.39258.2496-.095.21298-.00006.46091.21292.5559l1.86532.83202c.21298.095.46091.00007.5559-.2129.095-.21298-.00012-.46091-.21309-.5559l-1.86515-.83202c-.0532-.0238-.10865-.0356-.16332-.0367zm49.15794.0173c-.0547.001-.11024.013-.16351.0367l-1.86569.83057c-.21304.0949-.3083.34267-.21346.55571.0949.21304.34286.3083.5559.21346l1.8657-.83076c.21303-.0948.30811-.34267.21327-.55571-.0711-.15978-.22818-.25323-.39221-.24997zM7.42859 22.61527c-.16349.0137-.31006.12291-.36424.28921-.0722.22172.048.45839.26977.53064l4.61629 1.50418c.22171.0722.45839-.0481.53064-.26977.0722-.22172-.048-.4584-.26977-.53064L7.595 22.6347c-.0554-.0181-.11192-.024-.16641-.0194zm51.31484.018c-.0545-.005-.11078.001-.16623.0194l-4.61736 1.50092c-.22178.0721-.34223.30869-.27014.53046.0721.22177.30868.34223.53046.27014l4.61719-1.50092c.22178-.0721.3424-.30869.27032-.53046-.0541-.16633-.20077-.2757-.36424-.28957zM6.75607 25.36479c-.1961-.002-.37196.13412-.41438.33371-.0485.2281.0962.45073.32427.49922l1.99777.42455c.2281.0485.45072-.0962.49921-.32427.0485-.22811-.0962-.45074-.32427-.49922l-1.99759-.42455c-.0285-.006-.057-.009-.085-.009zm52.65462.004c-.028.00023-.0563.004-.0848.009l-1.99778.42437c-.2281.0485-.37271.27093-.32426.49904.0485.2281.2711.3729.49921.32445l1.99759-.42437c.2281-.0485.3729-.27111.32445-.49922-.0424-.19959-.21829-.33537-.41437-.33371zM6.24704 28.13046c-.1952.0187-.35587.17185-.37731.37477-.0245.2319.14232.43838.37422.46288l4.82829.51048c.2319.0245.43838-.1425.46288-.37441.0245-.2319-.1425-.43838-.37441-.46288l-4.82828-.51048c-.029-.003-.0575-.003-.0854-.00035zm53.6763.0363c-.0279-.003-.0566-.003-.0856.00035l-4.82883.50394c-.23194.0242-.39914.2304-.37496.46233.0242.23194.2304.39918.46234.37496l4.82883-.50394c.23193-.0242.39914-.2304.37496-.46234-.0212-.20294-.1816-.35634-.37678-.37532zM6.16529 30.96149c-.2332 0-.42091.18772-.42091.42092 0 .23319.18771.42091.42091.42091h2.04228c.23319 0 .4211-.18772.4211-.42091 0-.2332-.18791-.42092-.4211-.42092zm51.79298 0c-.23319 0-.42092.18772-.42092.42092.00001.23319.18773.42091.42092.42091h2.04228c.23319 0 .42092-.18772.42092-.42091 0-.2332-.18773-.42092-.42092-.42092zM11.15508 33.2561c-.0279-.003-.0564-.003-.0854.00035l-4.82902.50394c-.23194.0242-.39913.2304-.37495.46233.0242.23194.2304.39918.46233.37496l4.82902-.50394c.23194-.0242.39913-.2304.37495-.46234-.0212-.20294-.18177-.35634-.37695-.37531zm43.85314.0298c-.19521.0187-.35588.17186-.37732.37478-.0245.2319.14233.43838.37423.46288l4.82829.51048c.23191.0245.43837-.14251.46288-.37441.0245-.2319-.14251-.43838-.37441-.46288l-4.8281-.51048c-.029-.003-.0577-.003-.0856-.00035zm-46.2602 2.8436c-.028.00024-.0565.003-.085.009l-1.99777.42436c-.22811.0485-.37271.27111-.32427.49922.0485.22811.27111.37272.49922.32427l1.99777-.42419c.2281-.0485.37271-.27111.32426-.49921-.0424-.1996-.2181-.33537-.41419-.33372zm48.66925.004c-.19609-.002-.37177.13394-.41419.33353-.0485.2281.096.45074.32409.49922l1.99777.42455c.22809.0485.45073-.096.49921-.32409.0485-.2281-.0962-.45092-.32426-.4994l-1.9976-.42455c-.0285-.006-.057-.009-.085-.009zm-45.30519 1.65787c-.0545-.005-.11077.001-.16622.0194L7.3285 39.31168c-.22178.0721-.34223.30869-.27014.53046.0721.22178.30868.34222.53046.27014l4.61719-1.50092c.22178-.0721.34241-.30869.27032-.53046-.0541-.16633-.20077-.2757-.36425-.28957zm41.93713.0149c-.16349.0137-.31005.12292-.36423.28921-.0722.22173.048.4584.26977.53065l4.61628 1.50418c.22172.0722.4584-.0481.53064-.26977.0723-.22172-.048-.4584-.26977-.53065l-4.61628-1.50418c-.0554-.0181-.11191-.024-.16641-.0194zm-43.69909 3.27251c-.0547.001-.11006.0128-.16332.0365l-1.86587.83075c-.21304.0948-.30812.34267-.21328.55571.0949.21304.34268.30812.55571.21328l1.86589-.83058c.21303-.0948.30811-.34267.21327-.55571-.0711-.15978-.22837-.25323-.3924-.24997zm45.45888.016c-.16403-.004-.32133.0899-.39258.24961-.095.21297-.00006.4609.21291.55589l1.86515.83202c.21297.095.46091.00006.5559-.21291.095-.21297.00006-.4609-.21291-.55589l-1.86515-.83203c-.0532-.0238-.10864-.0356-.16332-.0367zm-41.82613.91214c-.0808-.006-.16424.012-.23998.0558L9.53826 44.4903c-.20195.1166-.27065.37302-.15405.57497.1166.20195.37302.27065.57497.15405l4.20463-2.4274c.20195-.1166.27064-.3732.15405-.57515-.0729-.12622-.2003-.20041-.33499-.20982zm38.20028 0c-.13469.009-.26229.0836-.33517.20982-.1166.20195-.0479.45855.15405.57515l4.20463 2.4274c.20196.1166.45855.0479.57515-.15405.1166-.20195.0479-.45837-.15404-.57497l-4.20482-2.42758c-.0757-.0437-.15899-.0614-.2398-.0558zm-39.24903 3.56244c-.081.003-.16211.0291-.2329.0805l-1.65296 1.19935c-.18875.13694-.2305.39912-.0936.58787.13695.18875.39912.2305.58787.0935l1.65314-1.19935c.18877-.13693.23051-.39911.0936-.58786-.0856-.11797-.22022-.17866-.35516-.17404zm40.28761.0142c-.13494-.005-.26948.0558-.35515.17367-.13708.18865-.0955.45098.0932.58805l1.65224 1.20044c.18866.13707.4508.0955.58787-.0932.13707-.18866.0956-.4508-.093-.58787l-1.65224-1.20044c-.0707-.0514-.15193-.0778-.23289-.0807zm-36.54387.14533c-.10743-.006-.21702.0298-.30374.10773l-3.61076 3.2458c-.17342.15589-.18751.42098-.0316.59441.15589.17342.42097.1875.5944.0316l3.61077-3.2458c.17342-.15589.18751-.42098.0316-.59441-.0779-.0867-.18322-.13361-.29067-.13933zm32.80012.0116c-.10745.006-.21283.0525-.29084.13915-.15603.17332-.14207.43839.0312.59441l3.60841 3.24834c.17332.15604.43857.14208.59459-.0312.15603-.17331.14207-.43839-.0312-.5944l-3.6086-3.24835c-.0867-.078-.19611-.11355-.30356-.10791zm-29.37464 3.08358c-.13493-.005-.2696.0554-.35534.1733l-2.85613 3.92614c-.13719.18858-.0959.45087.0926.58805.18857.13719.45087.0959.58805-.0927l2.85613-3.92614c.13718-.18857.0959-.45086-.0926-.58805-.0707-.0514-.15175-.0778-.23271-.0806zm25.93573.0176c-.081.003-.16211.0289-.2329.0803-.18875.13694-.23048.39911-.0936.58787l2.85086 3.92995c.13693.18876.39911.2305.58787.0936.18876-.13693.23049-.3991.0936-.58786l-2.85086-3.92996c-.0856-.11797-.22004-.17846-.35498-.17385zm-29.6228.6064c-.10745.006-.21282.0525-.29084.13915l-1.36649 1.51763c-.15605.1733-.14223.43855.0311.59459.1733.15604.43837.14205.5944-.0313l1.36666-1.51762c.15606-.1733.14206-.43856-.0312-.59459-.0867-.078-.19611-.11354-.30357-.10791zm33.33076.002c-.10745-.006-.21691.0299-.30356.10791-.17333.156-.18726.42108-.0313.5944l1.3663 1.51799c.15602.17333.42109.18726.59442.0312.17332-.15601.18726-.42126.0312-.59459l-1.36631-1.5178c-.078-.0867-.18339-.13351-.29084-.13916zm-25.65524 1.68366c-.16403-.004-.32114.0899-.39239.24961l-1.97816 4.43389c-.095.21297-.00005.46089.21292.5559.21296.095.46089.00005.55589-.21291l1.97815-4.4339c.095-.21296.00005-.46089-.21292-.55589-.0532-.0238-.10881-.0356-.16349-.0367zm17.95556.0122c-.0547.001-.11023.0128-.1635.0365-.21297.0947-.30836.34244-.21363.55553l1.97196 4.43662c.0947.21297.34262.30836.55571.21364.21298-.0947.30836-.34244.21364-.55553l-1.97197-4.43662c-.071-.15973-.22818-.25329-.39221-.25015zM20.61581 52.5046c-.13468.009-.26212.0836-.33498.20982l-1.02115 1.76869c-.11659.20195-.0479.45837.15406.57497.20195.1166.45837.0479.57496-.15405l1.02115-1.76869c.11659-.20195.0479-.45837-.15406-.57497-.0757-.0437-.15916-.0614-.23998-.0558zm24.93421 0c-.0808-.006-.16406.0121-.23979.0558-.20195.1166-.27065.37302-.15405.57497l1.02114 1.76869c.1166.20195.37302.27064.57496.15405.20196-.1166.27066-.37302.15406-.57497l-1.02114-1.76869c-.0729-.12622-.20049-.20041-.33518-.20982zm-17.0545.0634c-.19609-.002-.3718.13394-.41419.33354l-1.00897 4.74926c-.0485.2281.0962.45076.32427.49921.22811.0485.45076-.0962.49922-.32427l1.00896-4.74926c.0485-.2281-.0962-.45076-.32427-.49921-.0285-.006-.057-.009-.085-.009zm9.1599.003c-.028.00022-.0563.003-.0848.009-.22814.0483-.37294.27071-.32465.49885l1.00553 4.74999c.0483.22814.27088.37293.49903.32464.22814-.0483.37293-.27089.32464-.49903l-1.0057-4.74965c-.0423-.19963-.21793-.33543-.41402-.33391zm-4.5725.47905c-.23319 0-.42092.18772-.42092.42092v4.85517c0 .2332.18773.42092.42092.42092.2332 0 .42092-.18772.42092-.42092v-4.85517c0-.2332-.18772-.42092-.42092-.42092zm-7.72657 1.56886c-.16347.0139-.31017.12324-.36423.28957l-.63129 1.94236c-.0721.22178.0484.45837.27014.53047.22177.0721.45836-.0486.53046-.27032l.63128-1.94218c.0721-.22177-.0484-.45836-.27013-.53046-.0554-.018-.11173-.024-.16623-.0194zm15.44987.001c-.0545-.005-.11078.001-.16622.0193-.22178.0721-.34238.30868-.27033.53047l.63111 1.94235c.0721.22179.30868.3422.53046.27014.22178-.0721.34238-.3085.27032-.53028l-.63128-1.94236c-.0541-.16634-.20058-.27568-.36406-.28957zm-10.36543 1.08181c-.1952.0188-.356.17203-.37732.37496l-.21346 2.03119c-.0244.23192.14268.43812.3746.46252.23192.0244.4383-.14268.4627-.3746l.21345-2.03101c.0244-.23192-.14268-.4383-.37458-.4627-.029-.003-.0575-.003-.0854-.00035zm5.26736.002c-.0279-.003-.0566-.003-.0856.00035-.23193.0242-.39917.2304-.37495.46233l.21218 2.03138c.0242.23193.2304.399.46234.37478.23193-.0242.39918-.23041.37496-.46234l-.212-2.03119c-.0212-.20295-.18178-.35637-.37697-.37533z" paint-order="markers stroke fill"/>
28
- <path d="m469.09621 100.6068-65.50955 38.06124-41.41979 65.20654 60.59382-44.88117z" filter="url(#f)" opacity=".40900005" paint-order="markers stroke fill" transform="translate(-112.09544 -20.8224) scale(.35154)"/>
29
- <path fill="#ff5150" d="m36.3834003 34.83806178-6.60095092-6.91272438 23.41607429-15.75199774z" paint-order="markers stroke fill"/>
30
- <path fill="#f1f1f1" d="m36.38339038 34.83805895-6.60095092-6.91272438-16.81512624 22.66471911z" paint-order="markers stroke fill"/>
31
- <path d="m12.96732 50.59006 23.41607-15.75201 16.81513-22.66472z" opacity=".243"/>
32
- </svg>
@@ -1,11 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
- <title>share</title>
4
- <g id="share" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
5
- <g id="Group" transform="translate(3.500000, 2.000000)" stroke="#000000">
6
- <path d="M6.3,4 L8.1,4 C8.59705627,4 9,4.39796911 9,4.88888889 L9,11.1111111 C9,11.6020309 8.59705627,12 8.1,12 L0.9,12 C0.402943725,12 0,11.6020309 0,11.1111111 L0,4.88888889 C0,4.39796911 0.402943725,4 0.9,4 L2.7,4 L2.7,4" id="Path"></path>
7
- <line x1="4.5" y1="7" x2="4.5" y2="-1.94289029e-16" id="Path-2"></line>
8
- <polyline id="Path-3" points="2.5 2 4.5 0 6.5 2"></polyline>
9
- </g>
10
- </g>
11
- </svg>