@atproto/oauth-provider-ui 0.1.0 → 0.1.1
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/dist/authorization-page-Cms-rcBA.js +3 -0
- package/dist/authorization-page-Cms-rcBA.js.map +1 -0
- package/dist/bundle-manifest.json +630 -0
- package/dist/error-page-DC6Vc-cv.js +2 -0
- package/dist/error-page-DC6Vc-cv.js.map +1 -0
- package/dist/error-view-CRGNTAn2.css +1 -0
- package/dist/error-view-MVy7C9l0.js +59 -0
- package/dist/error-view-MVy7C9l0.js.map +1 -0
- package/dist/index-CHPoD7Rp.js +20 -0
- package/dist/index-CHPoD7Rp.js.map +1 -0
- package/dist/messages-B0mgsxS-.js +2 -0
- package/dist/messages-B0mgsxS-.js.map +1 -0
- package/dist/messages-B5g8Fkio.js +2 -0
- package/dist/messages-B5g8Fkio.js.map +1 -0
- package/dist/messages-BCMss-Kt.js +2 -0
- package/dist/messages-BCMss-Kt.js.map +1 -0
- package/dist/messages-BGUrKgyK.js +2 -0
- package/dist/messages-BGUrKgyK.js.map +1 -0
- package/dist/messages-BjxAnLDp.js +2 -0
- package/dist/messages-BjxAnLDp.js.map +1 -0
- package/dist/messages-Bjysz3rI.js +2 -0
- package/dist/messages-Bjysz3rI.js.map +1 -0
- package/dist/messages-BvvEr3UX.js +2 -0
- package/dist/messages-BvvEr3UX.js.map +1 -0
- package/dist/messages-Bz6JOhJf.js +2 -0
- package/dist/messages-Bz6JOhJf.js.map +1 -0
- package/dist/messages-BzL3D1EU.js +2 -0
- package/dist/messages-BzL3D1EU.js.map +1 -0
- package/dist/messages-CAvN5UoW.js +2 -0
- package/dist/messages-CAvN5UoW.js.map +1 -0
- package/dist/messages-CEmswT1Q.js +2 -0
- package/dist/messages-CEmswT1Q.js.map +1 -0
- package/dist/messages-CHYqz0q6.js +2 -0
- package/dist/messages-CHYqz0q6.js.map +1 -0
- package/dist/messages-CRmpdijj.js +2 -0
- package/dist/messages-CRmpdijj.js.map +1 -0
- package/dist/messages-Cdb79R6S.js +2 -0
- package/dist/messages-Cdb79R6S.js.map +1 -0
- package/dist/messages-ChkJ_0WT.js +2 -0
- package/dist/messages-ChkJ_0WT.js.map +1 -0
- package/dist/messages-CqiEX6JJ.js +2 -0
- package/dist/messages-CqiEX6JJ.js.map +1 -0
- package/dist/messages-CxkHjJSR.js +2 -0
- package/dist/messages-CxkHjJSR.js.map +1 -0
- package/dist/messages-D0-cWoJ9.js +2 -0
- package/dist/messages-D0-cWoJ9.js.map +1 -0
- package/dist/messages-D2MnAxYY.js +2 -0
- package/dist/messages-D2MnAxYY.js.map +1 -0
- package/dist/messages-D5TZVsui.js +2 -0
- package/dist/messages-D5TZVsui.js.map +1 -0
- package/dist/messages-DBdV4-iw.js +2 -0
- package/dist/messages-DBdV4-iw.js.map +1 -0
- package/dist/messages-DEK3zybC.js +2 -0
- package/dist/messages-DEK3zybC.js.map +1 -0
- package/dist/messages-DGSM5jkd.js +2 -0
- package/dist/messages-DGSM5jkd.js.map +1 -0
- package/dist/messages-DJgAnSTQ.js +2 -0
- package/dist/messages-DJgAnSTQ.js.map +1 -0
- package/dist/messages-DK7O7sb_.js +2 -0
- package/dist/messages-DK7O7sb_.js.map +1 -0
- package/dist/messages-DRp7qc3j.js +2 -0
- package/dist/messages-DRp7qc3j.js.map +1 -0
- package/dist/messages-DT6xRw0m.js +2 -0
- package/dist/messages-DT6xRw0m.js.map +1 -0
- package/dist/messages-LnzLtU0L.js +2 -0
- package/dist/messages-LnzLtU0L.js.map +1 -0
- package/dist/messages-_Nk2qNGw.js +2 -0
- package/dist/messages-_Nk2qNGw.js.map +1 -0
- package/dist/messages-eHH6nZyF.js +2 -0
- package/dist/messages-eHH6nZyF.js.map +1 -0
- package/dist/messages-iNw8zY2C.js +2 -0
- package/dist/messages-iNw8zY2C.js.map +1 -0
- package/dist/messages-ipc0L8yF.js +2 -0
- package/dist/messages-ipc0L8yF.js.map +1 -0
- package/dist/messages-j7LsWm2F.js +2 -0
- package/dist/messages-j7LsWm2F.js.map +1 -0
- package/dist/messages-mgE_5UEw.js +2 -0
- package/dist/messages-mgE_5UEw.js.map +1 -0
- package/dist/messages-oRd-J5--.js +2 -0
- package/dist/messages-oRd-J5--.js.map +1 -0
- package/package.json +10 -8
- package/.linguirc +0 -57
- package/CHANGELOG.md +0 -17
- package/CONTRIBUTING.md +0 -6
- package/authorization-page.html +0 -186
- package/error-page.html +0 -118
- package/index.html +0 -13
- package/src/authorization-page.tsx +0 -49
- package/src/components/forms/button-toggle-visibility.tsx +0 -43
- package/src/components/forms/button.tsx +0 -60
- package/src/components/forms/fieldset.tsx +0 -55
- package/src/components/forms/form-card-async.tsx +0 -103
- package/src/components/forms/form-card.tsx +0 -49
- package/src/components/forms/input-checkbox.tsx +0 -78
- package/src/components/forms/input-container.tsx +0 -107
- package/src/components/forms/input-email-address.tsx +0 -65
- package/src/components/forms/input-new-password.tsx +0 -62
- package/src/components/forms/input-password.tsx +0 -87
- package/src/components/forms/input-text.tsx +0 -82
- package/src/components/forms/input-token.tsx +0 -94
- package/src/components/forms/wizard-card.tsx +0 -116
- package/src/components/layouts/layout-title-page.tsx +0 -78
- package/src/components/layouts/layout-welcome.tsx +0 -78
- package/src/components/utils/account-identifier.tsx +0 -23
- package/src/components/utils/account-image.tsx +0 -33
- package/src/components/utils/admonition.tsx +0 -52
- package/src/components/utils/client-name.tsx +0 -71
- package/src/components/utils/error-card.tsx +0 -93
- package/src/components/utils/error-message.tsx +0 -88
- package/src/components/utils/help-card.tsx +0 -46
- package/src/components/utils/icons.tsx +0 -88
- package/src/components/utils/link-anchor.tsx +0 -28
- package/src/components/utils/link-title.tsx +0 -26
- package/src/components/utils/multi-lang-string.tsx +0 -62
- package/src/components/utils/password-strength-label.tsx +0 -37
- package/src/components/utils/password-strength-meter.tsx +0 -58
- package/src/components/utils/url-viewer.tsx +0 -73
- package/src/error-page.tsx +0 -23
- package/src/hooks/use-api.ts +0 -202
- package/src/hooks/use-async-action.ts +0 -120
- package/src/hooks/use-bound-dispatch.ts +0 -5
- package/src/hooks/use-browser-color-scheme.ts +0 -31
- package/src/hooks/use-random-string.ts +0 -37
- package/src/hooks/use-stepper.ts +0 -87
- package/src/lib/api.ts +0 -225
- package/src/lib/cookies.ts +0 -17
- package/src/lib/json-client.ts +0 -141
- package/src/lib/password.ts +0 -98
- package/src/lib/ref.ts +0 -17
- package/src/lib/util.ts +0 -14
- package/src/locales/an/messages.po +0 -494
- package/src/locales/ast/messages.po +0 -494
- package/src/locales/ca/messages.po +0 -494
- package/src/locales/da/messages.po +0 -494
- package/src/locales/de/messages.po +0 -494
- package/src/locales/el/messages.po +0 -494
- package/src/locales/en/messages.po +0 -494
- package/src/locales/en-GB/messages.po +0 -494
- package/src/locales/es/messages.po +0 -494
- package/src/locales/eu/messages.po +0 -494
- package/src/locales/fi/messages.po +0 -494
- package/src/locales/fr/messages.po +0 -494
- package/src/locales/ga/messages.po +0 -494
- package/src/locales/gl/messages.po +0 -494
- package/src/locales/hi/messages.po +0 -494
- package/src/locales/hu/messages.po +0 -494
- package/src/locales/ia/messages.po +0 -494
- package/src/locales/id/messages.po +0 -494
- package/src/locales/it/messages.po +0 -494
- package/src/locales/ja/messages.po +0 -494
- package/src/locales/km/messages.po +0 -494
- package/src/locales/ko/messages.po +0 -494
- package/src/locales/load.ts +0 -8
- package/src/locales/locale-provider.tsx +0 -108
- package/src/locales/locale-selector.tsx +0 -57
- package/src/locales/locales.ts +0 -183
- package/src/locales/ne/messages.po +0 -494
- package/src/locales/nl/messages.po +0 -494
- package/src/locales/pl/messages.po +0 -494
- package/src/locales/pt-BR/messages.po +0 -494
- package/src/locales/ro/messages.po +0 -494
- package/src/locales/ru/messages.po +0 -494
- package/src/locales/sv/messages.po +0 -494
- package/src/locales/th/messages.po +0 -494
- package/src/locales/tr/messages.po +0 -494
- package/src/locales/uk/messages.po +0 -494
- package/src/locales/vi/messages.po +0 -494
- package/src/locales/zh-CN/messages.po +0 -494
- package/src/locales/zh-HK/messages.po +0 -494
- package/src/locales/zh-TW/messages.po +0 -494
- package/src/style.css +0 -219
- package/src/views/authorize/accept/accept-form.tsx +0 -155
- package/src/views/authorize/accept/accept-view.tsx +0 -70
- package/src/views/authorize/authorize-view.tsx +0 -186
- package/src/views/authorize/reset-password/reset-password-confirm-form.tsx +0 -88
- package/src/views/authorize/reset-password/reset-password-request-form.tsx +0 -80
- package/src/views/authorize/reset-password/reset-password-view.tsx +0 -127
- package/src/views/authorize/sign-in/sign-in-form.tsx +0 -240
- package/src/views/authorize/sign-in/sign-in-picker.tsx +0 -116
- package/src/views/authorize/sign-in/sign-in-view.tsx +0 -145
- package/src/views/authorize/sign-up/sign-up-account-form.tsx +0 -142
- package/src/views/authorize/sign-up/sign-up-disclaimer.tsx +0 -51
- package/src/views/authorize/sign-up/sign-up-handle-form.tsx +0 -287
- package/src/views/authorize/sign-up/sign-up-hcaptcha-form.tsx +0 -108
- package/src/views/authorize/sign-up/sign-up-view.tsx +0 -158
- package/src/views/authorize/welcome/welcome-view.tsx +0 -56
- package/src/views/error/error-view.tsx +0 -31
- package/tsconfig.json +0 -7
- package/tsconfig.src.json +0 -13
- package/tsconfig.src.tsbuildinfo +0 -1
- package/tsconfig.tools.json +0 -8
- package/tsconfig.tools.tsbuildinfo +0 -1
- package/vite.config.mjs +0 -47
- /package/{src/hydration-data.d.ts → hydration-data.d.ts} +0 -0
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { clsx } from 'clsx'
|
|
2
|
-
import { JSX, ReactNode } from 'react'
|
|
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:items-center md:justify-stretch',
|
|
31
|
-
'min-w-screen min-h-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 items-start',
|
|
44
|
-
'md:flex-col md:items-end',
|
|
45
|
-
'md:self-stretch',
|
|
46
|
-
'md:max-w-fix md:w-1/2 md:p-4',
|
|
47
|
-
'md:text-right',
|
|
48
|
-
'md:dark:border-r md:dark:border-slate-700',
|
|
49
|
-
'md:bg-slate-100 md:dark:bg-slate-800',
|
|
50
|
-
)}
|
|
51
|
-
>
|
|
52
|
-
<div className="grid grow content-center md:justify-items-end">
|
|
53
|
-
{title && (
|
|
54
|
-
<h1
|
|
55
|
-
key="title"
|
|
56
|
-
className="text-primary text-xl font-semibold md:my-4 md:text-2xl lg:text-5xl"
|
|
57
|
-
>
|
|
58
|
-
{title}
|
|
59
|
-
</h1>
|
|
60
|
-
)}
|
|
61
|
-
|
|
62
|
-
{subtitle && (
|
|
63
|
-
<p
|
|
64
|
-
key="subtitle"
|
|
65
|
-
className="hidden max-w-xs text-slate-600 md:block dark:text-slate-400"
|
|
66
|
-
>
|
|
67
|
-
{subtitle}
|
|
68
|
-
</p>
|
|
69
|
-
)}
|
|
70
|
-
</div>
|
|
71
|
-
|
|
72
|
-
<LocaleSelector key="localeSelector" className="m-1 md:m-2" />
|
|
73
|
-
</div>
|
|
74
|
-
|
|
75
|
-
<main className="w-full p-6 md:max-w-3xl md:px-12">{children}</main>
|
|
76
|
-
</div>
|
|
77
|
-
)
|
|
78
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { useLingui } from '@lingui/react/macro'
|
|
2
|
-
import { clsx } from 'clsx'
|
|
3
|
-
import { JSX } from 'react'
|
|
4
|
-
import type { CustomizationData } from '@atproto/oauth-provider-api'
|
|
5
|
-
import { Override } from '../../lib/util.ts'
|
|
6
|
-
import { LocaleSelector } from '../../locales/locale-selector.tsx'
|
|
7
|
-
import { LinkAnchor } from '../utils/link-anchor.tsx'
|
|
8
|
-
|
|
9
|
-
export type LayoutWelcomeProps = Override<
|
|
10
|
-
JSX.IntrinsicElements['div'],
|
|
11
|
-
{
|
|
12
|
-
customizationData: CustomizationData | undefined
|
|
13
|
-
title?: string
|
|
14
|
-
}
|
|
15
|
-
>
|
|
16
|
-
|
|
17
|
-
export function LayoutWelcome({
|
|
18
|
-
customizationData: { logo, name, links } = {},
|
|
19
|
-
title = name,
|
|
20
|
-
|
|
21
|
-
// div
|
|
22
|
-
className,
|
|
23
|
-
children,
|
|
24
|
-
...props
|
|
25
|
-
}: LayoutWelcomeProps) {
|
|
26
|
-
const { t } = useLingui()
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
<div
|
|
30
|
-
{...props}
|
|
31
|
-
className={clsx(
|
|
32
|
-
'min-h-screen w-full',
|
|
33
|
-
'flex flex-col items-center justify-center',
|
|
34
|
-
'bg-white text-slate-900',
|
|
35
|
-
'dark:bg-slate-900 dark:text-slate-100',
|
|
36
|
-
className,
|
|
37
|
-
)}
|
|
38
|
-
>
|
|
39
|
-
{title && <title>{title}</title>}
|
|
40
|
-
|
|
41
|
-
<main className="flex w-full grow flex-col items-center justify-center overflow-hidden p-6">
|
|
42
|
-
{logo && (
|
|
43
|
-
<img
|
|
44
|
-
src={logo}
|
|
45
|
-
alt={name || t`Logo`}
|
|
46
|
-
aria-hidden
|
|
47
|
-
className="mb-4 h-16 w-16 md:mb-8 md:h-24 md:w-24"
|
|
48
|
-
/>
|
|
49
|
-
)}
|
|
50
|
-
|
|
51
|
-
{name && (
|
|
52
|
-
<h1 className="mx-4 mb-4 text-center text-2xl font-bold md:mb-8 md:text-4xl">
|
|
53
|
-
{name}
|
|
54
|
-
</h1>
|
|
55
|
-
)}
|
|
56
|
-
|
|
57
|
-
{children}
|
|
58
|
-
</main>
|
|
59
|
-
|
|
60
|
-
<footer className="bg-contrast-25 dark:bg-contrast-50 flex w-full flex-wrap items-center justify-between overflow-hidden px-4 md:px-6">
|
|
61
|
-
<nav className="flex flex-wrap items-center justify-start">
|
|
62
|
-
{links?.map((link, i) => (
|
|
63
|
-
<LinkAnchor
|
|
64
|
-
key={i}
|
|
65
|
-
link={link}
|
|
66
|
-
className="text-text-light m-2 text-xs hover:underline md:m-4 md:text-sm"
|
|
67
|
-
/>
|
|
68
|
-
))}
|
|
69
|
-
</nav>
|
|
70
|
-
|
|
71
|
-
<LocaleSelector
|
|
72
|
-
className="m-1 text-xs md:m-2 md:text-sm"
|
|
73
|
-
key="localeSelector"
|
|
74
|
-
/>
|
|
75
|
-
</footer>
|
|
76
|
-
</div>
|
|
77
|
-
)
|
|
78
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { JSX } from 'react'
|
|
2
|
-
import type { Account } from '@atproto/oauth-provider-api'
|
|
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 h-6 w-6 rounded-full"
|
|
23
|
-
onError={() => setErrored(true)}
|
|
24
|
-
/>
|
|
25
|
-
) : (
|
|
26
|
-
<div
|
|
27
|
-
aria-hidden
|
|
28
|
-
className="bg-primary border-primary h-6 w-6 overflow-hidden rounded-full border-2 border-solid text-white"
|
|
29
|
-
>
|
|
30
|
-
<AccountIcon className="-mx-1 -mb-1" />
|
|
31
|
-
</div>
|
|
32
|
-
)
|
|
33
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { clsx } from 'clsx'
|
|
2
|
-
import { JSX, memo } from 'react'
|
|
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-contrast',
|
|
31
|
-
className,
|
|
32
|
-
)}
|
|
33
|
-
>
|
|
34
|
-
{role === 'info' ? (
|
|
35
|
-
<EyeIcon
|
|
36
|
-
aria-hidden
|
|
37
|
-
className={clsx('h-6 w-6 fill-current', 'text-primary')}
|
|
38
|
-
/>
|
|
39
|
-
) : (
|
|
40
|
-
<AlertIcon
|
|
41
|
-
aria-hidden
|
|
42
|
-
className={clsx(
|
|
43
|
-
'h-6 w-6 fill-current',
|
|
44
|
-
role === 'alert' ? 'text-inherit' : 'text-primary',
|
|
45
|
-
)}
|
|
46
|
-
/>
|
|
47
|
-
)}
|
|
48
|
-
|
|
49
|
-
<div className="flex flex-1 flex-col">{children}</div>
|
|
50
|
-
</div>
|
|
51
|
-
)
|
|
52
|
-
})
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { Trans } from '@lingui/react/macro'
|
|
2
|
-
import { JSX, useMemo } 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
|
-
const url = useMemo(() => {
|
|
25
|
-
try {
|
|
26
|
-
return new URL(clientId)
|
|
27
|
-
} catch {
|
|
28
|
-
return null
|
|
29
|
-
}
|
|
30
|
-
}, [clientId])
|
|
31
|
-
|
|
32
|
-
if (clientTrusted && clientMetadata.client_name) {
|
|
33
|
-
return <span {...attrs}>{clientMetadata.client_name}</span>
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// @NOTE: not using isOAuthClientIdLoopback & isOAuthClientIdDiscoverable from
|
|
37
|
-
// @atproto/oauth-types here because 1) we don't need to validate here and 2)
|
|
38
|
-
// we prefer not to import un-necessary code to improve bundle size.
|
|
39
|
-
|
|
40
|
-
if (url?.protocol === 'http:') {
|
|
41
|
-
return (
|
|
42
|
-
<span {...attrs}>
|
|
43
|
-
<Trans>An application on your device</Trans>
|
|
44
|
-
</span>
|
|
45
|
-
)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (url?.protocol === 'https:') {
|
|
49
|
-
// Only display the url details if the client id does not follow our
|
|
50
|
-
// convention.
|
|
51
|
-
const simplifiedView =
|
|
52
|
-
url.protocol === 'https:' &&
|
|
53
|
-
url.pathname === '/oauth-client-metadata.json' &&
|
|
54
|
-
!url.port &&
|
|
55
|
-
!url.search
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
<UrlViewer
|
|
59
|
-
{...attrs}
|
|
60
|
-
url={url}
|
|
61
|
-
proto={!simplifiedView}
|
|
62
|
-
host={true}
|
|
63
|
-
path={!simplifiedView}
|
|
64
|
-
query={!simplifiedView}
|
|
65
|
-
hash={false}
|
|
66
|
-
/>
|
|
67
|
-
)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return <span {...attrs}>{clientId}</span>
|
|
71
|
-
}
|
|
@@ -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 { clsx } from 'clsx'
|
|
3
|
-
import { JSX } from 'react'
|
|
4
|
-
import type { LinkDefinition } from '@atproto/oauth-provider-api'
|
|
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
|
-
'rounded-md bg-slate-100 p-3 text-sm text-slate-800 dark:bg-slate-800 dark:text-slate-400',
|
|
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-primary"
|
|
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 type { LinkDefinition } from '@atproto/oauth-provider-api'
|
|
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
|
-
}
|