@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.
- package/CHANGELOG.md +31 -0
- package/dist/account/account-manager.d.ts +7 -5
- package/dist/account/account-manager.d.ts.map +1 -1
- package/dist/account/account-manager.js +34 -25
- package/dist/account/account-manager.js.map +1 -1
- package/dist/account/account-store.d.ts +7 -0
- package/dist/account/account-store.d.ts.map +1 -1
- package/dist/account/account-store.js.map +1 -1
- package/dist/account/account.d.ts +1 -11
- package/dist/account/account.d.ts.map +1 -1
- package/dist/account/{sign-up-data.d.ts → sign-up-input.d.ts} +3 -3
- package/dist/account/sign-up-input.d.ts.map +1 -0
- package/dist/account/{sign-up-data.js → sign-up-input.js} +3 -3
- package/dist/account/sign-up-input.js.map +1 -0
- package/dist/assets/assets-middleware.d.ts +2 -0
- package/dist/assets/assets-middleware.d.ts.map +1 -1
- package/dist/assets/assets-middleware.js +12 -14
- package/dist/assets/assets-middleware.js.map +1 -1
- package/dist/lib/csp/index.d.ts +5 -6
- package/dist/lib/csp/index.d.ts.map +1 -1
- package/dist/lib/csp/index.js +14 -11
- package/dist/lib/csp/index.js.map +1 -1
- package/dist/lib/hcaptcha.d.ts +5 -3
- package/dist/lib/hcaptcha.d.ts.map +1 -1
- package/dist/lib/hcaptcha.js +7 -4
- package/dist/lib/hcaptcha.js.map +1 -1
- package/dist/lib/html/build-document.d.ts +2 -2
- package/dist/lib/html/build-document.d.ts.map +1 -1
- package/dist/lib/html/build-document.js +11 -7
- package/dist/lib/html/build-document.js.map +1 -1
- package/dist/lib/html/html.d.ts.map +1 -1
- package/dist/lib/html/html.js +10 -13
- package/dist/lib/html/html.js.map +1 -1
- package/dist/lib/html/util.d.ts +0 -1
- package/dist/lib/html/util.d.ts.map +1 -1
- package/dist/lib/html/util.js +0 -4
- package/dist/lib/html/util.js.map +1 -1
- package/dist/lib/http/response.d.ts +3 -1
- package/dist/lib/http/response.d.ts.map +1 -1
- package/dist/lib/http/response.js +3 -0
- package/dist/lib/http/response.js.map +1 -1
- package/dist/lib/http/security-headers.d.ts +48 -0
- package/dist/lib/http/security-headers.d.ts.map +1 -0
- package/dist/lib/http/security-headers.js +62 -0
- package/dist/lib/http/security-headers.js.map +1 -0
- package/dist/lib/util/type.d.ts +8 -0
- package/dist/lib/util/type.d.ts.map +1 -1
- package/dist/lib/util/type.js.map +1 -1
- package/dist/oauth-hooks.d.ts +4 -25
- package/dist/oauth-hooks.d.ts.map +1 -1
- package/dist/oauth-provider.js +2 -2
- package/dist/oauth-provider.js.map +1 -1
- package/dist/output/backend-data.d.ts +4 -0
- package/dist/output/backend-data.d.ts.map +1 -0
- package/dist/output/backend-data.js +19 -0
- package/dist/output/backend-data.js.map +1 -0
- package/dist/output/build-authorize-data.d.ts +3 -19
- package/dist/output/build-authorize-data.d.ts.map +1 -1
- package/dist/output/build-authorize-data.js.map +1 -1
- package/dist/output/build-customization-data.d.ts +11 -18
- package/dist/output/build-customization-data.d.ts.map +1 -1
- package/dist/output/build-customization-data.js +1 -1
- package/dist/output/build-customization-data.js.map +1 -1
- package/dist/output/build-error-data.d.ts +3 -0
- package/dist/output/build-error-data.d.ts.map +1 -0
- package/dist/output/build-error-data.js +10 -0
- package/dist/output/build-error-data.js.map +1 -0
- package/dist/output/build-error-payload.d.ts +2 -1
- package/dist/output/build-error-payload.d.ts.map +1 -1
- package/dist/output/build-error-payload.js.map +1 -1
- package/dist/output/output-manager.d.ts +10 -4
- package/dist/output/output-manager.d.ts.map +1 -1
- package/dist/output/output-manager.js +68 -39
- package/dist/output/output-manager.js.map +1 -1
- package/dist/output/send-web-page.d.ts +6 -10
- package/dist/output/send-web-page.d.ts.map +1 -1
- package/dist/output/send-web-page.js +27 -47
- package/dist/output/send-web-page.js.map +1 -1
- package/dist/signer/signed-token-payload.d.ts +3 -3
- package/dist/signer/signer.d.ts +2 -2
- package/package.json +7 -40
- package/src/account/account-manager.ts +55 -34
- package/src/account/account-store.ts +8 -0
- package/src/account/account.ts +1 -14
- package/src/account/{sign-up-data.ts → sign-up-input.ts} +2 -2
- package/src/assets/assets-middleware.ts +11 -17
- package/src/lib/csp/index.ts +16 -13
- package/src/lib/hcaptcha.ts +10 -7
- package/src/lib/html/build-document.ts +15 -8
- package/src/lib/html/html.ts +11 -18
- package/src/lib/html/util.ts +0 -4
- package/src/lib/http/response.ts +9 -1
- package/src/lib/http/security-headers.ts +91 -0
- package/src/lib/util/type.ts +18 -0
- package/src/oauth-hooks.ts +4 -25
- package/src/oauth-provider.ts +2 -2
- package/src/output/backend-data.ts +18 -0
- package/src/output/build-authorize-data.ts +3 -26
- package/src/output/build-customization-data.ts +2 -13
- package/src/output/build-error-data.ts +8 -0
- package/src/output/build-error-payload.ts +4 -2
- package/src/output/output-manager.ts +86 -47
- package/src/output/send-web-page.ts +29 -58
- package/tsconfig.backend.json +1 -2
- package/tsconfig.backend.tsbuildinfo +1 -1
- package/tsconfig.json +1 -5
- package/.linguirc +0 -57
- package/dist/account/sign-up-data.d.ts.map +0 -1
- package/dist/account/sign-up-data.js.map +0 -1
- package/dist/assets/app/bundle-manifest.json +0 -614
- package/dist/assets/app/index-DZHZ9kCP.js +0 -36
- package/dist/assets/app/index-DZHZ9kCP.js.map +0 -1
- package/dist/assets/app/main-B_dNxQo_.js +0 -4
- package/dist/assets/app/main-B_dNxQo_.js.map +0 -1
- package/dist/assets/app/main-Dr6y26KY.css +0 -3
- package/dist/assets/app/main-Dr6y26KY.js +0 -306
- package/dist/assets/app/main-Dr6y26KY.js.map +0 -1
- package/dist/assets/app/messages-6_mYuGzB.js +0 -4
- package/dist/assets/app/messages-6_mYuGzB.js.map +0 -1
- package/dist/assets/app/messages-7wdeBTpD.js +0 -4
- package/dist/assets/app/messages-7wdeBTpD.js.map +0 -1
- package/dist/assets/app/messages-B-YFoWKc.js +0 -4
- package/dist/assets/app/messages-B-YFoWKc.js.map +0 -1
- package/dist/assets/app/messages-B10DUOE-.js +0 -4
- package/dist/assets/app/messages-B10DUOE-.js.map +0 -1
- package/dist/assets/app/messages-B4AwFEeZ.js +0 -4
- package/dist/assets/app/messages-B4AwFEeZ.js.map +0 -1
- package/dist/assets/app/messages-BDP8MyEC.js +0 -4
- package/dist/assets/app/messages-BDP8MyEC.js.map +0 -1
- package/dist/assets/app/messages-BIS87lxQ.js +0 -4
- package/dist/assets/app/messages-BIS87lxQ.js.map +0 -1
- package/dist/assets/app/messages-BI_Wbjdt.js +0 -4
- package/dist/assets/app/messages-BI_Wbjdt.js.map +0 -1
- package/dist/assets/app/messages-BMAouhRx.js +0 -4
- package/dist/assets/app/messages-BMAouhRx.js.map +0 -1
- package/dist/assets/app/messages-BdckMnJj.js +0 -4
- package/dist/assets/app/messages-BdckMnJj.js.map +0 -1
- package/dist/assets/app/messages-BgBLzc46.js +0 -4
- package/dist/assets/app/messages-BgBLzc46.js.map +0 -1
- package/dist/assets/app/messages-BobD78yK.js +0 -4
- package/dist/assets/app/messages-BobD78yK.js.map +0 -1
- package/dist/assets/app/messages-BtThT9UZ.js +0 -4
- package/dist/assets/app/messages-BtThT9UZ.js.map +0 -1
- package/dist/assets/app/messages-BwKHkbeh.js +0 -4
- package/dist/assets/app/messages-BwKHkbeh.js.map +0 -1
- package/dist/assets/app/messages-C417YUvA.js +0 -4
- package/dist/assets/app/messages-C417YUvA.js.map +0 -1
- package/dist/assets/app/messages-C4CxO4bO.js +0 -4
- package/dist/assets/app/messages-C4CxO4bO.js.map +0 -1
- package/dist/assets/app/messages-C5vd04e6.js +0 -4
- package/dist/assets/app/messages-C5vd04e6.js.map +0 -1
- package/dist/assets/app/messages-CAri2Wnz.js +0 -4
- package/dist/assets/app/messages-CAri2Wnz.js.map +0 -1
- package/dist/assets/app/messages-CPtWTZeG.js +0 -4
- package/dist/assets/app/messages-CPtWTZeG.js.map +0 -1
- package/dist/assets/app/messages-CiaM5zm8.js +0 -4
- package/dist/assets/app/messages-CiaM5zm8.js.map +0 -1
- package/dist/assets/app/messages-CkL-L2R6.js +0 -4
- package/dist/assets/app/messages-CkL-L2R6.js.map +0 -1
- package/dist/assets/app/messages-Cy_4XLNe.js +0 -4
- package/dist/assets/app/messages-Cy_4XLNe.js.map +0 -1
- package/dist/assets/app/messages-D5_ad-Eo.js +0 -4
- package/dist/assets/app/messages-D5_ad-Eo.js.map +0 -1
- package/dist/assets/app/messages-DChMl9mT.js +0 -4
- package/dist/assets/app/messages-DChMl9mT.js.map +0 -1
- package/dist/assets/app/messages-DWX-DIfv.js +0 -4
- package/dist/assets/app/messages-DWX-DIfv.js.map +0 -1
- package/dist/assets/app/messages-DgfsOphe.js +0 -4
- package/dist/assets/app/messages-DgfsOphe.js.map +0 -1
- package/dist/assets/app/messages-Dj5B_DR6.js +0 -4
- package/dist/assets/app/messages-Dj5B_DR6.js.map +0 -1
- package/dist/assets/app/messages-Dwzqo4eA.js +0 -4
- package/dist/assets/app/messages-Dwzqo4eA.js.map +0 -1
- package/dist/assets/app/messages-ESCIXJR7.js +0 -4
- package/dist/assets/app/messages-ESCIXJR7.js.map +0 -1
- package/dist/assets/app/messages-dglB2edb.js +0 -4
- package/dist/assets/app/messages-dglB2edb.js.map +0 -1
- package/dist/assets/app/messages-e_ClRrWc.js +0 -4
- package/dist/assets/app/messages-e_ClRrWc.js.map +0 -1
- package/dist/assets/app/messages-evvDxmrP.js +0 -4
- package/dist/assets/app/messages-evvDxmrP.js.map +0 -1
- package/dist/assets/app/messages-pPbdLb5B.js +0 -4
- package/dist/assets/app/messages-pPbdLb5B.js.map +0 -1
- package/dist/assets/app/messages-tJv8gHL2.js +0 -4
- package/dist/assets/app/messages-tJv8gHL2.js.map +0 -1
- package/dist/assets/app/messages-vLRVEw96.js +0 -4
- package/dist/assets/app/messages-vLRVEw96.js.map +0 -1
- package/dist/assets/asset.d.ts +0 -9
- package/dist/assets/asset.d.ts.map +0 -1
- package/dist/assets/asset.js +0 -3
- package/dist/assets/asset.js.map +0 -1
- package/dist/assets/index.d.ts +0 -5
- package/dist/assets/index.d.ts.map +0 -1
- package/dist/assets/index.js +0 -78
- package/dist/assets/index.js.map +0 -1
- package/rollup.config.js +0 -98
- package/src/assets/app/app.tsx +0 -43
- package/src/assets/app/backend-data.ts +0 -27
- package/src/assets/app/backend-types.ts +0 -66
- package/src/assets/app/components/forms/button-toggle-visibility.tsx +0 -43
- package/src/assets/app/components/forms/button.tsx +0 -60
- package/src/assets/app/components/forms/fieldset.tsx +0 -55
- package/src/assets/app/components/forms/form-card-async.tsx +0 -103
- package/src/assets/app/components/forms/form-card.tsx +0 -49
- package/src/assets/app/components/forms/input-checkbox.tsx +0 -78
- package/src/assets/app/components/forms/input-container.tsx +0 -107
- package/src/assets/app/components/forms/input-email-address.tsx +0 -65
- package/src/assets/app/components/forms/input-new-password.tsx +0 -62
- package/src/assets/app/components/forms/input-password.tsx +0 -87
- package/src/assets/app/components/forms/input-text.tsx +0 -82
- package/src/assets/app/components/forms/input-token.tsx +0 -94
- package/src/assets/app/components/forms/wizard-card.tsx +0 -116
- package/src/assets/app/components/layouts/layout-title-page.tsx +0 -77
- package/src/assets/app/components/layouts/layout-welcome.tsx +0 -73
- package/src/assets/app/components/utils/account-identifier.tsx +0 -23
- package/src/assets/app/components/utils/account-image.tsx +0 -33
- package/src/assets/app/components/utils/admonition.tsx +0 -52
- package/src/assets/app/components/utils/client-name.tsx +0 -45
- package/src/assets/app/components/utils/error-card.tsx +0 -93
- package/src/assets/app/components/utils/error-message.tsx +0 -88
- package/src/assets/app/components/utils/help-card.tsx +0 -46
- package/src/assets/app/components/utils/icons.tsx +0 -88
- package/src/assets/app/components/utils/link-anchor.tsx +0 -28
- package/src/assets/app/components/utils/link-title.tsx +0 -26
- package/src/assets/app/components/utils/multi-lang-string.tsx +0 -56
- package/src/assets/app/components/utils/password-strength-label.tsx +0 -37
- package/src/assets/app/components/utils/password-strength-meter.tsx +0 -58
- package/src/assets/app/components/utils/url-viewer.tsx +0 -73
- package/src/assets/app/cookies.ts +0 -11
- package/src/assets/app/hooks/use-api.ts +0 -178
- package/src/assets/app/hooks/use-async-action.ts +0 -120
- package/src/assets/app/hooks/use-bound-dispatch.ts +0 -5
- package/src/assets/app/hooks/use-browser-color-scheme.ts +0 -31
- package/src/assets/app/hooks/use-csrf-token.ts +0 -5
- package/src/assets/app/hooks/use-random-string.ts +0 -37
- package/src/assets/app/hooks/use-stepper.ts +0 -87
- package/src/assets/app/index.html +0 -182
- package/src/assets/app/lib/api.ts +0 -289
- package/src/assets/app/lib/clsx.ts +0 -6
- package/src/assets/app/lib/json-client.ts +0 -94
- package/src/assets/app/lib/password.ts +0 -98
- package/src/assets/app/lib/ref.ts +0 -17
- package/src/assets/app/lib/util.ts +0 -13
- package/src/assets/app/locales/an/messages.po +0 -490
- package/src/assets/app/locales/ast/messages.po +0 -490
- package/src/assets/app/locales/ca/messages.po +0 -490
- package/src/assets/app/locales/da/messages.po +0 -490
- package/src/assets/app/locales/de/messages.po +0 -490
- package/src/assets/app/locales/el/messages.po +0 -490
- package/src/assets/app/locales/en/messages.po +0 -490
- package/src/assets/app/locales/en-GB/messages.po +0 -490
- package/src/assets/app/locales/es/messages.po +0 -490
- package/src/assets/app/locales/eu/messages.po +0 -490
- package/src/assets/app/locales/fi/messages.po +0 -490
- package/src/assets/app/locales/fr/messages.po +0 -490
- package/src/assets/app/locales/ga/messages.po +0 -490
- package/src/assets/app/locales/gl/messages.po +0 -490
- package/src/assets/app/locales/hi/messages.po +0 -490
- package/src/assets/app/locales/hu/messages.po +0 -490
- package/src/assets/app/locales/ia/messages.po +0 -490
- package/src/assets/app/locales/id/messages.po +0 -490
- package/src/assets/app/locales/it/messages.po +0 -490
- package/src/assets/app/locales/ja/messages.po +0 -490
- package/src/assets/app/locales/km/messages.po +0 -490
- package/src/assets/app/locales/ko/messages.po +0 -490
- package/src/assets/app/locales/load.ts +0 -8
- package/src/assets/app/locales/locale-context.ts +0 -19
- package/src/assets/app/locales/locale-provider.tsx +0 -112
- package/src/assets/app/locales/locale-selector.tsx +0 -58
- package/src/assets/app/locales/locales.ts +0 -168
- package/src/assets/app/locales/ne/messages.po +0 -490
- package/src/assets/app/locales/nl/messages.po +0 -490
- package/src/assets/app/locales/pl/messages.po +0 -490
- package/src/assets/app/locales/pt-BR/messages.po +0 -490
- package/src/assets/app/locales/ro/messages.po +0 -490
- package/src/assets/app/locales/ru/messages.po +0 -490
- package/src/assets/app/locales/sv/messages.po +0 -490
- package/src/assets/app/locales/th/messages.po +0 -490
- package/src/assets/app/locales/tr/messages.po +0 -490
- package/src/assets/app/locales/uk/messages.po +0 -490
- package/src/assets/app/locales/vi/messages.po +0 -490
- package/src/assets/app/locales/zh-CN/messages.po +0 -490
- package/src/assets/app/locales/zh-HK/messages.po +0 -490
- package/src/assets/app/locales/zh-TW/messages.po +0 -490
- package/src/assets/app/main.css +0 -33
- package/src/assets/app/main.tsx +0 -44
- package/src/assets/app/views/authorize/accept/accept-form.tsx +0 -150
- package/src/assets/app/views/authorize/accept/accept-view.tsx +0 -70
- package/src/assets/app/views/authorize/authorize-view.tsx +0 -180
- package/src/assets/app/views/authorize/reset-password/reset-password-confirm-form.tsx +0 -88
- package/src/assets/app/views/authorize/reset-password/reset-password-request-form.tsx +0 -80
- package/src/assets/app/views/authorize/reset-password/reset-password-view.tsx +0 -127
- package/src/assets/app/views/authorize/sign-in/sign-in-form.tsx +0 -242
- package/src/assets/app/views/authorize/sign-in/sign-in-picker.tsx +0 -116
- package/src/assets/app/views/authorize/sign-in/sign-in-view.tsx +0 -145
- package/src/assets/app/views/authorize/sign-up/sign-up-account-form.tsx +0 -142
- package/src/assets/app/views/authorize/sign-up/sign-up-disclaimer.tsx +0 -51
- package/src/assets/app/views/authorize/sign-up/sign-up-handle-form.tsx +0 -287
- package/src/assets/app/views/authorize/sign-up/sign-up-hcaptcha-form.tsx +0 -108
- package/src/assets/app/views/authorize/sign-up/sign-up-view.tsx +0 -158
- package/src/assets/app/views/authorize/welcome/welcome-view.tsx +0 -56
- package/src/assets/app/views/error/error-view.tsx +0 -31
- package/src/assets/asset.ts +0 -9
- package/src/assets/index.ts +0 -86
- package/tailwind.config.js +0 -31
- package/tsconfig.frontend.json +0 -11
- package/tsconfig.frontend.tsbuildinfo +0 -1
- package/tsconfig.tools.json +0 -8
- package/tsconfig.tools.tsbuildinfo +0 -1
- 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,88 +0,0 @@
|
|
1
|
-
import { Trans } from '@lingui/react/macro'
|
2
|
-
import { ReactNode, memo } from 'react'
|
3
|
-
import {
|
4
|
-
AccessDeniedError,
|
5
|
-
EmailTakenError,
|
6
|
-
HandleUnavailableError,
|
7
|
-
InvalidCredentialsError,
|
8
|
-
InvalidInviteCodeError,
|
9
|
-
InvalidRequestError,
|
10
|
-
RequestExpiredError,
|
11
|
-
SecondAuthenticationFactorRequiredError,
|
12
|
-
UnknownRequestUriError,
|
13
|
-
} from '../../lib/api.ts'
|
14
|
-
import { JsonErrorResponse } from '../../lib/json-client.ts'
|
15
|
-
|
16
|
-
export type ApiErrorMessageProps = {
|
17
|
-
error: unknown
|
18
|
-
}
|
19
|
-
|
20
|
-
export const ErrorMessage = memo(function ErrorMessage({
|
21
|
-
error,
|
22
|
-
}: ApiErrorMessageProps): ReactNode {
|
23
|
-
// Matches the order of the error checks in the API's parseError method (must
|
24
|
-
// be from most specific to least specific to avoid unreachable code paths).
|
25
|
-
|
26
|
-
if (error instanceof SecondAuthenticationFactorRequiredError) {
|
27
|
-
return <Trans>A second authentication factor is required</Trans>
|
28
|
-
}
|
29
|
-
|
30
|
-
if (error instanceof InvalidCredentialsError) {
|
31
|
-
return <Trans>Wrong identifier or password</Trans>
|
32
|
-
}
|
33
|
-
|
34
|
-
if (error instanceof InvalidInviteCodeError) {
|
35
|
-
return <Trans>The invite code is not valid</Trans>
|
36
|
-
}
|
37
|
-
|
38
|
-
if (error instanceof HandleUnavailableError) {
|
39
|
-
switch (error.reason) {
|
40
|
-
case 'syntax':
|
41
|
-
return <Trans>The handle is invalid</Trans>
|
42
|
-
case 'domain':
|
43
|
-
return <Trans>The domain name is not allowed</Trans>
|
44
|
-
case 'slur':
|
45
|
-
return <Trans>The handle contains inappropriate language</Trans>
|
46
|
-
case 'taken':
|
47
|
-
if (error.description === 'Reserved handle') {
|
48
|
-
return <Trans>This handle is reserved</Trans>
|
49
|
-
}
|
50
|
-
return <Trans>The handle is already in use</Trans>
|
51
|
-
default:
|
52
|
-
return <Trans>That handle cannot be used</Trans>
|
53
|
-
}
|
54
|
-
}
|
55
|
-
|
56
|
-
if (error instanceof EmailTakenError) {
|
57
|
-
return <Trans>This email is already used</Trans>
|
58
|
-
}
|
59
|
-
|
60
|
-
if (
|
61
|
-
error instanceof UnknownRequestUriError ||
|
62
|
-
error instanceof RequestExpiredError
|
63
|
-
) {
|
64
|
-
return <Trans>This sign-in session has expired</Trans>
|
65
|
-
}
|
66
|
-
|
67
|
-
if (error instanceof InvalidRequestError) {
|
68
|
-
return (
|
69
|
-
<Trans>
|
70
|
-
The data you submitted is invalid. Please check the form and try again.
|
71
|
-
</Trans>
|
72
|
-
)
|
73
|
-
}
|
74
|
-
|
75
|
-
if (error instanceof AccessDeniedError) {
|
76
|
-
return (
|
77
|
-
<Trans>
|
78
|
-
This authorization request has been denied. Please try again.
|
79
|
-
</Trans>
|
80
|
-
)
|
81
|
-
}
|
82
|
-
|
83
|
-
if (error instanceof JsonErrorResponse) {
|
84
|
-
return <Trans>Unexpected server response</Trans>
|
85
|
-
}
|
86
|
-
|
87
|
-
return <Trans>An unknown error occurred</Trans>
|
88
|
-
})
|
@@ -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
|
-
}
|