@atproto/oauth-provider 0.5.1 → 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 (325) hide show
  1. package/CHANGELOG.md +39 -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 +13 -5
  7. package/dist/account/account-store.d.ts.map +1 -1
  8. package/dist/account/account-store.js +24 -8
  9. package/dist/account/account-store.js.map +1 -1
  10. package/dist/account/account.d.ts +1 -11
  11. package/dist/account/account.d.ts.map +1 -1
  12. package/dist/account/{sign-up-data.d.ts → sign-up-input.d.ts} +5 -5
  13. package/dist/account/sign-up-input.d.ts.map +1 -0
  14. package/dist/account/{sign-up-data.js → sign-up-input.js} +3 -3
  15. package/dist/account/sign-up-input.js.map +1 -0
  16. package/dist/assets/assets-middleware.d.ts +2 -0
  17. package/dist/assets/assets-middleware.d.ts.map +1 -1
  18. package/dist/assets/assets-middleware.js +12 -14
  19. package/dist/assets/assets-middleware.js.map +1 -1
  20. package/dist/errors/invalid-invite-code-error.d.ts +5 -0
  21. package/dist/errors/invalid-invite-code-error.d.ts.map +1 -0
  22. package/dist/errors/invalid-invite-code-error.js +11 -0
  23. package/dist/errors/invalid-invite-code-error.js.map +1 -0
  24. package/dist/errors/oauth-error.d.ts +2 -2
  25. package/dist/errors/oauth-error.js.map +1 -1
  26. package/dist/lib/csp/index.d.ts +5 -6
  27. package/dist/lib/csp/index.d.ts.map +1 -1
  28. package/dist/lib/csp/index.js +14 -11
  29. package/dist/lib/csp/index.js.map +1 -1
  30. package/dist/lib/hcaptcha.d.ts +5 -3
  31. package/dist/lib/hcaptcha.d.ts.map +1 -1
  32. package/dist/lib/hcaptcha.js +7 -4
  33. package/dist/lib/hcaptcha.js.map +1 -1
  34. package/dist/lib/html/build-document.d.ts +2 -2
  35. package/dist/lib/html/build-document.d.ts.map +1 -1
  36. package/dist/lib/html/build-document.js +11 -7
  37. package/dist/lib/html/build-document.js.map +1 -1
  38. package/dist/lib/html/html.d.ts.map +1 -1
  39. package/dist/lib/html/html.js +10 -13
  40. package/dist/lib/html/html.js.map +1 -1
  41. package/dist/lib/html/util.d.ts +0 -1
  42. package/dist/lib/html/util.d.ts.map +1 -1
  43. package/dist/lib/html/util.js +0 -4
  44. package/dist/lib/html/util.js.map +1 -1
  45. package/dist/lib/http/response.d.ts +3 -1
  46. package/dist/lib/http/response.d.ts.map +1 -1
  47. package/dist/lib/http/response.js +3 -0
  48. package/dist/lib/http/response.js.map +1 -1
  49. package/dist/lib/http/security-headers.d.ts +48 -0
  50. package/dist/lib/http/security-headers.d.ts.map +1 -0
  51. package/dist/lib/http/security-headers.js +62 -0
  52. package/dist/lib/http/security-headers.js.map +1 -0
  53. package/dist/lib/util/type.d.ts +8 -0
  54. package/dist/lib/util/type.d.ts.map +1 -1
  55. package/dist/lib/util/type.js.map +1 -1
  56. package/dist/oauth-errors.d.ts +1 -0
  57. package/dist/oauth-errors.d.ts.map +1 -1
  58. package/dist/oauth-errors.js +3 -1
  59. package/dist/oauth-errors.js.map +1 -1
  60. package/dist/oauth-hooks.d.ts +4 -25
  61. package/dist/oauth-hooks.d.ts.map +1 -1
  62. package/dist/oauth-provider.d.ts.map +1 -1
  63. package/dist/oauth-provider.js +26 -25
  64. package/dist/oauth-provider.js.map +1 -1
  65. package/dist/output/backend-data.d.ts +4 -0
  66. package/dist/output/backend-data.d.ts.map +1 -0
  67. package/dist/output/backend-data.js +19 -0
  68. package/dist/output/backend-data.js.map +1 -0
  69. package/dist/output/build-authorize-data.d.ts +3 -19
  70. package/dist/output/build-authorize-data.d.ts.map +1 -1
  71. package/dist/output/build-authorize-data.js.map +1 -1
  72. package/dist/output/build-customization-data.d.ts +11 -18
  73. package/dist/output/build-customization-data.d.ts.map +1 -1
  74. package/dist/output/build-customization-data.js +1 -1
  75. package/dist/output/build-customization-data.js.map +1 -1
  76. package/dist/output/build-error-data.d.ts +3 -0
  77. package/dist/output/build-error-data.d.ts.map +1 -0
  78. package/dist/output/build-error-data.js +10 -0
  79. package/dist/output/build-error-data.js.map +1 -0
  80. package/dist/output/build-error-payload.d.ts +2 -1
  81. package/dist/output/build-error-payload.d.ts.map +1 -1
  82. package/dist/output/build-error-payload.js.map +1 -1
  83. package/dist/output/output-manager.d.ts +10 -4
  84. package/dist/output/output-manager.d.ts.map +1 -1
  85. package/dist/output/output-manager.js +68 -39
  86. package/dist/output/output-manager.js.map +1 -1
  87. package/dist/output/send-web-page.d.ts +6 -10
  88. package/dist/output/send-web-page.d.ts.map +1 -1
  89. package/dist/output/send-web-page.js +27 -47
  90. package/dist/output/send-web-page.js.map +1 -1
  91. package/dist/signer/signed-token-payload.d.ts +3 -3
  92. package/dist/signer/signer.d.ts +2 -2
  93. package/package.json +7 -39
  94. package/src/account/account-manager.ts +55 -34
  95. package/src/account/account-store.ts +29 -6
  96. package/src/account/account.ts +1 -14
  97. package/src/account/{sign-up-data.ts → sign-up-input.ts} +2 -2
  98. package/src/assets/assets-middleware.ts +11 -17
  99. package/src/errors/invalid-invite-code-error.ts +10 -0
  100. package/src/errors/oauth-error.ts +1 -1
  101. package/src/lib/csp/index.ts +16 -13
  102. package/src/lib/hcaptcha.ts +10 -7
  103. package/src/lib/html/build-document.ts +15 -8
  104. package/src/lib/html/html.ts +11 -18
  105. package/src/lib/html/util.ts +0 -4
  106. package/src/lib/http/response.ts +9 -1
  107. package/src/lib/http/security-headers.ts +91 -0
  108. package/src/lib/util/type.ts +18 -0
  109. package/src/oauth-errors.ts +1 -0
  110. package/src/oauth-hooks.ts +4 -25
  111. package/src/oauth-provider.ts +40 -34
  112. package/src/output/backend-data.ts +18 -0
  113. package/src/output/build-authorize-data.ts +3 -26
  114. package/src/output/build-customization-data.ts +2 -13
  115. package/src/output/build-error-data.ts +8 -0
  116. package/src/output/build-error-payload.ts +4 -2
  117. package/src/output/output-manager.ts +86 -47
  118. package/src/output/send-web-page.ts +29 -58
  119. package/tsconfig.backend.json +1 -2
  120. package/tsconfig.backend.tsbuildinfo +1 -1
  121. package/tsconfig.json +1 -5
  122. package/.linguirc +0 -57
  123. package/dist/account/sign-up-data.d.ts.map +0 -1
  124. package/dist/account/sign-up-data.js.map +0 -1
  125. package/dist/assets/app/bundle-manifest.json +0 -614
  126. package/dist/assets/app/index-ItwwtJ8r.js +0 -36
  127. package/dist/assets/app/index-ItwwtJ8r.js.map +0 -1
  128. package/dist/assets/app/main-B_dNxQo_.js +0 -4
  129. package/dist/assets/app/main-B_dNxQo_.js.map +0 -1
  130. package/dist/assets/app/main-CSatvmRR.css +0 -3
  131. package/dist/assets/app/main-CSatvmRR.js +0 -306
  132. package/dist/assets/app/main-CSatvmRR.js.map +0 -1
  133. package/dist/assets/app/messages-BQeltXSF.js +0 -4
  134. package/dist/assets/app/messages-BQeltXSF.js.map +0 -1
  135. package/dist/assets/app/messages-BQkEhfjg.js +0 -4
  136. package/dist/assets/app/messages-BQkEhfjg.js.map +0 -1
  137. package/dist/assets/app/messages-BUjKj_UJ.js +0 -4
  138. package/dist/assets/app/messages-BUjKj_UJ.js.map +0 -1
  139. package/dist/assets/app/messages-BWIQa8fO.js +0 -4
  140. package/dist/assets/app/messages-BWIQa8fO.js.map +0 -1
  141. package/dist/assets/app/messages-BaNVb0bp.js +0 -4
  142. package/dist/assets/app/messages-BaNVb0bp.js.map +0 -1
  143. package/dist/assets/app/messages-BaizVXcF.js +0 -4
  144. package/dist/assets/app/messages-BaizVXcF.js.map +0 -1
  145. package/dist/assets/app/messages-BfoClA1Y.js +0 -4
  146. package/dist/assets/app/messages-BfoClA1Y.js.map +0 -1
  147. package/dist/assets/app/messages-BsKGDZnC.js +0 -4
  148. package/dist/assets/app/messages-BsKGDZnC.js.map +0 -1
  149. package/dist/assets/app/messages-Bu-TJhml.js +0 -4
  150. package/dist/assets/app/messages-Bu-TJhml.js.map +0 -1
  151. package/dist/assets/app/messages-BvOKnBQk.js +0 -4
  152. package/dist/assets/app/messages-BvOKnBQk.js.map +0 -1
  153. package/dist/assets/app/messages-BxDzCiWz.js +0 -4
  154. package/dist/assets/app/messages-BxDzCiWz.js.map +0 -1
  155. package/dist/assets/app/messages-CDgFOy4S.js +0 -4
  156. package/dist/assets/app/messages-CDgFOy4S.js.map +0 -1
  157. package/dist/assets/app/messages-CLbTz0o9.js +0 -4
  158. package/dist/assets/app/messages-CLbTz0o9.js.map +0 -1
  159. package/dist/assets/app/messages-CNwSh0t7.js +0 -4
  160. package/dist/assets/app/messages-CNwSh0t7.js.map +0 -1
  161. package/dist/assets/app/messages-CSMNJ6P8.js +0 -4
  162. package/dist/assets/app/messages-CSMNJ6P8.js.map +0 -1
  163. package/dist/assets/app/messages-CZQUw3mp.js +0 -4
  164. package/dist/assets/app/messages-CZQUw3mp.js.map +0 -1
  165. package/dist/assets/app/messages-CZT41oVp.js +0 -4
  166. package/dist/assets/app/messages-CZT41oVp.js.map +0 -1
  167. package/dist/assets/app/messages-C_b-d3t8.js +0 -4
  168. package/dist/assets/app/messages-C_b-d3t8.js.map +0 -1
  169. package/dist/assets/app/messages-C_u3MTc2.js +0 -4
  170. package/dist/assets/app/messages-C_u3MTc2.js.map +0 -1
  171. package/dist/assets/app/messages-Cn8nHZic.js +0 -4
  172. package/dist/assets/app/messages-Cn8nHZic.js.map +0 -1
  173. package/dist/assets/app/messages-CtDywJUm.js +0 -4
  174. package/dist/assets/app/messages-CtDywJUm.js.map +0 -1
  175. package/dist/assets/app/messages-CurtIjBF.js +0 -4
  176. package/dist/assets/app/messages-CurtIjBF.js.map +0 -1
  177. package/dist/assets/app/messages-Cv6zIbaP.js +0 -4
  178. package/dist/assets/app/messages-Cv6zIbaP.js.map +0 -1
  179. package/dist/assets/app/messages-D1eLQuPE.js +0 -4
  180. package/dist/assets/app/messages-D1eLQuPE.js.map +0 -1
  181. package/dist/assets/app/messages-D8vHEaYW.js +0 -4
  182. package/dist/assets/app/messages-D8vHEaYW.js.map +0 -1
  183. package/dist/assets/app/messages-DJ1Q4GeC.js +0 -4
  184. package/dist/assets/app/messages-DJ1Q4GeC.js.map +0 -1
  185. package/dist/assets/app/messages-DRL3exqd.js +0 -4
  186. package/dist/assets/app/messages-DRL3exqd.js.map +0 -1
  187. package/dist/assets/app/messages-DWLPQRTp.js +0 -4
  188. package/dist/assets/app/messages-DWLPQRTp.js.map +0 -1
  189. package/dist/assets/app/messages-DjVaE9YE.js +0 -4
  190. package/dist/assets/app/messages-DjVaE9YE.js.map +0 -1
  191. package/dist/assets/app/messages-DqpMfFJR.js +0 -4
  192. package/dist/assets/app/messages-DqpMfFJR.js.map +0 -1
  193. package/dist/assets/app/messages-ETjhJBEN.js +0 -4
  194. package/dist/assets/app/messages-ETjhJBEN.js.map +0 -1
  195. package/dist/assets/app/messages-EUKrgrGn.js +0 -4
  196. package/dist/assets/app/messages-EUKrgrGn.js.map +0 -1
  197. package/dist/assets/app/messages-QQrOUcPW.js +0 -4
  198. package/dist/assets/app/messages-QQrOUcPW.js.map +0 -1
  199. package/dist/assets/app/messages-e2QGqFL6.js +0 -4
  200. package/dist/assets/app/messages-e2QGqFL6.js.map +0 -1
  201. package/dist/assets/app/messages-p61py7gD.js +0 -4
  202. package/dist/assets/app/messages-p61py7gD.js.map +0 -1
  203. package/dist/assets/asset.d.ts +0 -9
  204. package/dist/assets/asset.d.ts.map +0 -1
  205. package/dist/assets/asset.js +0 -3
  206. package/dist/assets/asset.js.map +0 -1
  207. package/dist/assets/index.d.ts +0 -5
  208. package/dist/assets/index.d.ts.map +0 -1
  209. package/dist/assets/index.js +0 -78
  210. package/dist/assets/index.js.map +0 -1
  211. package/rollup.config.js +0 -98
  212. package/src/assets/app/app.tsx +0 -43
  213. package/src/assets/app/backend-data.ts +0 -27
  214. package/src/assets/app/backend-types.ts +0 -66
  215. package/src/assets/app/components/forms/button-toggle-visibility.tsx +0 -43
  216. package/src/assets/app/components/forms/button.tsx +0 -60
  217. package/src/assets/app/components/forms/fieldset.tsx +0 -55
  218. package/src/assets/app/components/forms/form-card-async.tsx +0 -103
  219. package/src/assets/app/components/forms/form-card.tsx +0 -49
  220. package/src/assets/app/components/forms/input-checkbox.tsx +0 -73
  221. package/src/assets/app/components/forms/input-container.tsx +0 -107
  222. package/src/assets/app/components/forms/input-email-address.tsx +0 -66
  223. package/src/assets/app/components/forms/input-new-password.tsx +0 -62
  224. package/src/assets/app/components/forms/input-password.tsx +0 -88
  225. package/src/assets/app/components/forms/input-text.tsx +0 -76
  226. package/src/assets/app/components/forms/input-token.tsx +0 -94
  227. package/src/assets/app/components/forms/wizard-card.tsx +0 -116
  228. package/src/assets/app/components/layouts/layout-title-page.tsx +0 -77
  229. package/src/assets/app/components/layouts/layout-welcome.tsx +0 -73
  230. package/src/assets/app/components/utils/account-identifier.tsx +0 -23
  231. package/src/assets/app/components/utils/account-image.tsx +0 -33
  232. package/src/assets/app/components/utils/admonition.tsx +0 -52
  233. package/src/assets/app/components/utils/client-name.tsx +0 -45
  234. package/src/assets/app/components/utils/error-card.tsx +0 -93
  235. package/src/assets/app/components/utils/error-message.tsx +0 -62
  236. package/src/assets/app/components/utils/help-card.tsx +0 -46
  237. package/src/assets/app/components/utils/icons.tsx +0 -88
  238. package/src/assets/app/components/utils/link-anchor.tsx +0 -28
  239. package/src/assets/app/components/utils/link-title.tsx +0 -26
  240. package/src/assets/app/components/utils/multi-lang-string.tsx +0 -56
  241. package/src/assets/app/components/utils/password-strength-label.tsx +0 -37
  242. package/src/assets/app/components/utils/password-strength-meter.tsx +0 -58
  243. package/src/assets/app/components/utils/url-viewer.tsx +0 -73
  244. package/src/assets/app/cookies.ts +0 -11
  245. package/src/assets/app/hooks/use-api.ts +0 -178
  246. package/src/assets/app/hooks/use-async-action.ts +0 -120
  247. package/src/assets/app/hooks/use-bound-dispatch.ts +0 -5
  248. package/src/assets/app/hooks/use-browser-color-scheme.ts +0 -31
  249. package/src/assets/app/hooks/use-csrf-token.ts +0 -5
  250. package/src/assets/app/hooks/use-random-string.ts +0 -37
  251. package/src/assets/app/hooks/use-stepper.ts +0 -87
  252. package/src/assets/app/index.html +0 -182
  253. package/src/assets/app/lib/api.ts +0 -267
  254. package/src/assets/app/lib/clsx.ts +0 -6
  255. package/src/assets/app/lib/json-client.ts +0 -94
  256. package/src/assets/app/lib/password.ts +0 -98
  257. package/src/assets/app/lib/ref.ts +0 -17
  258. package/src/assets/app/lib/util.ts +0 -13
  259. package/src/assets/app/locales/an/messages.po +0 -492
  260. package/src/assets/app/locales/ast/messages.po +0 -492
  261. package/src/assets/app/locales/ca/messages.po +0 -492
  262. package/src/assets/app/locales/da/messages.po +0 -492
  263. package/src/assets/app/locales/de/messages.po +0 -492
  264. package/src/assets/app/locales/el/messages.po +0 -492
  265. package/src/assets/app/locales/en/messages.po +0 -492
  266. package/src/assets/app/locales/en-GB/messages.po +0 -492
  267. package/src/assets/app/locales/es/messages.po +0 -492
  268. package/src/assets/app/locales/eu/messages.po +0 -492
  269. package/src/assets/app/locales/fi/messages.po +0 -492
  270. package/src/assets/app/locales/fr/messages.po +0 -492
  271. package/src/assets/app/locales/ga/messages.po +0 -492
  272. package/src/assets/app/locales/gl/messages.po +0 -492
  273. package/src/assets/app/locales/hi/messages.po +0 -492
  274. package/src/assets/app/locales/hu/messages.po +0 -492
  275. package/src/assets/app/locales/ia/messages.po +0 -492
  276. package/src/assets/app/locales/id/messages.po +0 -492
  277. package/src/assets/app/locales/it/messages.po +0 -492
  278. package/src/assets/app/locales/ja/messages.po +0 -492
  279. package/src/assets/app/locales/km/messages.po +0 -492
  280. package/src/assets/app/locales/ko/messages.po +0 -492
  281. package/src/assets/app/locales/load.ts +0 -8
  282. package/src/assets/app/locales/locale-context.ts +0 -19
  283. package/src/assets/app/locales/locale-provider.tsx +0 -112
  284. package/src/assets/app/locales/locale-selector.tsx +0 -58
  285. package/src/assets/app/locales/locales.ts +0 -168
  286. package/src/assets/app/locales/ne/messages.po +0 -492
  287. package/src/assets/app/locales/nl/messages.po +0 -492
  288. package/src/assets/app/locales/pl/messages.po +0 -492
  289. package/src/assets/app/locales/pt-BR/messages.po +0 -492
  290. package/src/assets/app/locales/ro/messages.po +0 -492
  291. package/src/assets/app/locales/ru/messages.po +0 -492
  292. package/src/assets/app/locales/sv/messages.po +0 -492
  293. package/src/assets/app/locales/th/messages.po +0 -492
  294. package/src/assets/app/locales/tr/messages.po +0 -492
  295. package/src/assets/app/locales/uk/messages.po +0 -492
  296. package/src/assets/app/locales/vi/messages.po +0 -492
  297. package/src/assets/app/locales/zh-CN/messages.po +0 -492
  298. package/src/assets/app/locales/zh-HK/messages.po +0 -492
  299. package/src/assets/app/locales/zh-TW/messages.po +0 -492
  300. package/src/assets/app/main.css +0 -33
  301. package/src/assets/app/main.tsx +0 -44
  302. package/src/assets/app/views/authorize/accept/accept-form.tsx +0 -150
  303. package/src/assets/app/views/authorize/accept/accept-view.tsx +0 -70
  304. package/src/assets/app/views/authorize/authorize-view.tsx +0 -180
  305. package/src/assets/app/views/authorize/reset-password/reset-password-confirm-form.tsx +0 -88
  306. package/src/assets/app/views/authorize/reset-password/reset-password-request-form.tsx +0 -80
  307. package/src/assets/app/views/authorize/reset-password/reset-password-view.tsx +0 -127
  308. package/src/assets/app/views/authorize/sign-in/sign-in-form.tsx +0 -244
  309. package/src/assets/app/views/authorize/sign-in/sign-in-picker.tsx +0 -116
  310. package/src/assets/app/views/authorize/sign-in/sign-in-view.tsx +0 -145
  311. package/src/assets/app/views/authorize/sign-up/sign-up-account-form.tsx +0 -140
  312. package/src/assets/app/views/authorize/sign-up/sign-up-disclaimer.tsx +0 -51
  313. package/src/assets/app/views/authorize/sign-up/sign-up-handle-form.tsx +0 -289
  314. package/src/assets/app/views/authorize/sign-up/sign-up-hcaptcha-form.tsx +0 -108
  315. package/src/assets/app/views/authorize/sign-up/sign-up-view.tsx +0 -158
  316. package/src/assets/app/views/authorize/welcome/welcome-view.tsx +0 -56
  317. package/src/assets/app/views/error/error-view.tsx +0 -31
  318. package/src/assets/asset.ts +0 -9
  319. package/src/assets/index.ts +0 -86
  320. package/tailwind.config.js +0 -31
  321. package/tsconfig.frontend.json +0 -11
  322. package/tsconfig.frontend.tsbuildinfo +0 -1
  323. package/tsconfig.tools.json +0 -8
  324. package/tsconfig.tools.tsbuildinfo +0 -1
  325. package/vite.config.mjs +0 -16
@@ -1,73 +0,0 @@
1
- import { JSX } from 'react'
2
- import { CustomizationData } from '../../backend-types.ts'
3
- import { clsx } from '../../lib/clsx.ts'
4
- import { Override } from '../../lib/util.ts'
5
- import { LocaleSelector } from '../../locales/locale-selector.tsx'
6
- import { LinkAnchor } from '../utils/link-anchor.tsx'
7
-
8
- export type LayoutWelcomeProps = Override<
9
- JSX.IntrinsicElements['div'],
10
- {
11
- customizationData: CustomizationData | undefined
12
- title?: string
13
- }
14
- >
15
-
16
- export function LayoutWelcome({
17
- customizationData: { logo, name, links } = {},
18
- title = name,
19
-
20
- // div
21
- className,
22
- children,
23
- ...props
24
- }: LayoutWelcomeProps) {
25
- return (
26
- <div
27
- {...props}
28
- className={clsx(
29
- 'min-h-screen w-full',
30
- 'flex items-center justify-center flex-col',
31
- 'bg-white text-slate-900',
32
- 'dark:bg-slate-900 dark:text-slate-100',
33
- className,
34
- )}
35
- >
36
- {title && <title>{title}</title>}
37
-
38
- <main className="w-full overflow-hidden flex-grow flex flex-col items-center justify-center p-6">
39
- {logo && (
40
- <img
41
- src={logo}
42
- alt={name || `Logo`}
43
- aria-hidden
44
- className="w-16 h-16 md:w-24 md:h-24 mb-4 md:mb-8"
45
- />
46
- )}
47
-
48
- {name && (
49
- <h1 className="text-2xl md:text-4xl mb-4 md:mb-8 mx-4 text-center font-bold">
50
- {name}
51
- </h1>
52
- )}
53
-
54
- {children}
55
- </main>
56
-
57
- <nav className="w-full overflow-hidden border-t border-t-slate-200 dark:border-t-slate-700 flex flex-wrap justify-center content-center">
58
- {links?.map((link, i) => (
59
- <LinkAnchor
60
- key={i}
61
- link={link}
62
- className="m-2 md:m-4 text-xs md:text-sm text-brand hover:underline"
63
- />
64
- ))}
65
-
66
- <LocaleSelector
67
- className="m-1 md:m-2 text-xs md:text-sm"
68
- key="localeSelector"
69
- />
70
- </nav>
71
- </div>
72
- )
73
- }
@@ -1,23 +0,0 @@
1
- import { JSX } from 'react'
2
- import { Account } from '../../backend-types.ts'
3
- import { Override } from '../../lib/util.ts'
4
-
5
- export type AccountIdentifierProps = Override<
6
- Omit<JSX.IntrinsicElements['b'], 'children'>,
7
- {
8
- account: Account
9
- }
10
- >
11
-
12
- export function AccountIdentifier({
13
- account,
14
-
15
- // b
16
- ...props
17
- }: AccountIdentifierProps) {
18
- return (
19
- <b {...props}>
20
- {account.preferred_username || account.email || account.sub}
21
- </b>
22
- )
23
- }
@@ -1,33 +0,0 @@
1
- import { useEffect, useState } from 'react'
2
- import { AccountIcon } from './icons.tsx'
3
-
4
- export type AccountIconProps = {
5
- src?: string
6
- alt: string
7
- }
8
-
9
- export function AccountImage({ src, alt }: AccountIconProps) {
10
- const [errored, setErrored] = useState(false)
11
-
12
- useEffect(() => {
13
- setErrored(false)
14
- }, [src])
15
-
16
- return src && !errored ? (
17
- <img
18
- aria-hidden
19
- crossOrigin="anonymous"
20
- src={src}
21
- alt={alt}
22
- className="-ml-1 w-6 h-6 rounded-full"
23
- onError={() => setErrored(true)}
24
- />
25
- ) : (
26
- <div
27
- aria-hidden
28
- className="h-6 w-6 text-white bg-brand rounded-full border-solid border-2 border-brand overflow-hidden"
29
- >
30
- <AccountIcon className="-mx-1 -mb-1" />
31
- </div>
32
- )
33
- }
@@ -1,52 +0,0 @@
1
- import { JSX, memo } from 'react'
2
- import { clsx } from '../../lib/clsx.ts'
3
- import { Override } from '../../lib/util.ts'
4
- import { AlertIcon, EyeIcon } from './icons.tsx'
5
-
6
- export type AdmonitionProps = Override<
7
- JSX.IntrinsicElements['div'],
8
- {
9
- role: 'alert' | 'status' | 'info'
10
- }
11
- >
12
-
13
- export const Admonition = memo(function Admonition({
14
- role = 'alert',
15
- children,
16
- className,
17
- ...props
18
- }: AdmonitionProps) {
19
- return (
20
- <div
21
- {...props}
22
- role={role}
23
- className={clsx(
24
- 'flex flex-row',
25
- 'gap-2',
26
- 'p-3',
27
- 'rounded-lg',
28
- 'border',
29
- 'border-gray-300 dark:border-gray-700',
30
- role === 'alert' && 'bg-error text-error-c',
31
- className,
32
- )}
33
- >
34
- {role === 'info' ? (
35
- <EyeIcon
36
- aria-hidden
37
- className={clsx('fill-current h-6 w-6', 'text-brand')}
38
- />
39
- ) : (
40
- <AlertIcon
41
- aria-hidden
42
- className={clsx(
43
- 'fill-current h-6 w-6',
44
- role === 'alert' ? 'text-inherit' : 'text-brand',
45
- )}
46
- />
47
- )}
48
-
49
- <div className="flex flex-1 flex-col">{children}</div>
50
- </div>
51
- )
52
- })
@@ -1,45 +0,0 @@
1
- import { Trans } from '@lingui/react/macro'
2
- import { JSX } from 'react'
3
- import type { OAuthClientMetadata } from '@atproto/oauth-types'
4
- import { Override } from '../../lib/util.ts'
5
- import { UrlViewer } from './url-viewer.tsx'
6
-
7
- export type ClientNameProps = Override<
8
- Omit<JSX.IntrinsicElements['span'], 'children'>,
9
- {
10
- clientId: string
11
- clientMetadata: OAuthClientMetadata
12
- clientTrusted: boolean
13
- }
14
- >
15
-
16
- export function ClientName({
17
- clientId,
18
- clientMetadata,
19
- clientTrusted,
20
-
21
- // span
22
- ...attrs
23
- }: ClientNameProps) {
24
- if (clientTrusted && clientMetadata.client_name) {
25
- return <span {...attrs}>{clientMetadata.client_name}</span>
26
- }
27
-
28
- // @NOTE: not using isOAuthClientIdLoopback & isOAuthClientIdDiscoverable from
29
- // @atproto/oauth-types here because 1) we don't need to validate here and 2)
30
- // we prefer not to import un-necessary code to improve bundle size.
31
-
32
- if (clientId.startsWith('http://')) {
33
- return (
34
- <span {...attrs}>
35
- <Trans>An application on your device</Trans>
36
- </span>
37
- )
38
- }
39
-
40
- if (clientId.startsWith('https://')) {
41
- return <UrlViewer {...attrs} url={clientId} path />
42
- }
43
-
44
- return <span {...attrs}>{clientId}</span>
45
- }
@@ -1,93 +0,0 @@
1
- import { Trans } from '@lingui/react/macro'
2
- import { memo, useEffect, useMemo, useState } from 'react'
3
- import { useRandomString } from '../../hooks/use-random-string.ts'
4
- import { Api } from '../../lib/api.ts'
5
- import { JsonErrorResponse } from '../../lib/json-client.ts'
6
- import { Override } from '../../lib/util.ts'
7
- import { Admonition, AdmonitionProps } from './admonition.tsx'
8
- import { ErrorMessage } from './error-message.tsx'
9
-
10
- export type ErrorCardProps = Override<
11
- Omit<AdmonitionProps, 'role'>,
12
- {
13
- error: unknown
14
- }
15
- >
16
- export const ErrorCard = memo(function ErrorCard({
17
- error,
18
-
19
- // Admonition
20
- children,
21
- onClick,
22
- onKeyDown,
23
- ...props
24
- }: ErrorCardProps) {
25
- const [inputCount, setInputCount] = useState(0)
26
- // Every 5th input will toggle showing the details
27
- const showDetails = ((inputCount / 5) | 0) % 2 === 1
28
-
29
- const detailsDivId = useRandomString('error-card-')
30
-
31
- const parsedError = useMemo(
32
- () =>
33
- error instanceof JsonErrorResponse
34
- ? // Already parsed:
35
- error
36
- : // If "error" is a json object, try parsing it as a JsonErrorResponse:
37
- Api.parseError(error) ?? error,
38
- [error],
39
- )
40
-
41
- useEffect(() => {
42
- // For debugging purposes
43
- console.warn('Displayed error details:', parsedError)
44
-
45
- // Reset the input count when the error changes
46
- setInputCount(0)
47
- }, [parsedError])
48
-
49
- return (
50
- <Admonition
51
- role="alert"
52
- aria-controls={detailsDivId}
53
- tabIndex={0}
54
- onKeyDown={(event) => {
55
- onKeyDown?.(event)
56
- if (!event.defaultPrevented) {
57
- setInputCount((c) => c + 1)
58
- }
59
- }}
60
- onClick={(event) => {
61
- onClick?.(event)
62
- if (!event.defaultPrevented) {
63
- setInputCount((c) => c + 1)
64
- }
65
- }}
66
- {...props}
67
- >
68
- <ErrorMessage error={parsedError} />
69
-
70
- {children && <div className="mt-2">{children}</div>}
71
-
72
- <div hidden={!showDetails} id={detailsDivId} aria-hidden={!showDetails}>
73
- {parsedError instanceof JsonErrorResponse ? (
74
- <dl className="mt-2 grid grid-cols-[auto,1fr] gap-x-2 text-sm">
75
- <dt className="font-semibold">
76
- <Trans>Code</Trans>
77
- </dt>
78
- <dd>
79
- <code>{parsedError.error}</code>
80
- </dd>
81
-
82
- <dt className="font-semibold">
83
- <Trans>Description</Trans>
84
- </dt>
85
- <dd>{parsedError.description}</dd>
86
- </dl>
87
- ) : (
88
- <pre className="text-xs">{JSON.stringify(parsedError, null, 2)}</pre>
89
- )}
90
- </div>
91
- </Admonition>
92
- )
93
- })
@@ -1,62 +0,0 @@
1
- import { Trans } from '@lingui/react/macro'
2
- import { ReactNode, memo } from 'react'
3
- import {
4
- EmailTakenError,
5
- HandleUnavailableError,
6
- InvalidCredentialsError,
7
- RequestExpiredError,
8
- SecondAuthenticationFactorRequiredError,
9
- UnknownRequestUriError,
10
- } from '../../lib/api.ts'
11
- import { JsonErrorResponse } from '../../lib/json-client.ts'
12
-
13
- export type ApiErrorMessageProps = {
14
- error: unknown
15
- }
16
-
17
- export const ErrorMessage = memo(function ErrorMessage({
18
- error,
19
- }: ApiErrorMessageProps): ReactNode {
20
- if (error instanceof InvalidCredentialsError) {
21
- return <Trans>Wrong identifier or password</Trans>
22
- }
23
-
24
- if (error instanceof EmailTakenError) {
25
- return <Trans>This email is already used</Trans>
26
- }
27
-
28
- if (error instanceof HandleUnavailableError) {
29
- switch (error.reason) {
30
- case 'syntax':
31
- return <Trans>The handle is invalid</Trans>
32
- case 'domain':
33
- return <Trans>The domain name is not allowed</Trans>
34
- case 'slur':
35
- return <Trans>The handle contains inappropriate language</Trans>
36
- case 'taken':
37
- if (error.description === 'Reserved handle') {
38
- return <Trans>This handle is reserved</Trans>
39
- }
40
- return <Trans>The handle is already in use</Trans>
41
- default:
42
- return <Trans>That handle cannot be used</Trans>
43
- }
44
- }
45
-
46
- if (error instanceof SecondAuthenticationFactorRequiredError) {
47
- return <Trans>A second authentication factor is required</Trans>
48
- }
49
-
50
- if (
51
- error instanceof UnknownRequestUriError ||
52
- error instanceof RequestExpiredError
53
- ) {
54
- return <Trans>This sign-in session has expired</Trans>
55
- }
56
-
57
- if (error instanceof JsonErrorResponse) {
58
- return <Trans>Unexpected server response</Trans>
59
- }
60
-
61
- return <Trans>An unknown error occurred</Trans>
62
- })
@@ -1,46 +0,0 @@
1
- import { Trans } from '@lingui/react/macro'
2
- import { JSX } from 'react'
3
- import { LinkDefinition } from '../../backend-types.ts'
4
- import { clsx } from '../../lib/clsx.ts'
5
- import { Override } from '../../lib/util.ts'
6
-
7
- export type HelpCardProps = Override<
8
- Omit<JSX.IntrinsicElements['p'], 'children'>,
9
- {
10
- links?: readonly LinkDefinition[]
11
- }
12
- >
13
-
14
- export function HelpCard({
15
- links,
16
-
17
- className,
18
- ...props
19
- }: HelpCardProps) {
20
- const helpLink = links?.find((l) => l.rel === 'help')
21
-
22
- if (!helpLink) return null
23
-
24
- return (
25
- <p
26
- {...props}
27
- className={clsx(
28
- 'text-sm rounded-md bg-slate-100 text-slate-800 dark:bg-slate-800 dark:text-slate-400 p-3',
29
- className,
30
- )}
31
- >
32
- <Trans>
33
- Having trouble?{' '}
34
- <a
35
- role="link"
36
- href={helpLink.href}
37
- rel={helpLink.rel}
38
- target="_blank"
39
- className="text-brand"
40
- >
41
- <Trans>Contact support</Trans>
42
- </a>
43
- </Trans>
44
- </p>
45
- )
46
- }
@@ -1,88 +0,0 @@
1
- import type { FunctionComponent, JSX } from 'react'
2
- import { Override } from '../../lib/util.ts'
3
-
4
- export type IconProps = Override<
5
- Omit<JSX.IntrinsicElements['svg'], 'viewBox' | 'children' | 'xmlns'>,
6
- {
7
- /**
8
- * The title of the icon, used for accessibility.
9
- */
10
- title?: string
11
- }
12
- >
13
-
14
- const makeSvgComponent = (path: string, displayName: string) => {
15
- const SvgComponent: FunctionComponent<IconProps> = ({ title, ...props }) => (
16
- <svg
17
- xmlns="http://www.w3.org/2000/svg"
18
- viewBox="0 0 24 24"
19
- {...props}
20
- aria-hidden={!title}
21
- >
22
- {title && <title>{title}</title>}
23
- <path
24
- fill="currentColor"
25
- fillRule="evenodd"
26
- clipRule="evenodd"
27
- d={path}
28
- ></path>
29
- </svg>
30
- )
31
- SvgComponent.displayName = displayName
32
- return SvgComponent
33
- }
34
-
35
- export const AccountIcon = makeSvgComponent(
36
- 'M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,14C16.42,14 20,15.79 20,18V20H4V18C4,15.79 7.58,14 12,14Z',
37
- 'AccountIcon',
38
- )
39
-
40
- export const AlertIcon = makeSvgComponent(
41
- 'M11.14 4.494a.995.995 0 0 1 1.72 0l7.001 12.008a.996.996 0 0 1-.86 1.498H4.999a.996.996 0 0 1-.86-1.498L11.14 4.494Zm3.447-1.007c-1.155-1.983-4.019-1.983-5.174 0L2.41 15.494C1.247 17.491 2.686 20 4.998 20h14.004c2.312 0 3.751-2.509 2.587-4.506L14.587 3.487ZM13 9.019a1 1 0 1 0-2 0v2.994a1 1 0 1 0 2 0V9.02Zm-1 4.731a1.25 1.25 0 1 0 0 2.5 1.25 1.25 0 0 0 0-2.5Z',
42
- 'AlertIcon',
43
- )
44
-
45
- export const AtSymbolIcon = makeSvgComponent(
46
- 'M12 4a8 8 0 1 0 4.21 14.804 1 1 0 0 1 1.054 1.7A9.958 9.958 0 0 1 12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10c0 1.104-.27 2.31-.949 3.243-.716.984-1.849 1.6-3.331 1.465a4.207 4.207 0 0 1-2.93-1.585c-.94 1.21-2.388 1.94-3.985 1.715-2.53-.356-4.04-2.91-3.682-5.458.358-2.547 2.514-4.586 5.044-4.23.905.127 1.68.536 2.286 1.126a1 1 0 0 1 1.964.368l-.515 3.545v.002a2.222 2.222 0 0 0 1.999 2.526c.75.068 1.212-.21 1.533-.65.358-.493.566-1.245.566-2.067a8 8 0 0 0-8-8Zm-.112 5.13c-1.195-.168-2.544.819-2.784 2.529-.24 1.71.784 3.03 1.98 3.198 1.195.168 2.543-.819 2.784-2.529.24-1.71-.784-3.03-1.98-3.198Z',
47
- 'AtSymbolIcon',
48
- )
49
-
50
- export const CaretRightIcon = makeSvgComponent(
51
- 'M8.293 3.293a1 1 0 0 1 1.414 0l8 8a1 1 0 0 1 0 1.414l-8 8a1 1 0 0 1-1.414-1.414L15.586 12 8.293 4.707a1 1 0 0 1 0-1.414Z',
52
- 'CaretRightIcon',
53
- )
54
-
55
- export const CheckMarkIcon = makeSvgComponent(
56
- 'M21.59 3.193a1 1 0 0 1 .217 1.397l-11.706 16a1 1 0 0 1-1.429.193l-6.294-5a1 1 0 1 1 1.244-1.566l5.48 4.353 11.09-15.16a1 1 0 0 1 1.398-.217Z',
57
- 'CheckMarkIcon',
58
- )
59
-
60
- export const EmailIcon = makeSvgComponent(
61
- 'M4.568 4h14.864c.252 0 .498 0 .706.017.229.019.499.063.77.201a2 2 0 0 1 .874.874c.138.271.182.541.201.77.017.208.017.454.017.706v10.864c0 .252 0 .498-.017.706a2.022 2.022 0 0 1-.201.77 2 2 0 0 1-.874.874 2.022 2.022 0 0 1-.77.201c-.208.017-.454.017-.706.017H4.568c-.252 0-.498 0-.706-.017a2.022 2.022 0 0 1-.77-.201 2 2 0 0 1-.874-.874 2.022 2.022 0 0 1-.201-.77C2 17.93 2 17.684 2 17.432V6.568c0-.252 0-.498.017-.706.019-.229.063-.499.201-.77a2 2 0 0 1 .874-.874c.271-.138.541-.182.77-.201C4.07 4 4.316 4 4.568 4Zm.456 2L12 11.708 18.976 6H5.024ZM20 7.747l-6.733 5.509a2 2 0 0 1-2.534 0L4 7.746V17.4a8.187 8.187 0 0 0 .011.589h.014c.116.01.278.011.575.011h14.8a8.207 8.207 0 0 0 .589-.012v-.013c.01-.116.011-.279.011-.575V7.747Z',
62
- 'EmailIcon',
63
- )
64
-
65
- export const EyeIcon = makeSvgComponent(
66
- 'M12 6.5c3.79 0 7.17 2.13 8.82 5.5-1.65 3.37-5.02 5.5-8.82 5.5S4.83 15.37 3.18 12C4.83 8.63 8.21 6.5 12 6.5m0-2C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5m0 5c1.38 0 2.5 1.12 2.5 2.5s-1.12 2.5-2.5 2.5-2.5-1.12-2.5-2.5 1.12-2.5 2.5-2.5m0-2c-2.48 0-4.5 2.02-4.5 4.5s2.02 4.5 4.5 4.5 4.5-2.02 4.5-4.5-2.02-4.5-4.5-4.5',
67
- 'EyeIcon',
68
- )
69
-
70
- export const EyeSlashIcon = makeSvgComponent(
71
- 'M12 6c3.79 0 7.17 2.13 8.82 5.5-.59 1.22-1.42 2.27-2.41 3.12l1.41 1.41c1.39-1.23 2.49-2.77 3.18-4.53C21.27 7.11 17 4 12 4c-1.27 0-2.49.2-3.64.57l1.65 1.65C10.66 6.09 11.32 6 12 6m-1.07 1.14L13 9.21c.57.25 1.03.71 1.28 1.28l2.07 2.07c.08-.34.14-.7.14-1.07C16.5 9.01 14.48 7 12 7c-.37 0-.72.05-1.07.14M2.01 3.87l2.68 2.68C3.06 7.83 1.77 9.53 1 11.5 2.73 15.89 7 19 12 19c1.52 0 2.98-.29 4.32-.82l3.42 3.42 1.41-1.41L3.42 2.45zm7.5 7.5 2.61 2.61c-.04.01-.08.02-.12.02-1.38 0-2.5-1.12-2.5-2.5 0-.05.01-.08.01-.13m-3.4-3.4 1.75 1.75c-.23.55-.36 1.15-.36 1.78 0 2.48 2.02 4.5 4.5 4.5.63 0 1.23-.13 1.77-.36l.98.98c-.88.24-1.8.38-2.75.38-3.79 0-7.17-2.13-8.82-5.5.7-1.43 1.72-2.61 2.93-3.53',
72
- 'EyeSlashIcon',
73
- )
74
-
75
- export const LockIcon = makeSvgComponent(
76
- 'M7 7a5 5 0 0 1 10 0v2h1a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-9a2 2 0 0 1 2-2h1V7Zm-1 4v9h12v-9H6Zm9-2H9V7a3 3 0 1 1 6 0v2Zm-3 4a1 1 0 0 1 1 1v3a1 1 0 1 1-2 0v-3a1 1 0 0 1 1-1Z',
77
- 'LockIcon',
78
- )
79
-
80
- export const TokenIcon = makeSvgComponent(
81
- 'M4 5.5a.5.5 0 0 0-.5.5v2.535a.5.5 0 0 0 .25.433A3.498 3.498 0 0 1 5.5 12a3.498 3.498 0 0 1-1.75 3.032.5.5 0 0 0-.25.433V18a.5.5 0 0 0 .5.5h16a.5.5 0 0 0 .5-.5v-2.535a.5.5 0 0 0-.25-.433A3.498 3.498 0 0 1 18.5 12a3.5 3.5 0 0 1 1.75-3.032.5.5 0 0 0 .25-.433V6a.5.5 0 0 0-.5-.5H4ZM2.5 6A1.5 1.5 0 0 1 4 4.5h16A1.5 1.5 0 0 1 21.5 6v3.17a.5.5 0 0 1-.333.472 2.501 2.501 0 0 0 0 4.716.5.5 0 0 1 .333.471V18a1.5 1.5 0 0 1-1.5 1.5H4A1.5 1.5 0 0 1 2.5 18v-3.17a.5.5 0 0 1 .333-.472 2.501 2.501 0 0 0 0-4.716.5.5 0 0 1-.333-.471V6Zm12 2a.5.5 0 1 1 1 0 .5.5 0 0 1-1 0Zm0 4a.5.5 0 1 1 1 0 .5.5 0 0 1-1 0Zm0 4a.5.5 0 1 1 1 0 .5.5 0 0 1-1 0Z',
82
- 'TokenIcon',
83
- )
84
-
85
- export const XMarkIcon = makeSvgComponent(
86
- 'M4.293 4.293a1 1 0 0 1 1.414 0L12 10.586l6.293-6.293a1 1 0 1 1 1.414 1.414L13.414 12l6.293 6.293a1 1 0 0 1-1.414 1.414L12 13.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L10.586 12 4.293 5.707a1 1 0 0 1 0-1.414Z',
87
- 'XMarkIcon',
88
- )
@@ -1,28 +0,0 @@
1
- import { JSX } from 'react'
2
- import { LinkDefinition } from '../../backend-types.ts'
3
- import { Override } from '../../lib/util.ts'
4
- import { LinkTitle } from './link-title.tsx'
5
-
6
- export type LinkAnchorProps = Override<
7
- JSX.IntrinsicElements['a'],
8
- {
9
- link: LinkDefinition
10
- }
11
- >
12
- export function LinkAnchor({
13
- link,
14
-
15
- // a
16
- children = <LinkTitle link={link} />,
17
- role = 'link',
18
- target = '_blank',
19
- href = link.href,
20
- rel = link.rel,
21
- ...props
22
- }: LinkAnchorProps) {
23
- return (
24
- <a {...props} role={role} target={target} href={href} rel={rel}>
25
- {children}
26
- </a>
27
- )
28
- }
@@ -1,26 +0,0 @@
1
- import { Trans } from '@lingui/react/macro'
2
- import { LinkDefinition } from '../../backend-types.ts'
3
- import { MultiLangString } from './multi-lang-string.tsx'
4
-
5
- export type LinkNameProps = {
6
- link: LinkDefinition
7
- }
8
-
9
- export function LinkTitle({ link }: LinkNameProps) {
10
- return (
11
- <MultiLangString
12
- value={link.title}
13
- fallback={
14
- link.rel === 'canonical' ? (
15
- <Trans>Home</Trans>
16
- ) : link.rel === 'privacy-policy' ? (
17
- <Trans>Privacy Policy</Trans>
18
- ) : link.rel === 'terms-of-service' ? (
19
- <Trans>Terms of Service</Trans>
20
- ) : link.rel === 'help' ? (
21
- <Trans>Support</Trans>
22
- ) : undefined
23
- }
24
- />
25
- )
26
- }
@@ -1,56 +0,0 @@
1
- import { useLingui } from '@lingui/react/macro'
2
- import { ReactNode } from 'react'
3
- import type { LocalizedString } from '../../backend-types.ts'
4
-
5
- export type MultiLangStringProps = {
6
- value: LocalizedString
7
- fallback?: ReactNode
8
- }
9
-
10
- export function MultiLangString({
11
- value,
12
- fallback,
13
- }: MultiLangStringProps): ReactNode {
14
- const { i18n } = useLingui()
15
- return (
16
- findMatchingString(value, i18n.locale) ??
17
- fallback ??
18
- (typeof value === 'string' ? value : value.en)
19
- )
20
- }
21
-
22
- /**
23
- * Only returns a string if it matches the desired locale.
24
- */
25
- function findMatchingString(
26
- value: LocalizedString,
27
- locale: string,
28
- ): string | undefined {
29
- switch (typeof value) {
30
- case 'string':
31
- // By convention, string values are in english ("en")
32
- if (locale.startsWith('en')) return value
33
- break
34
-
35
- case 'object': {
36
- // Exact match
37
- const localeMatch = value[locale]
38
- if (typeof localeMatch === 'string') return localeMatch
39
-
40
- // Fallback to language match
41
- const lang = locale.split('-')[0]
42
- const langMatch = value[lang]
43
- if (typeof langMatch === 'string') return langMatch
44
-
45
- // Fallback to any locale from same language (e.g. "pt-PT" -> "pt-BR")
46
- for (const k in value) {
47
- if (k.startsWith(`${lang}-`)) {
48
- const fallbackMatch = value[k]
49
- if (typeof fallbackMatch === 'string') return fallbackMatch
50
- }
51
- }
52
- }
53
- }
54
-
55
- return undefined
56
- }
@@ -1,37 +0,0 @@
1
- import { Trans, useLingui } from '@lingui/react/macro'
2
- import { JSX } from 'react'
3
- import { PasswordStrength, getPasswordStrength } from '../../lib/password.ts'
4
- import { Override } from '../../lib/util.ts'
5
-
6
- export type PasswordStrengthLabelProps = Override<
7
- Omit<JSX.IntrinsicElements['span'], 'children' | 'aria-label'>,
8
- {
9
- password: string
10
- }
11
- >
12
-
13
- export function PasswordStrengthLabel({
14
- password,
15
-
16
- // span
17
- ...props
18
- }: PasswordStrengthLabelProps) {
19
- const { t } = useLingui()
20
- const strength = getPasswordStrength(password)
21
-
22
- return (
23
- <span {...props} aria-label={t`Password strength`}>
24
- {strength === PasswordStrength.extra ? (
25
- <Trans>Extra</Trans>
26
- ) : strength === PasswordStrength.strong ? (
27
- <Trans>Strong</Trans>
28
- ) : strength === PasswordStrength.moderate ? (
29
- <Trans>Moderate</Trans>
30
- ) : password ? (
31
- <Trans>Weak</Trans>
32
- ) : (
33
- <Trans>Missing</Trans>
34
- )}
35
- </span>
36
- )
37
- }