@atproto/oauth-provider 0.5.2 → 0.6.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 (310) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/account/account-manager.d.ts +7 -5
  3. package/dist/account/account-manager.d.ts.map +1 -1
  4. package/dist/account/account-manager.js +34 -25
  5. package/dist/account/account-manager.js.map +1 -1
  6. package/dist/account/account-store.d.ts +7 -0
  7. package/dist/account/account-store.d.ts.map +1 -1
  8. package/dist/account/account-store.js.map +1 -1
  9. package/dist/account/account.d.ts +1 -11
  10. package/dist/account/account.d.ts.map +1 -1
  11. package/dist/account/{sign-up-data.d.ts → sign-up-input.d.ts} +3 -3
  12. package/dist/account/sign-up-input.d.ts.map +1 -0
  13. package/dist/account/{sign-up-data.js → sign-up-input.js} +3 -3
  14. package/dist/account/sign-up-input.js.map +1 -0
  15. package/dist/assets/assets-middleware.d.ts +2 -0
  16. package/dist/assets/assets-middleware.d.ts.map +1 -1
  17. package/dist/assets/assets-middleware.js +12 -14
  18. package/dist/assets/assets-middleware.js.map +1 -1
  19. package/dist/lib/csp/index.d.ts +5 -6
  20. package/dist/lib/csp/index.d.ts.map +1 -1
  21. package/dist/lib/csp/index.js +14 -11
  22. package/dist/lib/csp/index.js.map +1 -1
  23. package/dist/lib/hcaptcha.d.ts +5 -3
  24. package/dist/lib/hcaptcha.d.ts.map +1 -1
  25. package/dist/lib/hcaptcha.js +7 -4
  26. package/dist/lib/hcaptcha.js.map +1 -1
  27. package/dist/lib/html/build-document.d.ts +2 -2
  28. package/dist/lib/html/build-document.d.ts.map +1 -1
  29. package/dist/lib/html/build-document.js +11 -7
  30. package/dist/lib/html/build-document.js.map +1 -1
  31. package/dist/lib/html/html.d.ts.map +1 -1
  32. package/dist/lib/html/html.js +10 -13
  33. package/dist/lib/html/html.js.map +1 -1
  34. package/dist/lib/html/util.d.ts +0 -1
  35. package/dist/lib/html/util.d.ts.map +1 -1
  36. package/dist/lib/html/util.js +0 -4
  37. package/dist/lib/html/util.js.map +1 -1
  38. package/dist/lib/http/response.d.ts +3 -1
  39. package/dist/lib/http/response.d.ts.map +1 -1
  40. package/dist/lib/http/response.js +3 -0
  41. package/dist/lib/http/response.js.map +1 -1
  42. package/dist/lib/http/security-headers.d.ts +48 -0
  43. package/dist/lib/http/security-headers.d.ts.map +1 -0
  44. package/dist/lib/http/security-headers.js +62 -0
  45. package/dist/lib/http/security-headers.js.map +1 -0
  46. package/dist/lib/util/type.d.ts +8 -0
  47. package/dist/lib/util/type.d.ts.map +1 -1
  48. package/dist/lib/util/type.js.map +1 -1
  49. package/dist/oauth-hooks.d.ts +4 -25
  50. package/dist/oauth-hooks.d.ts.map +1 -1
  51. package/dist/oauth-provider.js +2 -2
  52. package/dist/oauth-provider.js.map +1 -1
  53. package/dist/output/backend-data.d.ts +4 -0
  54. package/dist/output/backend-data.d.ts.map +1 -0
  55. package/dist/output/backend-data.js +19 -0
  56. package/dist/output/backend-data.js.map +1 -0
  57. package/dist/output/build-authorize-data.d.ts +3 -19
  58. package/dist/output/build-authorize-data.d.ts.map +1 -1
  59. package/dist/output/build-authorize-data.js.map +1 -1
  60. package/dist/output/build-customization-data.d.ts +11 -18
  61. package/dist/output/build-customization-data.d.ts.map +1 -1
  62. package/dist/output/build-customization-data.js +1 -1
  63. package/dist/output/build-customization-data.js.map +1 -1
  64. package/dist/output/build-error-data.d.ts +3 -0
  65. package/dist/output/build-error-data.d.ts.map +1 -0
  66. package/dist/output/build-error-data.js +10 -0
  67. package/dist/output/build-error-data.js.map +1 -0
  68. package/dist/output/build-error-payload.d.ts +2 -1
  69. package/dist/output/build-error-payload.d.ts.map +1 -1
  70. package/dist/output/build-error-payload.js.map +1 -1
  71. package/dist/output/output-manager.d.ts +10 -4
  72. package/dist/output/output-manager.d.ts.map +1 -1
  73. package/dist/output/output-manager.js +68 -39
  74. package/dist/output/output-manager.js.map +1 -1
  75. package/dist/output/send-web-page.d.ts +6 -10
  76. package/dist/output/send-web-page.d.ts.map +1 -1
  77. package/dist/output/send-web-page.js +27 -47
  78. package/dist/output/send-web-page.js.map +1 -1
  79. package/dist/signer/signed-token-payload.d.ts +3 -3
  80. package/dist/signer/signer.d.ts +2 -2
  81. package/package.json +7 -40
  82. package/src/account/account-manager.ts +55 -34
  83. package/src/account/account-store.ts +8 -0
  84. package/src/account/account.ts +1 -14
  85. package/src/account/{sign-up-data.ts → sign-up-input.ts} +2 -2
  86. package/src/assets/assets-middleware.ts +11 -17
  87. package/src/lib/csp/index.ts +16 -13
  88. package/src/lib/hcaptcha.ts +10 -7
  89. package/src/lib/html/build-document.ts +15 -8
  90. package/src/lib/html/html.ts +11 -18
  91. package/src/lib/html/util.ts +0 -4
  92. package/src/lib/http/response.ts +9 -1
  93. package/src/lib/http/security-headers.ts +91 -0
  94. package/src/lib/util/type.ts +18 -0
  95. package/src/oauth-hooks.ts +4 -25
  96. package/src/oauth-provider.ts +2 -2
  97. package/src/output/backend-data.ts +18 -0
  98. package/src/output/build-authorize-data.ts +3 -26
  99. package/src/output/build-customization-data.ts +2 -13
  100. package/src/output/build-error-data.ts +8 -0
  101. package/src/output/build-error-payload.ts +4 -2
  102. package/src/output/output-manager.ts +86 -47
  103. package/src/output/send-web-page.ts +29 -58
  104. package/tsconfig.backend.json +1 -2
  105. package/tsconfig.backend.tsbuildinfo +1 -1
  106. package/tsconfig.json +1 -5
  107. package/.linguirc +0 -57
  108. package/dist/account/sign-up-data.d.ts.map +0 -1
  109. package/dist/account/sign-up-data.js.map +0 -1
  110. package/dist/assets/app/bundle-manifest.json +0 -614
  111. package/dist/assets/app/index-DZHZ9kCP.js +0 -36
  112. package/dist/assets/app/index-DZHZ9kCP.js.map +0 -1
  113. package/dist/assets/app/main-B_dNxQo_.js +0 -4
  114. package/dist/assets/app/main-B_dNxQo_.js.map +0 -1
  115. package/dist/assets/app/main-Dr6y26KY.css +0 -3
  116. package/dist/assets/app/main-Dr6y26KY.js +0 -306
  117. package/dist/assets/app/main-Dr6y26KY.js.map +0 -1
  118. package/dist/assets/app/messages-6_mYuGzB.js +0 -4
  119. package/dist/assets/app/messages-6_mYuGzB.js.map +0 -1
  120. package/dist/assets/app/messages-7wdeBTpD.js +0 -4
  121. package/dist/assets/app/messages-7wdeBTpD.js.map +0 -1
  122. package/dist/assets/app/messages-B-YFoWKc.js +0 -4
  123. package/dist/assets/app/messages-B-YFoWKc.js.map +0 -1
  124. package/dist/assets/app/messages-B10DUOE-.js +0 -4
  125. package/dist/assets/app/messages-B10DUOE-.js.map +0 -1
  126. package/dist/assets/app/messages-B4AwFEeZ.js +0 -4
  127. package/dist/assets/app/messages-B4AwFEeZ.js.map +0 -1
  128. package/dist/assets/app/messages-BDP8MyEC.js +0 -4
  129. package/dist/assets/app/messages-BDP8MyEC.js.map +0 -1
  130. package/dist/assets/app/messages-BIS87lxQ.js +0 -4
  131. package/dist/assets/app/messages-BIS87lxQ.js.map +0 -1
  132. package/dist/assets/app/messages-BI_Wbjdt.js +0 -4
  133. package/dist/assets/app/messages-BI_Wbjdt.js.map +0 -1
  134. package/dist/assets/app/messages-BMAouhRx.js +0 -4
  135. package/dist/assets/app/messages-BMAouhRx.js.map +0 -1
  136. package/dist/assets/app/messages-BdckMnJj.js +0 -4
  137. package/dist/assets/app/messages-BdckMnJj.js.map +0 -1
  138. package/dist/assets/app/messages-BgBLzc46.js +0 -4
  139. package/dist/assets/app/messages-BgBLzc46.js.map +0 -1
  140. package/dist/assets/app/messages-BobD78yK.js +0 -4
  141. package/dist/assets/app/messages-BobD78yK.js.map +0 -1
  142. package/dist/assets/app/messages-BtThT9UZ.js +0 -4
  143. package/dist/assets/app/messages-BtThT9UZ.js.map +0 -1
  144. package/dist/assets/app/messages-BwKHkbeh.js +0 -4
  145. package/dist/assets/app/messages-BwKHkbeh.js.map +0 -1
  146. package/dist/assets/app/messages-C417YUvA.js +0 -4
  147. package/dist/assets/app/messages-C417YUvA.js.map +0 -1
  148. package/dist/assets/app/messages-C4CxO4bO.js +0 -4
  149. package/dist/assets/app/messages-C4CxO4bO.js.map +0 -1
  150. package/dist/assets/app/messages-C5vd04e6.js +0 -4
  151. package/dist/assets/app/messages-C5vd04e6.js.map +0 -1
  152. package/dist/assets/app/messages-CAri2Wnz.js +0 -4
  153. package/dist/assets/app/messages-CAri2Wnz.js.map +0 -1
  154. package/dist/assets/app/messages-CPtWTZeG.js +0 -4
  155. package/dist/assets/app/messages-CPtWTZeG.js.map +0 -1
  156. package/dist/assets/app/messages-CiaM5zm8.js +0 -4
  157. package/dist/assets/app/messages-CiaM5zm8.js.map +0 -1
  158. package/dist/assets/app/messages-CkL-L2R6.js +0 -4
  159. package/dist/assets/app/messages-CkL-L2R6.js.map +0 -1
  160. package/dist/assets/app/messages-Cy_4XLNe.js +0 -4
  161. package/dist/assets/app/messages-Cy_4XLNe.js.map +0 -1
  162. package/dist/assets/app/messages-D5_ad-Eo.js +0 -4
  163. package/dist/assets/app/messages-D5_ad-Eo.js.map +0 -1
  164. package/dist/assets/app/messages-DChMl9mT.js +0 -4
  165. package/dist/assets/app/messages-DChMl9mT.js.map +0 -1
  166. package/dist/assets/app/messages-DWX-DIfv.js +0 -4
  167. package/dist/assets/app/messages-DWX-DIfv.js.map +0 -1
  168. package/dist/assets/app/messages-DgfsOphe.js +0 -4
  169. package/dist/assets/app/messages-DgfsOphe.js.map +0 -1
  170. package/dist/assets/app/messages-Dj5B_DR6.js +0 -4
  171. package/dist/assets/app/messages-Dj5B_DR6.js.map +0 -1
  172. package/dist/assets/app/messages-Dwzqo4eA.js +0 -4
  173. package/dist/assets/app/messages-Dwzqo4eA.js.map +0 -1
  174. package/dist/assets/app/messages-ESCIXJR7.js +0 -4
  175. package/dist/assets/app/messages-ESCIXJR7.js.map +0 -1
  176. package/dist/assets/app/messages-dglB2edb.js +0 -4
  177. package/dist/assets/app/messages-dglB2edb.js.map +0 -1
  178. package/dist/assets/app/messages-e_ClRrWc.js +0 -4
  179. package/dist/assets/app/messages-e_ClRrWc.js.map +0 -1
  180. package/dist/assets/app/messages-evvDxmrP.js +0 -4
  181. package/dist/assets/app/messages-evvDxmrP.js.map +0 -1
  182. package/dist/assets/app/messages-pPbdLb5B.js +0 -4
  183. package/dist/assets/app/messages-pPbdLb5B.js.map +0 -1
  184. package/dist/assets/app/messages-tJv8gHL2.js +0 -4
  185. package/dist/assets/app/messages-tJv8gHL2.js.map +0 -1
  186. package/dist/assets/app/messages-vLRVEw96.js +0 -4
  187. package/dist/assets/app/messages-vLRVEw96.js.map +0 -1
  188. package/dist/assets/asset.d.ts +0 -9
  189. package/dist/assets/asset.d.ts.map +0 -1
  190. package/dist/assets/asset.js +0 -3
  191. package/dist/assets/asset.js.map +0 -1
  192. package/dist/assets/index.d.ts +0 -5
  193. package/dist/assets/index.d.ts.map +0 -1
  194. package/dist/assets/index.js +0 -78
  195. package/dist/assets/index.js.map +0 -1
  196. package/rollup.config.js +0 -98
  197. package/src/assets/app/app.tsx +0 -43
  198. package/src/assets/app/backend-data.ts +0 -27
  199. package/src/assets/app/backend-types.ts +0 -66
  200. package/src/assets/app/components/forms/button-toggle-visibility.tsx +0 -43
  201. package/src/assets/app/components/forms/button.tsx +0 -60
  202. package/src/assets/app/components/forms/fieldset.tsx +0 -55
  203. package/src/assets/app/components/forms/form-card-async.tsx +0 -103
  204. package/src/assets/app/components/forms/form-card.tsx +0 -49
  205. package/src/assets/app/components/forms/input-checkbox.tsx +0 -78
  206. package/src/assets/app/components/forms/input-container.tsx +0 -107
  207. package/src/assets/app/components/forms/input-email-address.tsx +0 -65
  208. package/src/assets/app/components/forms/input-new-password.tsx +0 -62
  209. package/src/assets/app/components/forms/input-password.tsx +0 -87
  210. package/src/assets/app/components/forms/input-text.tsx +0 -82
  211. package/src/assets/app/components/forms/input-token.tsx +0 -94
  212. package/src/assets/app/components/forms/wizard-card.tsx +0 -116
  213. package/src/assets/app/components/layouts/layout-title-page.tsx +0 -77
  214. package/src/assets/app/components/layouts/layout-welcome.tsx +0 -73
  215. package/src/assets/app/components/utils/account-identifier.tsx +0 -23
  216. package/src/assets/app/components/utils/account-image.tsx +0 -33
  217. package/src/assets/app/components/utils/admonition.tsx +0 -52
  218. package/src/assets/app/components/utils/client-name.tsx +0 -45
  219. package/src/assets/app/components/utils/error-card.tsx +0 -93
  220. package/src/assets/app/components/utils/error-message.tsx +0 -88
  221. package/src/assets/app/components/utils/help-card.tsx +0 -46
  222. package/src/assets/app/components/utils/icons.tsx +0 -88
  223. package/src/assets/app/components/utils/link-anchor.tsx +0 -28
  224. package/src/assets/app/components/utils/link-title.tsx +0 -26
  225. package/src/assets/app/components/utils/multi-lang-string.tsx +0 -56
  226. package/src/assets/app/components/utils/password-strength-label.tsx +0 -37
  227. package/src/assets/app/components/utils/password-strength-meter.tsx +0 -58
  228. package/src/assets/app/components/utils/url-viewer.tsx +0 -73
  229. package/src/assets/app/cookies.ts +0 -11
  230. package/src/assets/app/hooks/use-api.ts +0 -178
  231. package/src/assets/app/hooks/use-async-action.ts +0 -120
  232. package/src/assets/app/hooks/use-bound-dispatch.ts +0 -5
  233. package/src/assets/app/hooks/use-browser-color-scheme.ts +0 -31
  234. package/src/assets/app/hooks/use-csrf-token.ts +0 -5
  235. package/src/assets/app/hooks/use-random-string.ts +0 -37
  236. package/src/assets/app/hooks/use-stepper.ts +0 -87
  237. package/src/assets/app/index.html +0 -182
  238. package/src/assets/app/lib/api.ts +0 -289
  239. package/src/assets/app/lib/clsx.ts +0 -6
  240. package/src/assets/app/lib/json-client.ts +0 -94
  241. package/src/assets/app/lib/password.ts +0 -98
  242. package/src/assets/app/lib/ref.ts +0 -17
  243. package/src/assets/app/lib/util.ts +0 -13
  244. package/src/assets/app/locales/an/messages.po +0 -490
  245. package/src/assets/app/locales/ast/messages.po +0 -490
  246. package/src/assets/app/locales/ca/messages.po +0 -490
  247. package/src/assets/app/locales/da/messages.po +0 -490
  248. package/src/assets/app/locales/de/messages.po +0 -490
  249. package/src/assets/app/locales/el/messages.po +0 -490
  250. package/src/assets/app/locales/en/messages.po +0 -490
  251. package/src/assets/app/locales/en-GB/messages.po +0 -490
  252. package/src/assets/app/locales/es/messages.po +0 -490
  253. package/src/assets/app/locales/eu/messages.po +0 -490
  254. package/src/assets/app/locales/fi/messages.po +0 -490
  255. package/src/assets/app/locales/fr/messages.po +0 -490
  256. package/src/assets/app/locales/ga/messages.po +0 -490
  257. package/src/assets/app/locales/gl/messages.po +0 -490
  258. package/src/assets/app/locales/hi/messages.po +0 -490
  259. package/src/assets/app/locales/hu/messages.po +0 -490
  260. package/src/assets/app/locales/ia/messages.po +0 -490
  261. package/src/assets/app/locales/id/messages.po +0 -490
  262. package/src/assets/app/locales/it/messages.po +0 -490
  263. package/src/assets/app/locales/ja/messages.po +0 -490
  264. package/src/assets/app/locales/km/messages.po +0 -490
  265. package/src/assets/app/locales/ko/messages.po +0 -490
  266. package/src/assets/app/locales/load.ts +0 -8
  267. package/src/assets/app/locales/locale-context.ts +0 -19
  268. package/src/assets/app/locales/locale-provider.tsx +0 -112
  269. package/src/assets/app/locales/locale-selector.tsx +0 -58
  270. package/src/assets/app/locales/locales.ts +0 -168
  271. package/src/assets/app/locales/ne/messages.po +0 -490
  272. package/src/assets/app/locales/nl/messages.po +0 -490
  273. package/src/assets/app/locales/pl/messages.po +0 -490
  274. package/src/assets/app/locales/pt-BR/messages.po +0 -490
  275. package/src/assets/app/locales/ro/messages.po +0 -490
  276. package/src/assets/app/locales/ru/messages.po +0 -490
  277. package/src/assets/app/locales/sv/messages.po +0 -490
  278. package/src/assets/app/locales/th/messages.po +0 -490
  279. package/src/assets/app/locales/tr/messages.po +0 -490
  280. package/src/assets/app/locales/uk/messages.po +0 -490
  281. package/src/assets/app/locales/vi/messages.po +0 -490
  282. package/src/assets/app/locales/zh-CN/messages.po +0 -490
  283. package/src/assets/app/locales/zh-HK/messages.po +0 -490
  284. package/src/assets/app/locales/zh-TW/messages.po +0 -490
  285. package/src/assets/app/main.css +0 -33
  286. package/src/assets/app/main.tsx +0 -44
  287. package/src/assets/app/views/authorize/accept/accept-form.tsx +0 -150
  288. package/src/assets/app/views/authorize/accept/accept-view.tsx +0 -70
  289. package/src/assets/app/views/authorize/authorize-view.tsx +0 -180
  290. package/src/assets/app/views/authorize/reset-password/reset-password-confirm-form.tsx +0 -88
  291. package/src/assets/app/views/authorize/reset-password/reset-password-request-form.tsx +0 -80
  292. package/src/assets/app/views/authorize/reset-password/reset-password-view.tsx +0 -127
  293. package/src/assets/app/views/authorize/sign-in/sign-in-form.tsx +0 -242
  294. package/src/assets/app/views/authorize/sign-in/sign-in-picker.tsx +0 -116
  295. package/src/assets/app/views/authorize/sign-in/sign-in-view.tsx +0 -145
  296. package/src/assets/app/views/authorize/sign-up/sign-up-account-form.tsx +0 -142
  297. package/src/assets/app/views/authorize/sign-up/sign-up-disclaimer.tsx +0 -51
  298. package/src/assets/app/views/authorize/sign-up/sign-up-handle-form.tsx +0 -287
  299. package/src/assets/app/views/authorize/sign-up/sign-up-hcaptcha-form.tsx +0 -108
  300. package/src/assets/app/views/authorize/sign-up/sign-up-view.tsx +0 -158
  301. package/src/assets/app/views/authorize/welcome/welcome-view.tsx +0 -56
  302. package/src/assets/app/views/error/error-view.tsx +0 -31
  303. package/src/assets/asset.ts +0 -9
  304. package/src/assets/index.ts +0 -86
  305. package/tailwind.config.js +0 -31
  306. package/tsconfig.frontend.json +0 -11
  307. package/tsconfig.frontend.tsbuildinfo +0 -1
  308. package/tsconfig.tools.json +0 -8
  309. package/tsconfig.tools.tsbuildinfo +0 -1
  310. package/vite.config.mjs +0 -16
@@ -1,107 +0,0 @@
1
- import { JSX, ReactNode, useState } from 'react'
2
- import { clsx } from '../../lib/clsx.ts'
3
- import { Override } from '../../lib/util.ts'
4
-
5
- export type InputContainerProps = Override<
6
- JSX.IntrinsicElements['div'],
7
- {
8
- icon: ReactNode
9
- append?: ReactNode
10
- bellow?: ReactNode
11
- }
12
- >
13
-
14
- export function InputContainer({
15
- icon,
16
- append,
17
- bellow,
18
-
19
- // div
20
- className,
21
- children,
22
- onFocus,
23
- onBlur,
24
- ...props
25
- }: InputContainerProps) {
26
- const [hasFocus, setHasFocus] = useState(false)
27
-
28
- return (
29
- <div
30
- {...props}
31
- onFocus={(event) => {
32
- onFocus?.(event)
33
- if (!event.defaultPrevented) setHasFocus(true)
34
- }}
35
- onBlur={(event) => {
36
- onBlur?.(event)
37
- if (!event.defaultPrevented) setHasFocus(false)
38
- }}
39
- className={clsx(
40
- // Layout
41
- 'min-h-12',
42
- 'max-w-full',
43
- 'overflow-hidden',
44
- // Border
45
- 'rounded-lg',
46
- className,
47
- )}
48
- >
49
- <div
50
- className={clsx(
51
- // Layout
52
- 'px-1',
53
- 'w-full min-h-12',
54
- 'flex items-center justify-stretch',
55
- // Border
56
- 'rounded-lg',
57
- bellow ? 'rounded-br-none rounded-bl-none' : undefined,
58
- 'outline-none',
59
- 'border-solid border-2 border-transparent',
60
- 'focus:border-brand has-[:focus]:border-brand',
61
- 'hover:border-gray-400 hover:focus:border-gray-400',
62
- 'dark:hover:border-gray-500 dark:hover:focus:border-gray-500',
63
- // Background
64
- 'bg-gray-100 focus:bg-slate-200 has-[:focus]:bg-slate-200',
65
- 'dark:bg-slate-800 dark:focus:bg-slate-700 dark:has-[:focus]:bg-slate-700',
66
- // Font
67
- 'text-slate-600 dark:text-slate-300',
68
- 'accent-brand',
69
- )}
70
- >
71
- {icon && (
72
- <div
73
- className={clsx(
74
- 'shrink-0 grow-0',
75
- 'mx-1',
76
- hasFocus ? 'text-brand' : 'text-slate-500',
77
- )}
78
- >
79
- {icon}
80
- </div>
81
- )}
82
-
83
- {children}
84
-
85
- <div className="ml-1 grow-0 shrink-0 flex items-center">{append}</div>
86
- </div>
87
- {bellow && (
88
- <div
89
- className={clsx(
90
- // Layout
91
- 'px-3 py-2 space-x-2',
92
- 'flex flex-row items-center gap-1',
93
- // Border
94
- 'rounded-br-2 rounded-bl-2',
95
- // Background
96
- 'bg-gray-200 dark:bg-slate-700',
97
- // Font
98
- 'text-gray-700 dark:text-gray-300',
99
- 'text-sm italic',
100
- )}
101
- >
102
- {bellow}
103
- </div>
104
- )}
105
- </div>
106
- )
107
- }
@@ -1,65 +0,0 @@
1
- import { useLingui } from '@lingui/react/macro'
2
- import { ChangeEvent, useCallback, useState } from 'react'
3
- import { Override } from '../../lib/util.ts'
4
- import { AtSymbolIcon } from '../utils/icons.tsx'
5
- import { InputText, InputTextProps } from './input-text.tsx'
6
-
7
- export type InputEmailAddressProps = Override<
8
- Omit<InputTextProps, 'type'>,
9
- {
10
- onEmail?: (email: string | undefined) => void
11
- }
12
- >
13
-
14
- export function InputEmailAddress({
15
- onEmail,
16
-
17
- // InputTextProps
18
- autoCapitalize = 'none',
19
- autoComplete = 'email',
20
- autoCorrect = 'off',
21
- dir = 'auto',
22
- icon = <AtSymbolIcon className="w-5" />,
23
- onBlur,
24
- onChange,
25
- pattern = '^[^@]+@[^@]+\\.[^@]+$',
26
- spellCheck = 'false',
27
- value,
28
- defaultValue = value,
29
- title,
30
- ...props
31
- }: InputEmailAddressProps) {
32
- const { t } = useLingui()
33
- const [email, setEmail] = useState<string>(
34
- typeof defaultValue === 'string' ? defaultValue : '',
35
- )
36
-
37
- const doChange = useCallback(
38
- (event: ChangeEvent<HTMLInputElement>) => {
39
- const email = event.target.value.toLowerCase()
40
-
41
- setEmail(email)
42
- onChange?.(event)
43
- onEmail?.(event.target.validity.valid ? email : undefined)
44
- },
45
- [onChange, onEmail],
46
- )
47
-
48
- return (
49
- <InputText
50
- {...props}
51
- title={title ?? t`Email address`}
52
- type="email"
53
- autoCapitalize={autoCapitalize}
54
- autoCorrect={autoCorrect}
55
- dir={dir}
56
- spellCheck={spellCheck}
57
- icon={icon}
58
- pattern={pattern}
59
- autoComplete={autoComplete}
60
- value={email}
61
- onChange={doChange}
62
- onBlur={onBlur}
63
- />
64
- )
65
- }
@@ -1,62 +0,0 @@
1
- import { useLingui } from '@lingui/react/macro'
2
- import { ChangeEvent, useCallback, useState } from 'react'
3
- import { MIN_PASSWORD_LENGTH } from '../../lib/password.ts'
4
- import { Override } from '../../lib/util.ts'
5
- import { PasswordStrengthLabel } from '../utils/password-strength-label.tsx'
6
- import { PasswordStrengthMeter } from '../utils/password-strength-meter.tsx'
7
- import { InputPassword, InputPasswordProps } from './input-password.tsx'
8
-
9
- export type InputNewPasswordProps = Override<
10
- Omit<InputPasswordProps, 'value' | 'defaultValue'>,
11
- {
12
- password?: string
13
- onPassword?: (password: undefined | string) => void
14
- }
15
- >
16
-
17
- export function InputNewPassword({
18
- password: passwordInit = '',
19
- onPassword,
20
-
21
- // InputPasswordProps
22
- onChange,
23
- autoComplete = 'new-password',
24
- minLength = MIN_PASSWORD_LENGTH,
25
- ...props
26
- }: InputNewPasswordProps) {
27
- const { t } = useLingui()
28
- const [password, setPassword] = useState<string>(passwordInit)
29
-
30
- const doChange = useCallback(
31
- (event: ChangeEvent<HTMLInputElement>) => {
32
- const { value } = event.target
33
- onChange?.(event)
34
- if (event.defaultPrevented) return
35
- setPassword(value)
36
- onPassword?.(event.target.validity.valid ? value : undefined)
37
- },
38
- [onChange, onPassword],
39
- )
40
-
41
- return (
42
- <InputPassword
43
- {...props}
44
- placeholder={t`Enter a password`}
45
- aria-label={t`Enter your new password`}
46
- title={t`Password with at least ${MIN_PASSWORD_LENGTH} characters`}
47
- minLength={minLength}
48
- onChange={doChange}
49
- value={password}
50
- autoComplete={autoComplete}
51
- bellow={
52
- <>
53
- <PasswordStrengthMeter password={password} />
54
- <PasswordStrengthLabel
55
- className="grow-1 min-w-max text-xs text-gray-500 dark:text-gray-400"
56
- password={password}
57
- />
58
- </>
59
- }
60
- />
61
- )
62
- }
@@ -1,87 +0,0 @@
1
- import { useLingui } from '@lingui/react/macro'
2
- import { ChangeEvent, useCallback, useRef, useState } from 'react'
3
- import { mergeRefs } from '../../lib/ref.ts'
4
- import { Override } from '../../lib/util.ts'
5
- import { LockIcon } from '../utils/icons.tsx'
6
- import { ButtonToggleVisibility } from './button-toggle-visibility.tsx'
7
- import { InputText, InputTextProps } from './input-text.tsx'
8
-
9
- export type InputPasswordProps = Override<
10
- Omit<InputTextProps, 'type' | 'children'>,
11
- {
12
- autoHide?: boolean
13
- }
14
- >
15
-
16
- export function InputPassword({
17
- autoHide = true,
18
-
19
- // InputTextProps
20
- onBlur,
21
- onChange,
22
- append,
23
- autoComplete = 'current-password',
24
- icon = <LockIcon className="w-5" />,
25
- value,
26
- defaultValue = value,
27
- ref,
28
- title,
29
- dir = 'auto',
30
- autoCapitalize = 'none',
31
- autoCorrect = 'off',
32
- spellCheck = 'false',
33
- ...props
34
- }: InputPasswordProps) {
35
- const { t } = useLingui()
36
- const inputRef = useRef<HTMLInputElement>(null)
37
- const [visible, setVisible] = useState<boolean>(false)
38
- const [password, setPassword] = useState<string>(
39
- typeof defaultValue === 'string' ? defaultValue : '',
40
- )
41
-
42
- const doChange = useCallback(
43
- (event: ChangeEvent<HTMLInputElement>) => {
44
- onChange?.(event)
45
- setPassword(event.target.value)
46
- },
47
- [onChange],
48
- )
49
-
50
- return (
51
- <InputText
52
- {...props}
53
- title={title ?? t`Password`}
54
- ref={mergeRefs([ref, inputRef])}
55
- dir={dir}
56
- autoCapitalize={autoCapitalize}
57
- autoCorrect={autoCorrect}
58
- spellCheck={spellCheck}
59
- icon={icon}
60
- onBlur={
61
- autoHide
62
- ? (event) => {
63
- onBlur?.(event)
64
- if (!event.defaultPrevented) setVisible(false)
65
- }
66
- : onBlur
67
- }
68
- value={password}
69
- onChange={doChange}
70
- type={visible ? 'text' : 'password'}
71
- autoComplete={autoComplete}
72
- append={
73
- <>
74
- <ButtonToggleVisibility
75
- className="m-1"
76
- visible={visible}
77
- toggleVisible={() => {
78
- setVisible((prev) => !prev)
79
- inputRef.current?.focus()
80
- }}
81
- />
82
- {append}
83
- </>
84
- }
85
- />
86
- )
87
- }
@@ -1,82 +0,0 @@
1
- import { JSX, ReactNode, useContext, useRef } from 'react'
2
- import { clsx } from '../../lib/clsx.ts'
3
- import { mergeRefs } from '../../lib/ref.ts'
4
- import { Override } from '../../lib/util.ts'
5
- import { FieldsetContext } from './fieldset.tsx'
6
- import { InputContainer } from './input-container.tsx'
7
-
8
- export type InputTextProps = Override<
9
- Omit<JSX.IntrinsicElements['input'], 'children'>,
10
- {
11
- icon?: ReactNode
12
- append?: ReactNode
13
- bellow?: ReactNode
14
- className?: string
15
- }
16
- >
17
-
18
- export function InputText({
19
- icon,
20
- append,
21
- bellow,
22
- className,
23
-
24
- // input
25
- onFocus,
26
- onBlur,
27
- ref,
28
- disabled,
29
- title,
30
- 'aria-label': ariaLabel = title,
31
- 'aria-labelledby': ariaLabelledBy,
32
- placeholder = ariaLabel,
33
- ...props
34
- }: InputTextProps) {
35
- const ctx = useContext(FieldsetContext)
36
-
37
- const inputRef = useRef<HTMLInputElement>(null)
38
- const focusedRef = useRef(false) // ref instead of state to avoid re-renders
39
-
40
- return (
41
- <InputContainer
42
- icon={icon}
43
- append={append}
44
- bellow={bellow}
45
- className={clsx('cursor-text', className)}
46
- tabIndex={-1}
47
- onClick={(event) => {
48
- if (inputRef.current !== event.target) {
49
- event.preventDefault()
50
- event.stopPropagation()
51
- inputRef.current?.focus()
52
- }
53
- }}
54
- onMouseDown={(event) => {
55
- if (focusedRef.current && event.target !== inputRef.current) {
56
- // Prevent "blur" event from firing when clicking outside the input
57
- event.preventDefault()
58
- event.stopPropagation()
59
- }
60
- }}
61
- >
62
- <input
63
- {...props}
64
- disabled={disabled ?? ctx.disabled}
65
- title={title}
66
- placeholder={placeholder}
67
- aria-label={ariaLabel}
68
- aria-labelledby={ariaLabelledBy ?? ctx.labelId}
69
- ref={mergeRefs([ref, inputRef])}
70
- className="w-full bg-transparent bg-clip-padding text-base text-inherit outline-none dark:placeholder-gray-500 text-ellipsis"
71
- onFocus={(event) => {
72
- onFocus?.(event)
73
- if (!event.defaultPrevented) focusedRef.current = true
74
- }}
75
- onBlur={(event) => {
76
- onBlur?.(event)
77
- if (!event.defaultPrevented) focusedRef.current = false
78
- }}
79
- />
80
- </InputContainer>
81
- )
82
- }
@@ -1,94 +0,0 @@
1
- import { useLingui } from '@lingui/react/macro'
2
- import { ChangeEvent, useState } from 'react'
3
- import { Override } from '../../lib/util.ts'
4
- import { TokenIcon } from '../utils/icons.tsx'
5
- import { InputText, InputTextProps } from './input-text.tsx'
6
-
7
- export type InputTokenProps = Override<
8
- Omit<
9
- InputTextProps,
10
- | 'type'
11
- | 'pattern'
12
- | 'autoCapitalize'
13
- | 'autoCorrect'
14
- | 'autoComplete'
15
- | 'spellCheck'
16
- | 'minLength'
17
- | 'maxLength'
18
- | 'placeholder'
19
- | 'dir'
20
- >,
21
- {
22
- example?: string
23
- onToken?: (code: string | null) => void
24
- }
25
- >
26
-
27
- export const OTP_CODE_EXAMPLE = 'XXXXX-XXXXX'
28
-
29
- export function InputToken({
30
- example = OTP_CODE_EXAMPLE,
31
- onToken,
32
-
33
- // InputTextProps
34
- icon = <TokenIcon className="w-5" />,
35
- title = example,
36
- onChange,
37
- value,
38
- defaultValue = value,
39
- ...props
40
- }: InputTokenProps) {
41
- const { t } = useLingui()
42
- const [token, setToken] = useState<string>(
43
- typeof defaultValue === 'string' ? defaultValue : '',
44
- )
45
-
46
- return (
47
- <InputText
48
- {...props}
49
- type="text"
50
- autoCapitalize="none"
51
- autoCorrect="off"
52
- autoComplete="off"
53
- spellCheck="false"
54
- minLength={11}
55
- maxLength={11}
56
- dir="auto"
57
- icon={icon}
58
- pattern="^[A-Z2-7]{5}-[A-Z2-7]{5}$"
59
- placeholder={t`Looks like ${example}`}
60
- title={title}
61
- value={token}
62
- onChange={(event: ChangeEvent<HTMLInputElement>) => {
63
- const { value, selectionEnd, selectionStart } = event.currentTarget
64
-
65
- const fixedValue = fix(value)
66
-
67
- event.currentTarget.value = fixedValue
68
-
69
- // Move the cursor back where it was relative to the original value
70
- const pos = selectionEnd ?? selectionStart
71
- if (pos != null) {
72
- const fixedSlicedValue = fix(value.slice(0, pos))
73
- event.currentTarget.selectionStart =
74
- event.currentTarget.selectionEnd = fixedSlicedValue.length
75
- }
76
-
77
- setToken(fixedValue)
78
- onChange?.(event)
79
-
80
- if (!event.isDefaultPrevented()) {
81
- onToken?.(fixedValue.length === 11 ? fixedValue : null)
82
- }
83
- }}
84
- />
85
- )
86
- }
87
-
88
- function fix(value: string) {
89
- const normalized = value.toUpperCase().replaceAll(/[^A-Z2-7]/g, '')
90
-
91
- if (normalized.length <= 5) return normalized
92
-
93
- return `${normalized.slice(0, 5)}-${normalized.slice(5, 10)}`
94
- }
@@ -1,116 +0,0 @@
1
- import { Trans } from '@lingui/react/macro'
2
- import { JSX, ReactNode, useCallback } from 'react'
3
- import { DisabledStep, Step, useStepper } from '../../hooks/use-stepper.ts'
4
- import { clsx } from '../../lib/clsx.ts'
5
- import { Override } from '../../lib/util.ts'
6
-
7
- export type DoneFn = (...a: any) => unknown
8
-
9
- export type WizardRenderProps<TDone extends DoneFn> = {
10
- /**
11
- * Indicates wether the render function being invoked corresponds to the step
12
- * currently active. The steps titles could, for example, be rendered in a
13
- * list of links, where the current step is highlighted (based on `current`).
14
- *
15
- * Another use for this is to render the next/previous steps in order to
16
- * provide animated transitions between steps. In this case, `current` would
17
- * be used to disable any form interaction with the form transitioning in/out.
18
- */
19
- current: boolean
20
- invalid: boolean
21
-
22
- prev?: () => void
23
- prevLabel: ReactNode
24
-
25
- // On the last step, the "next()" function will actually be the done function
26
- next: (() => void) | TDone
27
- nextLabel: ReactNode
28
- }
29
-
30
- export type WizardRenderFn<TDone extends DoneFn> = (
31
- data: WizardRenderProps<TDone>,
32
- ) => ReactNode
33
-
34
- export type WizardStep<TDone extends DoneFn> = Step & {
35
- titleRender?: WizardRenderFn<TDone>
36
- contentRender: WizardRenderFn<TDone>
37
- }
38
-
39
- export type WizardCardProps<TDone extends DoneFn> = Override<
40
- Omit<JSX.IntrinsicElements['div'], 'children'>,
41
- {
42
- prevLabel?: ReactNode
43
- nextLabel?: ReactNode
44
-
45
- onBack?: () => void
46
- backLabel?: ReactNode
47
-
48
- onDone: TDone
49
- doneLabel?: ReactNode
50
-
51
- steps: readonly (WizardStep<TDone> | DisabledStep)[]
52
- }
53
- >
54
-
55
- export function WizardCard<TDone extends DoneFn>({
56
- prevLabel,
57
- nextLabel,
58
-
59
- onBack,
60
- backLabel,
61
-
62
- onDone,
63
- doneLabel,
64
-
65
- steps,
66
- className,
67
-
68
- ...props
69
- }: WizardCardProps<TDone>) {
70
- const {
71
- atFirst,
72
- atLast,
73
- count,
74
- current,
75
- currentPosition,
76
- completed,
77
- toNext,
78
- toPrev,
79
- toRequired,
80
- } = useStepper(steps)
81
-
82
- // Memoized to avoid re-renders in child (rendered) components
83
- const onNext = useCallback(() => {
84
- // If already at last step, go to the first incomplete (required) step
85
- if (!toNext()) toRequired()
86
- }, [toNext, toRequired])
87
-
88
- const data: WizardRenderProps<TDone> = {
89
- // The current UI only displays the current title & content.
90
- current: true,
91
- invalid: current ? current.invalid : false,
92
-
93
- prevLabel: (atFirst && backLabel) || prevLabel || <Trans>Back</Trans>,
94
- prev: atFirst ? onBack : toPrev,
95
-
96
- nextLabel: (atLast && doneLabel) || nextLabel || <Trans>Next</Trans>,
97
- next: atLast && completed ? onDone : onNext,
98
- }
99
-
100
- const stepTitle = current?.titleRender?.(data)
101
- const stepContent = current?.contentRender?.(data)
102
-
103
- return (
104
- <div className={clsx(className, 'flex flex-col')} {...props}>
105
- <p className="text-slate-500 dark:text-slate-400">
106
- <Trans>
107
- Step {currentPosition} of {count}
108
- </Trans>
109
- </p>
110
-
111
- {stepTitle && <h2 className="font-medium text-xl mb-4">{stepTitle}</h2>}
112
-
113
- {stepContent}
114
- </div>
115
- )
116
- }
@@ -1,77 +0,0 @@
1
- import { JSX, ReactNode } from 'react'
2
- import { clsx } from '../../lib/clsx.ts'
3
- import { Override } from '../../lib/util.ts'
4
- import { LocaleSelector } from '../../locales/locale-selector.tsx'
5
-
6
- export type LayoutTitlePageProps = Override<
7
- JSX.IntrinsicElements['div'],
8
- {
9
- title?: string
10
- subtitle?: ReactNode
11
- children?: ReactNode
12
- }
13
- >
14
-
15
- export function LayoutTitlePage({
16
- children,
17
- title,
18
- subtitle,
19
-
20
- // HTMLDivElement
21
- className,
22
- ...props
23
- }: LayoutTitlePageProps) {
24
- return (
25
- <div
26
- {...props}
27
- className={clsx(
28
- className,
29
- 'flex flex-col items-center',
30
- 'md:flex md:flex-row md:justify-stretch md:items-center',
31
- 'min-h-screen min-w-screen',
32
- 'bg-white text-slate-900',
33
- 'dark:bg-slate-900 dark:text-slate-100',
34
- )}
35
- >
36
- {title && <title>{title}</title>}
37
-
38
- <div
39
- className={clsx(
40
- 'px-6 pt-4',
41
- 'w-full',
42
- 'md:max-w-lg',
43
- 'flex flex-row md:flex-col',
44
- 'md:self-stretch',
45
- 'md:w-1/2 md:max-w-fix md:p-4',
46
- 'md:text-right',
47
- 'md:dark:border-r md:dark:border-slate-700',
48
- 'md:bg-slate-100 md:dark:bg-slate-800',
49
- )}
50
- >
51
- <div className="flex-grow grid content-center md:justify-items-end">
52
- {title && (
53
- <h1
54
- key="title"
55
- className="text-xl md:text-2xl lg:text-5xl md:my-4 font-semibold text-brand"
56
- >
57
- {title}
58
- </h1>
59
- )}
60
-
61
- {subtitle && (
62
- <p
63
- key="subtitle"
64
- className="hidden md:block max-w-xs text-slate-600 dark:text-slate-400"
65
- >
66
- {subtitle}
67
- </p>
68
- )}
69
- </div>
70
-
71
- <LocaleSelector key="localeSelector" className="m-1 md:m-2" />
72
- </div>
73
-
74
- <main className="w-full p-6 md:max-w-3xl md:px-12">{children}</main>
75
- </div>
76
- )
77
- }