refactor: generator token from outside

This commit is contained in:
SevicheCC 2023-06-07 16:02:47 +08:00
parent 86abf78493
commit 5edd4f4f14
Signed by: SevicheCC
GPG key ID: C577000000000000
15 changed files with 435 additions and 312 deletions

View file

@ -24,9 +24,6 @@ export default function Home() {
<FormContainer/>
</ClientOnly>
</CardContent>
{/* <CardFooter>
<p>Card Footer</p>
</CardFooter> */}
</Card>
</div>
</main>

View file

@ -1,26 +1,27 @@
"use client";
import { useEffect, useState } from "react";
import { useState } from "react";
import InputForm from "@/components/InputForm";
import ResultTable from "@/components/ResultTable";
import TokenTable from "@/components/TokenTable";
import ResultTable from "@/components/tables/ResultTable";
import useCreateApp from "@/hooks/useCreateApp";
import useAuth from "@/hooks/useAuth";
import { FormSchema } from "@/components/InputForm";
export type AppInfo = Pick<FormSchema, "instanceUrl" | "scopes">;
const FormContainer = () => {
const { appEntry, createApp } = useCreateApp();
const { credentials, createApp } = useCreateApp()
const [appInfo, setAppInfo] = useState<AppInfo>({
instanceUrl: "",
scopes: [""],
});
const { token, getAccessToken } = useAuth(appInfo);
return (
<>
<InputForm createApp={createApp} setAppInfo={setAppInfo} />
{appEntry && <ResultTable appEntry={appEntry} getAccessToken={getAccessToken}/>}
{/* <TokenTable appInfo={appInfo} /> */}
{credentials && (
<ResultTable credentials={credentials} appInfo={appInfo} />
)}
</>
);
};

View file

@ -16,13 +16,12 @@ import {
} from "@/components/ui/form";
import ScopeSection from "@/components/scopes/ScopeSection";
import { scopesInfo } from "@/lib/utils";
import { scopesInfo } from "@/lib/scopes";
import { Dispatch, SetStateAction } from "react";
import { AppEntry } from "@/lib/types";
import { AppInfo } from "./FormContainer";
const formSchema = z.object({
instanceUrl: z.string().trim(),
instanceUrl: z.string().url().trim(),
clientName: z.string().trim(),
redirectUris: z.string().trim(),
scopes: z.string().array().nonempty().optional(),
@ -31,8 +30,8 @@ const formSchema = z.object({
export type FormSchema = z.infer<typeof formSchema>;
interface InputFormProps {
createApp: ({ }: FormSchema) => Promise<void>
setAppInfo: Dispatch<SetStateAction<AppInfo>>
createApp: ({}: FormSchema) => Promise<void>;
setAppInfo: Dispatch<SetStateAction<AppInfo>>;
}
const InputForm: React.FC<InputFormProps> = ({ createApp, setAppInfo }) => {
@ -41,28 +40,30 @@ const InputForm: React.FC<InputFormProps> = ({ createApp, setAppInfo }) => {
defaultValues: {
instanceUrl: "https://",
clientName: "",
redirectUris: "",
redirectUris: "urn:ietf:wg:oauth:2.0:oob",
scopes: ["read"],
},
});
const onSubmit = async (values: FormSchema) => {
setAppInfo(values)
await createApp(values)
}
setAppInfo(values);
await createApp(values);
};
return (
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="flex flex-col space-y-6 mb-6"
className="mb-6 flex flex-col space-y-6"
>
<FormField
control={form.control}
name="instanceUrl"
render={({ field }) => (
<FormItem>
<FormLabel>Instance</FormLabel>
<FormLabel>
Instance<span className="text-sm text-red-400">*</span>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
@ -75,7 +76,9 @@ const InputForm: React.FC<InputFormProps> = ({ createApp, setAppInfo }) => {
name="clientName"
render={({ field }) => (
<FormItem>
<FormLabel>Application name</FormLabel>
<FormLabel>
Application name<span className="text-sm text-red-400">*</span>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
@ -101,7 +104,9 @@ const InputForm: React.FC<InputFormProps> = ({ createApp, setAppInfo }) => {
name="redirectUris"
render={({ field }) => (
<FormItem>
<FormLabel>Redirect URI</FormLabel>
<FormLabel>
Redirect URI<span className="text-sm text-red-400">*</span>
</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
@ -110,7 +115,7 @@ const InputForm: React.FC<InputFormProps> = ({ createApp, setAppInfo }) => {
<code className="relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-xs font-semibold">
urn:ietf:wg:oauth:2.0:oob
</code>{" "}
for local tests
for local tests or for getting access token
</FormDescription>
<FormMessage />
</FormItem>

View file

@ -1,59 +0,0 @@
"use client";
import {
Table,
TableBody,
TableCaption,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { AppEntry } from "@/lib/types";
import { CopyButton } from "@/components/ui/copybutton";
import { Button } from "@/components/ui/button";
interface ResultTableProps {
appEntry: AppEntry;
getAccessToken: (appEntry: AppEntry) => Promise<void>;
}
const renderTableRow = (label: string, value: string | undefined) => (
<TableRow className="relative">
<TableCell className="font-medium">{label}</TableCell>
<TableCell className="flex items-center justify-between break-all font-mono">
{value}
{value && <CopyButton value={value} className="end-2 shrink-0" />}
</TableCell>
</TableRow>
);
const ResultTable: React.FC<ResultTableProps> = ({
appEntry,
getAccessToken,
}) => {
return (
<>
<Table>
<TableHeader>
<TableRow>
<TableHead className="min-w-[120px]">Type</TableHead>
<TableHead>Value</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{renderTableRow("ID", appEntry?.id)}
{renderTableRow("Name", appEntry?.name)}
{renderTableRow("Website", appEntry?.website || "")}
{renderTableRow("Redirect URI", appEntry?.redirect_uri)}
{renderTableRow("Client ID", appEntry?.client_id)}
{renderTableRow("Client Secret", appEntry?.client_secret)}
{renderTableRow("Vapid Key", appEntry?.vapid_key)}
</TableBody>
</Table>
<Button onClick={()=>getAccessToken(appEntry)}>Generate AcessToken</Button>
</>
);
};
export default ResultTable;

View file

@ -1,9 +0,0 @@
'use client'
const TokenTable = () => {
return (
<div>5</div>
);
};
export default TokenTable;

View file

@ -0,0 +1,23 @@
"use client";
import { TableCell, TableRow } from "@/components/ui/table";
import { CopyButton } from "@/components/ui/copybutton";
interface CopyableRowProps {
label: string;
value: string | null;
}
const CopyableRow: React.FC<CopyableRowProps> = ({ label, value }) => {
return (
<TableRow className="relative">
<TableCell className="font-medium">{label}</TableCell>
<TableCell className="flex items-center justify-between break-all font-mono">
{value}
{value && <CopyButton value={value} className="end-2 shrink-0" />}
</TableCell>
</TableRow>
);
};
export default CopyableRow;

View file

@ -0,0 +1,80 @@
"use client";
import {
Table,
TableBody,
TableCaption,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { Credentials } from "@/lib/types";
import { CopyButton } from "@/components/ui/copybutton";
import { Button } from "@/components/ui/button";
import { ExternalLink } from "lucide-react";
import { getAuth } from "@/lib/utils";
import { AppInfo } from "../FormContainer";
interface ResultTableProps {
credentials: Credentials;
appInfo: AppInfo;
}
const renderTableRow = (label: string, value: string | undefined) => (
<TableRow className="relative">
<TableCell className="font-medium">{label}</TableCell>
<TableCell className="flex items-center justify-between break-all font-mono">
{value}
{value && <CopyButton value={value} className="end-2 shrink-0" />}
</TableCell>
</TableRow>
);
const ResultTable: React.FC<ResultTableProps> = ({ credentials, appInfo }) => {
const { instanceUrl, scopes } = appInfo;
const {
id,
name,
website,
redirect_uri,
client_id,
client_secret,
vapid_key,
} = credentials;
return (
<div className="flex flex-col items-center gap-4">
<Table>
<TableHeader>
<TableRow>
<TableHead className="min-w-[120px]">Type</TableHead>
<TableHead>Value</TableHead>
</TableRow>
</TableHeader>
{credentials && (
<TableBody>
{renderTableRow("ID", id)}
{renderTableRow("Name", name)}
{renderTableRow("Website", website || "")}
{renderTableRow("Redirect URI", redirect_uri)}
{renderTableRow("Client ID", client_id)}
{renderTableRow("Client Secret", client_secret)}
{renderTableRow("Vapid Key", vapid_key)}
</TableBody>
)}
</Table>
{redirect_uri === "urn:ietf:wg:oauth:2.0:oob" && (
<Button
onClick={() => getAuth(instanceUrl, client_id, scopes)}
variant="outline"
>
<ExternalLink className="mr-2 h-4 w-4" />
Generate Access Token
</Button>
)}
</div>
);
};
export default ResultTable;

59
components/ui/alert.tsx Normal file
View file

@ -0,0 +1,59 @@
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const alertVariants = cva(
"relative w-full rounded-lg border p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11",
{
variants: {
variant: {
default: "bg-background text-foreground",
destructive:
"text-destructive border-destructive/50 dark:border-destructive [&>svg]:text-destructive text-destructive",
},
},
defaultVariants: {
variant: "default",
},
}
)
const Alert = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>
>(({ className, variant, ...props }, ref) => (
<div
ref={ref}
role="alert"
className={cn(alertVariants({ variant }), className)}
{...props}
/>
))
Alert.displayName = "Alert"
const AlertTitle = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLHeadingElement>
>(({ className, ...props }, ref) => (
<h5
ref={ref}
className={cn("mb-1 font-medium leading-none tracking-tight", className)}
{...props}
/>
))
AlertTitle.displayName = "AlertTitle"
const AlertDescription = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("text-sm [&_p]:leading-relaxed", className)}
{...props}
/>
))
AlertDescription.displayName = "AlertDescription"
export { Alert, AlertTitle, AlertDescription }

View file

@ -1,92 +0,0 @@
import { useCallback, useState, useMemo } from "react";
import { AppEntry, MError } from "@/lib/types";
import { FormSchema } from "@/components/InputForm";
import { AppInfo } from "@/components/FormContainer";
const useAuth = (appInfo: AppInfo) => {
const { instanceUrl, scopes} = appInfo
const [token, setToken] = useState("");
const getCode = useCallback(
(client_id: string, redirect_uri: string) => {
const code = new URLSearchParams(window.location.search).get("code");
if (!code) {
const params = {
response_type: "code",
client_id,
redirect_uri,
};
if (scopes) {
const scope = 1
}
const queryString = new URLSearchParams(params).toString();
window.location.href = `${instanceUrl}/oauth/authorize?${queryString}`;
} else {
return code;
}
},
[instanceUrl, scopes]
);
const getAuth = useCallback(
async (
code: string,
client_id: string,
redirect_uri: string,
client_secret: string
) => {
const body = new URLSearchParams({
grant_type: "authorization_code",
client_id,
client_secret,
redirect_uri,
code,
});
try {
const response = await fetch(`${instanceUrl}/oauth/token`, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: body.toString(),
});
const result = await response.json();
if (!response.ok) throw new Error((result as MError).error);
return result.access_token;
} catch (error) {
console.error(error);
}
},
[instanceUrl]
);
const getAccessToken = useCallback(
async (appEntry: AppEntry) => {
const { client_id, redirect_uri, client_secret } = appEntry;
const code = getCode(client_id, redirect_uri);
if (code) {
const accessToken = await getAuth(
code,
client_id,
redirect_uri,
client_secret
);
setToken(accessToken);
}
},
[getCode, getAuth]
);
return {
token,
getAccessToken,
};
};
export default useAuth;

View file

@ -3,7 +3,7 @@ import { useCallback, useState } from "react";
import { AppEntry, MError } from "@/lib/types";
const useCreateApp = () => {
const [appEntry, setAppEntry] = useState<AppEntry>();
const [credentials, setCredentials] = useState<AppEntry>();
const createApp = useCallback(
async ({
@ -32,7 +32,7 @@ const useCreateApp = () => {
if (!request.ok || request.status === 424) {
throw new Error((await request.json()).error);
}
setAppEntry(await request.json());
setCredentials(await request.json());
} catch (error) {
throw new Error((error as MError).error);
}
@ -40,7 +40,7 @@ const useCreateApp = () => {
);
return {
appEntry,
credentials,
createApp,
};
};

87
lib/scopes.ts Normal file
View file

@ -0,0 +1,87 @@
import { ScopeInfo } from "./types";
export const READ_SCOPES = [
"read:accounts",
"read:blocks",
"read:bookmarks",
"read:favourites",
"read:filters",
"read:follows",
"read:lists",
"read:mutes",
"read:notifications",
"read:search",
"read:statuses",
];
export const WRITE_SCOPES = [
"write:account",
"write:blocks",
"write:bookmarks",
"write:favourites",
"write:filters",
"write:lists",
"write:mutes",
"write:notifications",
"write:statuses",
"write:conversations",
"write:media",
"write:reports",
];
export const ADMIN_READ_SCOPES = [
"admin:read:account",
"admin:read:reports",
"admin:read:domain_allows",
"admin:read:domain_blocks",
"admin:read:ip_blocks",
"admin:read:email_domain_blocks",
"admin:read:canonical_email_blocks",
];
export const ADMIN_WRITE_SCOPES = [
"admin:write:account",
"admin:write:reports",
"admin:write:domain_allows",
"admin:write:domain_blocks",
"admin:write:ip_blocks",
"admin:write:email_domain_blocks",
"admin:write:canonical_email_blocks",
];
export const scopesInfo: ScopeInfo[] = [
{
method: "read",
label: "Read",
scopes: READ_SCOPES,
description: "read account's data",
},
{
method: "write",
label: "Write",
scopes: WRITE_SCOPES,
description: "modify account's data",
},
{
method: "admin",
label: "Admin",
scopes: [ADMIN_READ_SCOPES, ADMIN_WRITE_SCOPES],
description: "read all data on the server",
},
{
method: "follow",
label: "Follow",
description: "modify account relationships,deprecated in 3.5.0 and newer.",
},
{
method: "push",
label: "Push",
description: "receive push notifications",
},
{
method: "crypto",
label: "Crypto",
description: "use end-to-end encryption",
},
];

View file

@ -14,7 +14,7 @@ export interface ScopeInfo {
description: string;
}
export interface AppEntry {
export interface Credentials {
id: string;
name: string;
website: string | null;

View file

@ -1,93 +1,25 @@
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
import { ScopeInfo } from "./types";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
export const READ_SCOPES = [
"read:accounts",
"read:blocks",
"read:bookmarks",
"read:favourites",
"read:filters",
"read:follows",
"read:lists",
"read:mutes",
"read:notifications",
"read:search",
"read:statuses",
];
export const getAuth = (
instanceUrl: string,
client_id: string,
scopes: any,
) => {
const params: any = {
response_type: "code",
client_id,
redirect_uri: "urn:ietf:wg:oauth:2.0:oob",
};
export const WRITE_SCOPES = [
"write:account",
"write:blocks",
"write:bookmarks",
"write:favourites",
"write:filters",
"write:lists",
"write:mutes",
"write:notifications",
"write:statuses",
"write:conversations",
"write:media",
"write:reports",
];
if (scopes) {
params.scopes = scopes.join(" ");
}
const queryString = new URLSearchParams(params).toString();
window.location.href = `${instanceUrl}/oauth/authorize?${queryString}`;
};
export const ADMIN_READ_SCOPES = [
"admin:read:account",
"admin:read:reports",
"admin:read:domain_allows",
"admin:read:domain_blocks",
"admin:read:ip_blocks",
"admin:read:email_domain_blocks",
"admin:read:canonical_email_blocks",
];
export const ADMIN_WRITE_SCOPES = [
"admin:write:account",
"admin:write:reports",
"admin:write:domain_allows",
"admin:write:domain_blocks",
"admin:write:ip_blocks",
"admin:write:email_domain_blocks",
"admin:write:canonical_email_blocks",
];
export const scopesInfo: ScopeInfo[] = [
{
method: "read",
label: "Read",
scopes: READ_SCOPES,
description: "read account's data",
},
{
method: "write",
label: "Write",
scopes: WRITE_SCOPES,
description: "modify account's data",
},
{
method: "admin",
label: "Admin",
scopes: [ADMIN_READ_SCOPES, ADMIN_WRITE_SCOPES],
description: "read all data on the server",
},
{
method: "follow",
label: "Follow",
description: "modify account relationships,deprecated in 3.5.0 and newer.",
},
{
method: "push",
label: "Push",
description: "receive push notifications",
},
{
method: "crypto",
label: "Crypto",
description: "use end-to-end encryption",
},
];

View file

@ -17,6 +17,7 @@
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-separator": "^1.0.3",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-tabs": "^1.0.4",
"@types/node": "20.2.5",
"@types/react": "18.2.7",
"@types/react-dom": "18.2.4",

View file

@ -19,6 +19,9 @@ dependencies:
'@radix-ui/react-slot':
specifier: ^1.0.2
version: 1.0.2(@types/react@18.2.7)(react@18.2.0)
'@radix-ui/react-tabs':
specifier: ^1.0.4
version: 1.0.4(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
'@types/node':
specifier: 20.2.5
version: 20.2.5
@ -395,6 +398,30 @@ packages:
react-dom: 18.2.0(react@18.2.0)
dev: false
/@radix-ui/react-collection@1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0
react-dom: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
dependencies:
'@babel/runtime': 7.22.3
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.7)(react@18.2.0)
'@radix-ui/react-context': 1.0.1(@types/react@18.2.7)(react@18.2.0)
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-slot': 1.0.2(@types/react@18.2.7)(react@18.2.0)
'@types/react': 18.2.7
'@types/react-dom': 18.2.4
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false
/@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.7)(react@18.2.0):
resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==}
peerDependencies:
@ -423,6 +450,20 @@ packages:
react: 18.2.0
dev: false
/@radix-ui/react-direction@1.0.1(@types/react@18.2.7)(react@18.2.0):
resolution: {integrity: sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
dependencies:
'@babel/runtime': 7.22.3
'@types/react': 18.2.7
react: 18.2.0
dev: false
/@radix-ui/react-id@1.0.1(@types/react@18.2.7)(react@18.2.0):
resolution: {integrity: sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==}
peerDependencies:
@ -502,6 +543,35 @@ packages:
react-dom: 18.2.0(react@18.2.0)
dev: false
/@radix-ui/react-roving-focus@1.0.4(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0
react-dom: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
dependencies:
'@babel/runtime': 7.22.3
'@radix-ui/primitive': 1.0.1
'@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.7)(react@18.2.0)
'@radix-ui/react-context': 1.0.1(@types/react@18.2.7)(react@18.2.0)
'@radix-ui/react-direction': 1.0.1(@types/react@18.2.7)(react@18.2.0)
'@radix-ui/react-id': 1.0.1(@types/react@18.2.7)(react@18.2.0)
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.7)(react@18.2.0)
'@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.7)(react@18.2.0)
'@types/react': 18.2.7
'@types/react-dom': 18.2.4
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false
/@radix-ui/react-separator@1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-itYmTy/kokS21aiV5+Z56MZB54KrhPgn6eHDKkFeOLR34HMN2s8PaN47qZZAGnvupcjxHaFZnW4pQEh0BvvVuw==}
peerDependencies:
@ -538,6 +608,34 @@ packages:
react: 18.2.0
dev: false
/@radix-ui/react-tabs@1.0.4(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-egZfYY/+wRNCflXNHx+dePvnz9FbmssDTJBtgRfDY7e8SE5oIo3Py2eCB1ckAbh1Q7cQ/6yJZThJ++sgbxibog==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0
react-dom: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
dependencies:
'@babel/runtime': 7.22.3
'@radix-ui/primitive': 1.0.1
'@radix-ui/react-context': 1.0.1(@types/react@18.2.7)(react@18.2.0)
'@radix-ui/react-direction': 1.0.1(@types/react@18.2.7)(react@18.2.0)
'@radix-ui/react-id': 1.0.1(@types/react@18.2.7)(react@18.2.0)
'@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-roving-focus': 1.0.4(@types/react-dom@18.2.4)(@types/react@18.2.7)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.7)(react@18.2.0)
'@types/react': 18.2.7
'@types/react-dom': 18.2.4
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false
/@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.7)(react@18.2.0):
resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==}
peerDependencies:
@ -661,8 +759,8 @@ packages:
resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==}
dev: false
/@typescript-eslint/parser@5.59.8(eslint@8.41.0)(typescript@5.0.4):
resolution: {integrity: sha512-AnR19RjJcpjoeGojmwZtCwBX/RidqDZtzcbG3xHrmz0aHHoOcbWnpDllenRDmDvsV0RQ6+tbb09/kyc+UT9Orw==}
/@typescript-eslint/parser@5.59.9(eslint@8.41.0)(typescript@5.0.4):
resolution: {integrity: sha512-FsPkRvBtcLQ/eVK1ivDiNYBjn3TGJdXy2fhXX+rc7czWl4ARwnpArwbihSOHI2Peg9WbtGHrbThfBUkZZGTtvQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
@ -671,9 +769,9 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/scope-manager': 5.59.8
'@typescript-eslint/types': 5.59.8
'@typescript-eslint/typescript-estree': 5.59.8(typescript@5.0.4)
'@typescript-eslint/scope-manager': 5.59.9
'@typescript-eslint/types': 5.59.9
'@typescript-eslint/typescript-estree': 5.59.9(typescript@5.0.4)
debug: 4.3.4
eslint: 8.41.0
typescript: 5.0.4
@ -681,21 +779,21 @@ packages:
- supports-color
dev: false
/@typescript-eslint/scope-manager@5.59.8:
resolution: {integrity: sha512-/w08ndCYI8gxGf+9zKf1vtx/16y8MHrZs5/tnjHhMLNSixuNcJavSX4wAiPf4aS5x41Es9YPCn44MIe4cxIlig==}
/@typescript-eslint/scope-manager@5.59.9:
resolution: {integrity: sha512-8RA+E+w78z1+2dzvK/tGZ2cpGigBZ58VMEHDZtpE1v+LLjzrYGc8mMaTONSxKyEkz3IuXFM0IqYiGHlCsmlZxQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
'@typescript-eslint/types': 5.59.8
'@typescript-eslint/visitor-keys': 5.59.8
'@typescript-eslint/types': 5.59.9
'@typescript-eslint/visitor-keys': 5.59.9
dev: false
/@typescript-eslint/types@5.59.8:
resolution: {integrity: sha512-+uWuOhBTj/L6awoWIg0BlWy0u9TyFpCHrAuQ5bNfxDaZ1Ppb3mx6tUigc74LHcbHpOHuOTOJrBoAnhdHdaea1w==}
/@typescript-eslint/types@5.59.9:
resolution: {integrity: sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: false
/@typescript-eslint/typescript-estree@5.59.8(typescript@5.0.4):
resolution: {integrity: sha512-Jy/lPSDJGNow14vYu6IrW790p7HIf/SOV1Bb6lZ7NUkLc2iB2Z9elESmsaUtLw8kVqogSbtLH9tut5GCX1RLDg==}
/@typescript-eslint/typescript-estree@5.59.9(typescript@5.0.4):
resolution: {integrity: sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
typescript: '*'
@ -703,8 +801,8 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/types': 5.59.8
'@typescript-eslint/visitor-keys': 5.59.8
'@typescript-eslint/types': 5.59.9
'@typescript-eslint/visitor-keys': 5.59.9
debug: 4.3.4
globby: 11.1.0
is-glob: 4.0.3
@ -715,11 +813,11 @@ packages:
- supports-color
dev: false
/@typescript-eslint/visitor-keys@5.59.8:
resolution: {integrity: sha512-pJhi2ms0x0xgloT7xYabil3SGGlojNNKjK/q6dB3Ey0uJLMjK2UDGJvHieiyJVW/7C3KI+Z4Q3pEHkm4ejA+xQ==}
/@typescript-eslint/visitor-keys@5.59.9:
resolution: {integrity: sha512-bT7s0td97KMaLwpEBckbzj/YohnvXtqbe2XgqNvTl6RJVakY5mvENOTPvw5u66nljfZxthESpDozs86U+oLY8Q==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
'@typescript-eslint/types': 5.59.8
'@typescript-eslint/types': 5.59.9
eslint-visitor-keys: 3.4.1
dev: false
@ -881,7 +979,7 @@ packages:
postcss: ^8.1.0
dependencies:
browserslist: 4.21.7
caniuse-lite: 1.0.30001492
caniuse-lite: 1.0.30001495
fraction.js: 4.2.0
normalize-range: 0.1.2
picocolors: 1.0.0
@ -941,8 +1039,8 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
dependencies:
caniuse-lite: 1.0.30001492
electron-to-chromium: 1.4.417
caniuse-lite: 1.0.30001495
electron-to-chromium: 1.4.423
node-releases: 2.0.12
update-browserslist-db: 1.0.11(browserslist@4.21.7)
dev: false
@ -983,8 +1081,8 @@ packages:
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
engines: {node: '>= 6'}
/caniuse-lite@1.0.30001492:
resolution: {integrity: sha512-2efF8SAZwgAX1FJr87KWhvuJxnGJKOnctQa8xLOskAXNXq8oiuqgl6u1kk3fFpsp3GgvzlRjiK1sl63hNtFADw==}
/caniuse-lite@1.0.30001495:
resolution: {integrity: sha512-F6x5IEuigtUfU5ZMQK2jsy5JqUUlEFRVZq8bO2a+ysq5K7jD6PPc9YXZj78xDNS3uNchesp1Jw47YXEqr+Viyg==}
dev: false
/capital-case@1.0.4:
@ -1269,8 +1367,8 @@ packages:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
dev: true
/electron-to-chromium@1.4.417:
resolution: {integrity: sha512-8rY8HdCxuSVY8wku3i/eDac4g1b4cSbruzocenrqBlzqruAZYHjQCHIjC66dLR9DXhEHTojsC4EjhZ8KmzwXqA==}
/electron-to-chromium@1.4.423:
resolution: {integrity: sha512-y4A7YfQcDGPAeSWM1IuoWzXpg9RY1nwHzHSwRtCSQFp9FgAVDgdWlFf0RbdWfLWQ2WUI+bddUgk5RgTjqRE6FQ==}
dev: false
/emoji-regex@8.0.0:
@ -1386,11 +1484,11 @@ packages:
dependencies:
'@next/eslint-plugin-next': 13.4.4
'@rushstack/eslint-patch': 1.3.0
'@typescript-eslint/parser': 5.59.8(eslint@8.41.0)(typescript@5.0.4)
'@typescript-eslint/parser': 5.59.9(eslint@8.41.0)(typescript@5.0.4)
eslint: 8.41.0
eslint-import-resolver-node: 0.3.7
eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.59.8)(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.41.0)
eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.59.8)(eslint-import-resolver-typescript@3.5.5)(eslint@8.41.0)
eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.59.9)(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.41.0)
eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.59.9)(eslint-import-resolver-typescript@3.5.5)(eslint@8.41.0)
eslint-plugin-jsx-a11y: 6.7.1(eslint@8.41.0)
eslint-plugin-react: 7.32.2(eslint@8.41.0)
eslint-plugin-react-hooks: 4.6.0(eslint@8.41.0)
@ -1419,7 +1517,7 @@ packages:
- supports-color
dev: false
/eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.59.8)(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.41.0):
/eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.59.9)(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.41.0):
resolution: {integrity: sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw==}
engines: {node: ^14.18.0 || >=16.0.0}
peerDependencies:
@ -1429,8 +1527,8 @@ packages:
debug: 4.3.4
enhanced-resolve: 5.14.1
eslint: 8.41.0
eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.59.8)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.41.0)
eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.59.8)(eslint-import-resolver-typescript@3.5.5)(eslint@8.41.0)
eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.59.9)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.41.0)
eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.59.9)(eslint-import-resolver-typescript@3.5.5)(eslint@8.41.0)
get-tsconfig: 4.6.0
globby: 13.1.4
is-core-module: 2.12.1
@ -1443,7 +1541,7 @@ packages:
- supports-color
dev: false
/eslint-module-utils@2.8.0(@typescript-eslint/parser@5.59.8)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.41.0):
/eslint-module-utils@2.8.0(@typescript-eslint/parser@5.59.9)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.41.0):
resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==}
engines: {node: '>=4'}
peerDependencies:
@ -1464,16 +1562,16 @@ packages:
eslint-import-resolver-webpack:
optional: true
dependencies:
'@typescript-eslint/parser': 5.59.8(eslint@8.41.0)(typescript@5.0.4)
'@typescript-eslint/parser': 5.59.9(eslint@8.41.0)(typescript@5.0.4)
debug: 3.2.7
eslint: 8.41.0
eslint-import-resolver-node: 0.3.7
eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.59.8)(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.41.0)
eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.59.9)(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.41.0)
transitivePeerDependencies:
- supports-color
dev: false
/eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.59.8)(eslint-import-resolver-typescript@3.5.5)(eslint@8.41.0):
/eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.59.9)(eslint-import-resolver-typescript@3.5.5)(eslint@8.41.0):
resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==}
engines: {node: '>=4'}
peerDependencies:
@ -1483,7 +1581,7 @@ packages:
'@typescript-eslint/parser':
optional: true
dependencies:
'@typescript-eslint/parser': 5.59.8(eslint@8.41.0)(typescript@5.0.4)
'@typescript-eslint/parser': 5.59.9(eslint@8.41.0)(typescript@5.0.4)
array-includes: 3.1.6
array.prototype.flat: 1.3.1
array.prototype.flatmap: 1.3.1
@ -1491,7 +1589,7 @@ packages:
doctrine: 2.1.0
eslint: 8.41.0
eslint-import-resolver-node: 0.3.7
eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.59.8)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.41.0)
eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.59.9)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.41.0)
has: 1.0.3
is-core-module: 2.12.1
is-glob: 4.0.3
@ -2470,7 +2568,7 @@ packages:
'@next/env': 13.4.4
'@swc/helpers': 0.5.1
busboy: 1.6.0
caniuse-lite: 1.0.30001492
caniuse-lite: 1.0.30001495
postcss: 8.4.14
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)