Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
add theme provider
Browse files- app/layout.tsx +5 -7
- app/page.tsx +2 -3
- assets/globals.css +4 -3
- components/editor/header.tsx +58 -5
- components/editor/index.tsx +1 -1
- components/editor/main/endpoint.tsx +4 -4
- components/editor/main/index.tsx +2 -2
- components/editor/main/parameter.tsx +1 -1
- components/editor/main/request.tsx +4 -4
- components/editor/main/response.tsx +5 -4
- components/editor/main/snippet/curl.tsx +4 -4
- components/editor/main/snippet/javascript.tsx +3 -3
- components/editor/main/snippet/python.tsx +3 -3
- components/editor/main/tabs.tsx +19 -49
- components/editor/sidebar.tsx +8 -8
- components/input/input.tsx +4 -4
- components/input/toggle.tsx +7 -7
- index.d.ts +9 -0
- package-lock.json +11 -0
- package.json +1 -0
- tailwind.config.ts +10 -9
app/layout.tsx
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
-
import type { Metadata } from "next";
|
2 |
import { Fira_Code, Inter } from "next/font/google";
|
|
|
3 |
import "@/assets/globals.css";
|
|
|
4 |
import { Editor } from "@/components/editor";
|
5 |
|
6 |
const inter = Inter({
|
@@ -15,11 +16,6 @@ const fira_code = Fira_Code({
|
|
15 |
variable: "--font-fira-code",
|
16 |
});
|
17 |
|
18 |
-
export const metadata: Metadata = {
|
19 |
-
title: "Create Next App",
|
20 |
-
description: "Generated by create next app",
|
21 |
-
};
|
22 |
-
|
23 |
export default function RootLayout({
|
24 |
children,
|
25 |
}: {
|
@@ -28,7 +24,9 @@ export default function RootLayout({
|
|
28 |
return (
|
29 |
<html lang="en" className={`${inter.variable} ${fira_code.variable}`}>
|
30 |
<body>
|
31 |
-
<
|
|
|
|
|
32 |
</body>
|
33 |
</html>
|
34 |
);
|
|
|
|
|
1 |
import { Fira_Code, Inter } from "next/font/google";
|
2 |
+
import { ThemeProvider } from "next-themes";
|
3 |
import "@/assets/globals.css";
|
4 |
+
import "highlight.js/styles/github.css";
|
5 |
import { Editor } from "@/components/editor";
|
6 |
|
7 |
const inter = Inter({
|
|
|
16 |
variable: "--font-fira-code",
|
17 |
});
|
18 |
|
|
|
|
|
|
|
|
|
|
|
19 |
export default function RootLayout({
|
20 |
children,
|
21 |
}: {
|
|
|
24 |
return (
|
25 |
<html lang="en" className={`${inter.variable} ${fira_code.variable}`}>
|
26 |
<body>
|
27 |
+
<ThemeProvider attribute="class" defaultTheme="dark" enableSystem>
|
28 |
+
<Editor>{children}</Editor>
|
29 |
+
</ThemeProvider>
|
30 |
</body>
|
31 |
</html>
|
32 |
);
|
app/page.tsx
CHANGED
@@ -1,6 +1,5 @@
|
|
1 |
-
|
2 |
-
import Image from "next/image";
|
3 |
|
4 |
export default function Home() {
|
5 |
-
return <
|
6 |
}
|
|
|
1 |
+
"use client";
|
|
|
2 |
|
3 |
export default function Home() {
|
4 |
+
return <div />;
|
5 |
}
|
assets/globals.css
CHANGED
@@ -2,7 +2,8 @@
|
|
2 |
@tailwind components;
|
3 |
@tailwind utilities;
|
4 |
|
5 |
-
html,
|
|
|
6 |
@apply bg-gray-200 min-h-screen relative tracking-wide overflow-x-hidden;
|
7 |
z-index: 1;
|
8 |
}
|
@@ -10,7 +11,7 @@ html, body {
|
|
10 |
#background__noisy {
|
11 |
@apply bg-blend-normal pointer-events-none opacity-80;
|
12 |
background-size: 25ww auto;
|
13 |
-
background-image: url(
|
14 |
z-index: -1;
|
15 |
@apply fixed w-screen h-screen top-0 left-0;
|
16 |
-
}
|
|
|
2 |
@tailwind components;
|
3 |
@tailwind utilities;
|
4 |
|
5 |
+
html,
|
6 |
+
body {
|
7 |
@apply bg-gray-200 min-h-screen relative tracking-wide overflow-x-hidden;
|
8 |
z-index: 1;
|
9 |
}
|
|
|
11 |
#background__noisy {
|
12 |
@apply bg-blend-normal pointer-events-none opacity-80;
|
13 |
background-size: 25ww auto;
|
14 |
+
background-image: url("/background_noisy.webp");
|
15 |
z-index: -1;
|
16 |
@apply fixed w-screen h-screen top-0 left-0;
|
17 |
+
}
|
components/editor/header.tsx
CHANGED
@@ -1,26 +1,79 @@
|
|
|
|
1 |
import Image from "next/image";
|
2 |
import { TbMenu2 } from "react-icons/tb";
|
|
|
|
|
|
|
|
|
|
|
3 |
|
4 |
import HFLogo from "assets/hf-logo.svg";
|
|
|
5 |
|
6 |
export const EditorHeader = ({
|
7 |
onToggleMenu,
|
8 |
}: {
|
9 |
onToggleMenu: () => void;
|
10 |
}) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
return (
|
12 |
-
<header className="px-4 xl:px-6 py-2.5 border border-slate-950 bg-slate-950 flex justify-between items-center">
|
13 |
<div className="w-5 h-5 block xl:hidden" onClick={onToggleMenu}>
|
14 |
-
<TbMenu2 className="w-full h-full text-slate-100" />
|
15 |
</div>
|
16 |
<Image src={HFLogo} alt="Hugging Face Logo" width={34} height={34} />
|
17 |
-
<p className="text-gray-300 font-code text-sm font-semibold">
|
18 |
Hub API Playground
|
19 |
</p>
|
20 |
<div className="hidden xl:flex items-center justify-end gap-3">
|
21 |
-
<div className="bg-teal-600 w-3 h-3 rounded-full" />
|
22 |
<div className="bg-indigo-600 w-3 h-3 rounded-full" />
|
23 |
-
<div className="bg-purple-500 w-3 h-3 rounded-full" />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
</div>
|
25 |
</header>
|
26 |
);
|
|
|
1 |
+
"use client";
|
2 |
import Image from "next/image";
|
3 |
import { TbMenu2 } from "react-icons/tb";
|
4 |
+
import { MdOutlineNightlight, MdOutlineLightMode } from "react-icons/md";
|
5 |
+
import classNames from "classnames";
|
6 |
+
import { useTheme } from "next-themes";
|
7 |
+
import { useEffect, useState } from "react";
|
8 |
+
import("highlight.js/styles/atom-one-dark.css");
|
9 |
|
10 |
import HFLogo from "assets/hf-logo.svg";
|
11 |
+
import { useUpdateEffect } from "react-use";
|
12 |
|
13 |
export const EditorHeader = ({
|
14 |
onToggleMenu,
|
15 |
}: {
|
16 |
onToggleMenu: () => void;
|
17 |
}) => {
|
18 |
+
const [mounted, setMounted] = useState(false);
|
19 |
+
const { theme, setTheme } = useTheme();
|
20 |
+
|
21 |
+
useEffect(() => {
|
22 |
+
setMounted(true);
|
23 |
+
}, []);
|
24 |
+
|
25 |
+
if (!mounted) {
|
26 |
+
return null;
|
27 |
+
}
|
28 |
+
|
29 |
return (
|
30 |
+
<header className="px-4 xl:px-6 py-2.5 border-b dark:border-slate-950 border-gray-200 bg-white dark:bg-slate-950 flex justify-between items-center">
|
31 |
<div className="w-5 h-5 block xl:hidden" onClick={onToggleMenu}>
|
32 |
+
<TbMenu2 className="w-full h-full text-slate-600 dark:text-slate-100" />
|
33 |
</div>
|
34 |
<Image src={HFLogo} alt="Hugging Face Logo" width={34} height={34} />
|
35 |
+
<p className="text-gray-800 dark:text-gray-300 font-code text-sm font-semibold">
|
36 |
Hub API Playground
|
37 |
</p>
|
38 |
<div className="hidden xl:flex items-center justify-end gap-3">
|
39 |
+
{/* <div className="bg-teal-600 w-3 h-3 rounded-full" />
|
40 |
<div className="bg-indigo-600 w-3 h-3 rounded-full" />
|
41 |
+
<div className="bg-purple-500 w-3 h-3 rounded-full" /> */}
|
42 |
+
<div className="rounded-full bg-gray-100 border-gray-200 dark:bg-slate-800 border dark:border-slate-700 p-0.5 flex items-center justify-between relative z-[1] cursor-pointer">
|
43 |
+
<div
|
44 |
+
className={classNames(
|
45 |
+
"transition-transform duration-200 ease-in-out top-0.5 w-6 h-6 rounded-full absolute -z-[1]",
|
46 |
+
{
|
47 |
+
"translate-x-full bg-indigo-500": theme === "dark",
|
48 |
+
"translate-x-0 bg-amber-500": theme === "light",
|
49 |
+
}
|
50 |
+
)}
|
51 |
+
/>
|
52 |
+
<div
|
53 |
+
className={`size-6 rounded-full flex items-center justify-center ${
|
54 |
+
theme === "light"
|
55 |
+
? "text-white"
|
56 |
+
: "dark:text-slate-500 text-gray-400"
|
57 |
+
} p-1`}
|
58 |
+
onClick={() => {
|
59 |
+
setTheme("light");
|
60 |
+
}}
|
61 |
+
>
|
62 |
+
<MdOutlineLightMode />
|
63 |
+
</div>
|
64 |
+
<div
|
65 |
+
className={`size-6 rounded-full flex items-center justify-center ${
|
66 |
+
theme === "dark"
|
67 |
+
? "text-white"
|
68 |
+
: "dark:text-slate-500 text-gray-400"
|
69 |
+
} p-1`}
|
70 |
+
onClick={() => {
|
71 |
+
setTheme("dark");
|
72 |
+
}}
|
73 |
+
>
|
74 |
+
<MdOutlineNightlight />
|
75 |
+
</div>
|
76 |
+
</div>
|
77 |
</div>
|
78 |
</header>
|
79 |
);
|
components/editor/index.tsx
CHANGED
@@ -18,7 +18,7 @@ export const Editor = ({ children }: any) => {
|
|
18 |
});
|
19 |
|
20 |
return (
|
21 |
-
<div className="bg-slate-950 w-full overflow-hidden shadow-xl h-[100vh]">
|
22 |
<EditorHeader onToggleMenu={() => setOpen(!open)} />
|
23 |
<main className="flex h-full">
|
24 |
<EditorSidebar
|
|
|
18 |
});
|
19 |
|
20 |
return (
|
21 |
+
<div className="bg-white dark:bg-slate-950 w-full overflow-hidden shadow-xl h-[100vh]">
|
22 |
<EditorHeader onToggleMenu={() => setOpen(!open)} />
|
23 |
<main className="flex h-full">
|
24 |
<EditorSidebar
|
components/editor/main/endpoint.tsx
CHANGED
@@ -28,9 +28,9 @@ export const Endpoint = ({
|
|
28 |
};
|
29 |
|
30 |
return (
|
31 |
-
<div className="bg-slate-950/40 w-full px-4 xl:px-6 pt-5">
|
32 |
-
<div className="bg-slate-950 p-3 rounded-lg flex items-center justify-between">
|
33 |
-
<div className="text-white text-sm flex items-center justify-start gap-2 w-full">
|
34 |
<Method method={method} />
|
35 |
<div className="flex items-center justify-start gap-1 flex-wrap">
|
36 |
{path_formatted.map((p, i) => {
|
@@ -46,7 +46,7 @@ export const Endpoint = ({
|
|
46 |
}
|
47 |
/>
|
48 |
) : (
|
49 |
-
<p key={i} className="text-slate-300">
|
50 |
{p.content}
|
51 |
</p>
|
52 |
);
|
|
|
28 |
};
|
29 |
|
30 |
return (
|
31 |
+
<div className="bg-white dark:bg-slate-950/40 w-full px-4 xl:px-6 pt-5">
|
32 |
+
<div className="bg-slate-200 border-slate-300 dark:border-0 dark:bg-slate-950 p-3 rounded-lg flex items-center justify-between">
|
33 |
+
<div className="text-gray-600 dark:text-white text-sm flex items-center justify-start gap-2 w-full">
|
34 |
<Method method={method} />
|
35 |
<div className="flex items-center justify-start gap-1 flex-wrap">
|
36 |
{path_formatted.map((p, i) => {
|
|
|
46 |
}
|
47 |
/>
|
48 |
) : (
|
49 |
+
<p key={i} className="text-gray-600 dark:text-slate-300">
|
50 |
{p.content}
|
51 |
</p>
|
52 |
);
|
components/editor/main/index.tsx
CHANGED
@@ -43,7 +43,7 @@ export const EditorMain = ({ endpoint }: { endpoint: ApiRoute }) => {
|
|
43 |
});
|
44 |
|
45 |
return (
|
46 |
-
<div className="flex-1 bg-slate-900/50 h-[calc(100%-56px)]">
|
47 |
<div className="h-full grid grid-cols-1 xl:grid-cols-3">
|
48 |
<Request
|
49 |
parameters={formattedParameters}
|
@@ -65,7 +65,7 @@ export const EditorMain = ({ endpoint }: { endpoint: ApiRoute }) => {
|
|
65 |
onChange={setFormattedEndpoint}
|
66 |
>
|
67 |
<button
|
68 |
-
className="bg-indigo-500 hover:bg-indigo-500/80 text-white px-3 py-1 rounded-lg text-sm"
|
69 |
onClick={submit}
|
70 |
>
|
71 |
Send
|
|
|
43 |
});
|
44 |
|
45 |
return (
|
46 |
+
<div className="flex-1 bg-gray-100 dark:bg-slate-900/50 h-[calc(100%-56px)]">
|
47 |
<div className="h-full grid grid-cols-1 xl:grid-cols-3">
|
48 |
<Request
|
49 |
parameters={formattedParameters}
|
|
|
65 |
onChange={setFormattedEndpoint}
|
66 |
>
|
67 |
<button
|
68 |
+
className="bg-black hover:bg-gray-800 dark:bg-indigo-500 dark:hover:bg-indigo-500/80 text-white px-3 py-1 rounded-lg text-sm"
|
69 |
onClick={submit}
|
70 |
>
|
71 |
Send
|
components/editor/main/parameter.tsx
CHANGED
@@ -14,7 +14,7 @@ export const Parameter: React.FC<Props> = ({ value, onChange }) => {
|
|
14 |
return (
|
15 |
<input
|
16 |
type="text"
|
17 |
-
className="bg-indigo-600 !text-white px-1.5 rounded-md outline-none bg-opacity-80 max-w-[80px] text-center truncate"
|
18 |
onBlur={() => {
|
19 |
onChange(state, previousValue ?? `{${value}}`);
|
20 |
setPreviousValue(state as string);
|
|
|
14 |
return (
|
15 |
<input
|
16 |
type="text"
|
17 |
+
className="bg-indigo-500 dark:bg-indigo-600 !text-white px-1.5 rounded-md outline-none bg-opacity-80 max-w-[80px] text-center truncate"
|
18 |
onBlur={() => {
|
19 |
onChange(state, previousValue ?? `{${value}}`);
|
20 |
setPreviousValue(state as string);
|
components/editor/main/request.tsx
CHANGED
@@ -41,7 +41,7 @@ export const Request = ({
|
|
41 |
useUpdateEffect(() => onBodyChange(bodyForm), [bodyForm]);
|
42 |
|
43 |
return (
|
44 |
-
<div className="h-full bg-slate-900 pb-5 overflow-auto">
|
45 |
<div className="top-0 sticky w-full backdrop-blur">
|
46 |
{children}
|
47 |
<Tabs active={tab} setActive={setTab} endpoint={endpoint} />
|
@@ -49,7 +49,7 @@ export const Request = ({
|
|
49 |
<div className="px-4 xl:px-6">
|
50 |
{tab === "parameters" && parameters && (
|
51 |
<div className="mt-6 grid grid-cols-2 gap-6 w-full">
|
52 |
-
<p className="text-slate-200 uppercase text-xs font-semibold col-span-2">
|
53 |
Optional parameters
|
54 |
</p>
|
55 |
{parameters &&
|
@@ -82,7 +82,7 @@ export const Request = ({
|
|
82 |
)}
|
83 |
{tab === "body" && endpoint?.body?.length && (
|
84 |
<div className="mt-6 grid grid-cols-2 gap-6 w-full">
|
85 |
-
<p className="text-slate-200 uppercase text-xs font-semibold col-span-2">
|
86 |
Body
|
87 |
</p>
|
88 |
{endpoint?.body?.length &&
|
@@ -119,7 +119,7 @@ export const Request = ({
|
|
119 |
)}
|
120 |
{tab === "headers" && (
|
121 |
<div className="mt-8 grid grid-cols-1 gap-6 w-full">
|
122 |
-
<p className="text-slate-200 uppercase text-xs font-semibold">
|
123 |
Headers
|
124 |
</p>
|
125 |
<div className="w-full">
|
|
|
41 |
useUpdateEffect(() => onBodyChange(bodyForm), [bodyForm]);
|
42 |
|
43 |
return (
|
44 |
+
<div className="h-full bg-white dark:bg-slate-900 pb-5 overflow-auto">
|
45 |
<div className="top-0 sticky w-full backdrop-blur">
|
46 |
{children}
|
47 |
<Tabs active={tab} setActive={setTab} endpoint={endpoint} />
|
|
|
49 |
<div className="px-4 xl:px-6">
|
50 |
{tab === "parameters" && parameters && (
|
51 |
<div className="mt-6 grid grid-cols-2 gap-6 w-full">
|
52 |
+
<p className="text-slate-500 dark:text-slate-200 uppercase text-xs dark:font-semibold col-span-2">
|
53 |
Optional parameters
|
54 |
</p>
|
55 |
{parameters &&
|
|
|
82 |
)}
|
83 |
{tab === "body" && endpoint?.body?.length && (
|
84 |
<div className="mt-6 grid grid-cols-2 gap-6 w-full">
|
85 |
+
<p className="text-slate-500 dark:text-slate-200 uppercase text-xs dark:font-semibold col-span-2">
|
86 |
Body
|
87 |
</p>
|
88 |
{endpoint?.body?.length &&
|
|
|
119 |
)}
|
120 |
{tab === "headers" && (
|
121 |
<div className="mt-8 grid grid-cols-1 gap-6 w-full">
|
122 |
+
<p className="text-slate-500 dark:text-slate-200 uppercase text-xs dark:font-semibold col-span-2">
|
123 |
Headers
|
124 |
</p>
|
125 |
<div className="w-full">
|
components/editor/main/response.tsx
CHANGED
@@ -1,15 +1,16 @@
|
|
1 |
import Highlight from "react-highlight";
|
2 |
-
import "node_modules/highlight.js/styles/night-owl.css";
|
3 |
import { Loading } from "@/components/loading";
|
4 |
export const Response = ({ res, loading }: { res: any; loading: boolean }) => {
|
5 |
return (
|
6 |
-
<div className="overflow-auto h-full relative xl:col-span-2">
|
7 |
-
<Highlight className="json text-sm !bg-slate-950/10 !h-full !p-3 !font-code !whitespace-pre-wrap">
|
8 |
{JSON.stringify(res ?? {}, null, 2)}
|
9 |
</Highlight>
|
10 |
{loading && (
|
11 |
<Loading>
|
12 |
-
<p className="text-slate-400 text-lg mt-4">
|
|
|
|
|
13 |
</Loading>
|
14 |
)}
|
15 |
</div>
|
|
|
1 |
import Highlight from "react-highlight";
|
|
|
2 |
import { Loading } from "@/components/loading";
|
3 |
export const Response = ({ res, loading }: { res: any; loading: boolean }) => {
|
4 |
return (
|
5 |
+
<div className="overflow-auto h-full relative xl:col-span-2 border-l border-slate-200 dark:border-slate-700/50">
|
6 |
+
<Highlight className="json text-sm !bg-slate-100 dark:!bg-slate-950/10 !h-full !p-3 !font-code !whitespace-pre-wrap">
|
7 |
{JSON.stringify(res ?? {}, null, 2)}
|
8 |
</Highlight>
|
9 |
{loading && (
|
10 |
<Loading>
|
11 |
+
<p className="text-white dark:text-slate-400 text-lg mt-4">
|
12 |
+
Processing...
|
13 |
+
</p>
|
14 |
</Loading>
|
15 |
)}
|
16 |
</div>
|
components/editor/main/snippet/curl.tsx
CHANGED
@@ -70,17 +70,17 @@ export const CurlSnippet = ({
|
|
70 |
};
|
71 |
|
72 |
return (
|
73 |
-
<div className="bg-slate-950/50 rounded-xl overflow-hidden">
|
74 |
-
<header className="bg-slate-950 flex items-center justify-start px-5 py-4 uppercase gap-2 text-slate-300">
|
75 |
<BiCodeCurly className="text-xl" />
|
76 |
<p className="text-xs font-semibold">Curl</p>
|
77 |
</header>
|
78 |
<main className="px-6 py-6">
|
79 |
-
<Highlight className="curl text-xs font-code !bg-transparent !p-0 !whitespace-pre-wrap break-all !leading-relaxed">
|
80 |
{generateCurlRequestFromEndpoint()}
|
81 |
</Highlight>
|
82 |
<div className="flex justify-end relative" onClick={handleCopy}>
|
83 |
-
<BiSolidCopy className="text-slate-500 cursor-pointer hover:text-slate-300 transition-all duration-75" />
|
84 |
<div
|
85 |
className={classNames(
|
86 |
"bg-indigo-500/60 text-slate-100 text-xs font-semibold absolute bottom-0 right-0 z-10 rounded-lg px-2 py-1 pointer-events-none -translate-y-full transition-all duration-200",
|
|
|
70 |
};
|
71 |
|
72 |
return (
|
73 |
+
<div className="border dark:border-0 border-slate-200 bg-slate-50 dark:bg-slate-950/50 rounded-xl overflow-hidden">
|
74 |
+
<header className="bg-slate-200 dark:bg-slate-950 flex items-center justify-start px-5 py-4 uppercase gap-2 text-slate-600 dark:text-slate-300">
|
75 |
<BiCodeCurly className="text-xl" />
|
76 |
<p className="text-xs font-semibold">Curl</p>
|
77 |
</header>
|
78 |
<main className="px-6 py-6">
|
79 |
+
<Highlight className="curl text-xs font-code !bg-transparent !p-0 !whitespace-pre-wrap break-all !leading-relaxed !text-slate-800 dark:!text-slate-100">
|
80 |
{generateCurlRequestFromEndpoint()}
|
81 |
</Highlight>
|
82 |
<div className="flex justify-end relative" onClick={handleCopy}>
|
83 |
+
<BiSolidCopy className="text-slate-400 dark:text-slate-500 cursor-pointer hover:text-slate-500 dark:hover:text-slate-300 transition-all duration-75" />
|
84 |
<div
|
85 |
className={classNames(
|
86 |
"bg-indigo-500/60 text-slate-100 text-xs font-semibold absolute bottom-0 right-0 z-10 rounded-lg px-2 py-1 pointer-events-none -translate-y-full transition-all duration-200",
|
components/editor/main/snippet/javascript.tsx
CHANGED
@@ -80,13 +80,13 @@ export const JavascriptSnippet = ({
|
|
80 |
};
|
81 |
|
82 |
return (
|
83 |
-
<div className="bg-slate-950/50 rounded-xl overflow-hidden">
|
84 |
-
<header className="bg-slate-950 flex items-center justify-start px-5 py-4 uppercase gap-2 text-
|
85 |
<BiLogoJavascript className="text-xl" />
|
86 |
<p className="text-xs font-semibold">Javascript</p>
|
87 |
</header>
|
88 |
<main className="px-6 py-6">
|
89 |
-
<Highlight className="
|
90 |
{generateJavascriptRequestFromEndpoint()}
|
91 |
</Highlight>
|
92 |
<div className="flex justify-end relative" onClick={handleCopy}>
|
|
|
80 |
};
|
81 |
|
82 |
return (
|
83 |
+
<div className="border dark:border-0 border-slate-200 bg-slate-50 dark:bg-slate-950/50 rounded-xl overflow-hidden">
|
84 |
+
<header className="bg-slate-200 dark:bg-slate-950 flex items-center justify-start px-5 py-4 uppercase gap-2 text-amber-500">
|
85 |
<BiLogoJavascript className="text-xl" />
|
86 |
<p className="text-xs font-semibold">Javascript</p>
|
87 |
</header>
|
88 |
<main className="px-6 py-6">
|
89 |
+
<Highlight className="curl text-xs font-code !bg-transparent !p-0 !whitespace-pre-wrap break-all !leading-relaxed !text-slate-800 dark:!text-slate-100">
|
90 |
{generateJavascriptRequestFromEndpoint()}
|
91 |
</Highlight>
|
92 |
<div className="flex justify-end relative" onClick={handleCopy}>
|
components/editor/main/snippet/python.tsx
CHANGED
@@ -80,13 +80,13 @@ response = requests.${method.toLocaleLowerCase()}(
|
|
80 |
};
|
81 |
|
82 |
return (
|
83 |
-
<div className="bg-slate-950/50 rounded-xl overflow-hidden">
|
84 |
-
<header className="bg-slate-950 flex items-center justify-start px-5 py-4 uppercase gap-2 text-blue-500">
|
85 |
<BiLogoPython className="text-xl" />
|
86 |
<p className="text-xs font-semibold">Python</p>
|
87 |
</header>
|
88 |
<main className="px-6 py-6">
|
89 |
-
<Highlight className="
|
90 |
{generatePythonRequestFromEndpoint()}
|
91 |
</Highlight>
|
92 |
<div className="flex justify-end relative" onClick={handleCopy}>
|
|
|
80 |
};
|
81 |
|
82 |
return (
|
83 |
+
<div className="border dark:border-0 border-slate-200 bg-slate-50 dark:bg-slate-950/50 rounded-xl overflow-hidden">
|
84 |
+
<header className="bg-slate-200 dark:bg-slate-950 flex items-center justify-start px-5 py-4 uppercase gap-2 text-blue-500">
|
85 |
<BiLogoPython className="text-xl" />
|
86 |
<p className="text-xs font-semibold">Python</p>
|
87 |
</header>
|
88 |
<main className="px-6 py-6">
|
89 |
+
<Highlight className="curl text-xs font-code !bg-transparent !p-0 !whitespace-pre-wrap break-all !leading-relaxed !text-slate-800 dark:!text-slate-100">
|
90 |
{generatePythonRequestFromEndpoint()}
|
91 |
</Highlight>
|
92 |
<div className="flex justify-end relative" onClick={handleCopy}>
|
components/editor/main/tabs.tsx
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
import { ApiRoute } from "@/utils/type";
|
2 |
import classNames from "classnames";
|
3 |
|
4 |
-
|
5 |
export const Tabs = ({
|
6 |
active,
|
7 |
setActive,
|
@@ -12,55 +12,25 @@ export const Tabs = ({
|
|
12 |
endpoint: ApiRoute;
|
13 |
}) => {
|
14 |
return (
|
15 |
-
<ul className="flex items-center justify-center gap-
|
16 |
-
|
17 |
-
|
18 |
-
"
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
}
|
34 |
-
)}
|
35 |
-
onClick={() => setActive("parameters")}
|
36 |
-
>
|
37 |
-
Parameters
|
38 |
-
</li>
|
39 |
)}
|
40 |
-
{endpoint?.body && (
|
41 |
-
<li
|
42 |
-
className={classNames(
|
43 |
-
"text-sm text-slate-400 hover:text-slate-400 font-semibold uppercase -tracking-wider cursor-pointer py-4 px-2 border-b-2 border-transparent",
|
44 |
-
{
|
45 |
-
"!border-slate-100 !text-slate-100": "body" === active,
|
46 |
-
}
|
47 |
-
)}
|
48 |
-
onClick={() => setActive("body")}
|
49 |
-
>
|
50 |
-
Body
|
51 |
-
</li>
|
52 |
-
)}
|
53 |
-
<li
|
54 |
-
className={classNames(
|
55 |
-
"text-sm text-slate-400 hover:text-slate-400 font-semibold uppercase -tracking-wider cursor-pointer py-4 px-2 border-b-2 border-transparent",
|
56 |
-
{
|
57 |
-
"!border-slate-100 !text-slate-100": "snippet" === active,
|
58 |
-
}
|
59 |
-
)}
|
60 |
-
onClick={() => setActive("snippet")}
|
61 |
-
>
|
62 |
-
Snippet
|
63 |
-
</li>
|
64 |
</ul>
|
65 |
);
|
66 |
};
|
|
|
1 |
import { ApiRoute } from "@/utils/type";
|
2 |
import classNames from "classnames";
|
3 |
|
4 |
+
const TABS = ["headers", "parameters", "body", "snippet"];
|
5 |
export const Tabs = ({
|
6 |
active,
|
7 |
setActive,
|
|
|
12 |
endpoint: ApiRoute;
|
13 |
}) => {
|
14 |
return (
|
15 |
+
<ul className="border-b border-gray-200 dark:border-0 flex items-center justify-center gap-0 bg-white dark:bg-slate-950/40">
|
16 |
+
{TABS.map(
|
17 |
+
(tab: string) =>
|
18 |
+
(["headers", "snippet"].includes(tab) || tab in endpoint) && (
|
19 |
+
<li
|
20 |
+
key={tab}
|
21 |
+
className={classNames(
|
22 |
+
"text-sm px-6 text-gray-400 hover:text-gray-500 dark:text-slate-400 dark:hover:text-slate-400 dark:font-semibold uppercase -tracking-wider cursor-pointer py-4 border-b-2 border-transparent",
|
23 |
+
{
|
24 |
+
"!text-gray-500 !border-black dark:!border-slate-100 dark:!text-slate-100":
|
25 |
+
tab === active,
|
26 |
+
}
|
27 |
+
)}
|
28 |
+
onClick={() => setActive(tab as any)}
|
29 |
+
>
|
30 |
+
{tab.charAt(0).toUpperCase() + tab.slice(1)}
|
31 |
+
</li>
|
32 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
</ul>
|
35 |
);
|
36 |
};
|
components/editor/sidebar.tsx
CHANGED
@@ -28,7 +28,7 @@ export const EditorSidebar = ({
|
|
28 |
return (
|
29 |
<div
|
30 |
className={classNames(
|
31 |
-
"min-w-[300px] transition-all flex flex-col items-start justify-between duration-200 xl:max-w-sm w-2/3 xl:w-full bg-slate-900 border-r border-slate-700/40 h-[calc(100%-56px)] overflow-auto fixed top-[56px] xl:top-0 left-0 xl:relative z-10 -translate-x-full xl:!translate-x-0",
|
32 |
{
|
33 |
"translate-x-0 h-[calc(100%-56px)]": open,
|
34 |
}
|
@@ -39,9 +39,9 @@ export const EditorSidebar = ({
|
|
39 |
<li key={collection.key} className="block w-full">
|
40 |
<div
|
41 |
className={classNames(
|
42 |
-
"p-4 border-b border-slate-700/70 text-slate-400 cursor-pointer hover:bg-slate-700/30 flex items-center justify-between transition-all duration-200 select-none active:bg-indigo-600 active:text-slate-100",
|
43 |
{
|
44 |
-
"bg-
|
45 |
collections.includes(collection.key),
|
46 |
}
|
47 |
)}
|
@@ -68,16 +68,16 @@ export const EditorSidebar = ({
|
|
68 |
</div>
|
69 |
</div>
|
70 |
{collections.includes(collection.key) && (
|
71 |
-
<div className="bg-slate-700/20 w-full p-3 border-b border-slate-700/70">
|
72 |
<ul className="w-full">
|
73 |
{collection.endpoints.map((end, e) => (
|
74 |
<Link
|
75 |
key={e}
|
76 |
href={`/${collection.key}/${e}`}
|
77 |
className={classNames(
|
78 |
-
"text-slate-400 font-semibold text-xs flex items-center justify-start gap-2 rounded-md p-2.5 hover:bg-slate-600 hover:bg-opacity-10 cursor-pointer border-t border-b border-transparent select-none",
|
79 |
{
|
80 |
-
"bg-slate-
|
81 |
pathname.includes(`/${collection.key}/${e}`),
|
82 |
}
|
83 |
)}
|
@@ -96,14 +96,14 @@ export const EditorSidebar = ({
|
|
96 |
<a
|
97 |
href="https://huggingface.co/spaces/enzostvs/hub-api-playground/discussions/1"
|
98 |
target="_blank"
|
99 |
-
className="text-slate-300 font-semibold text-sm p-5 flex w-full bg-slate-950/20 hover:bg-slate-950/40 border-
|
100 |
>
|
101 |
Give Feedback
|
102 |
</a>
|
103 |
<a
|
104 |
href="https://huggingface.co/docs/hub/api"
|
105 |
target="_blank"
|
106 |
-
className="text-slate-300 font-semibold text-sm p-5 flex w-full bg-slate-950/20 hover:bg-slate-950/40"
|
107 |
>
|
108 |
See HUB API documentation
|
109 |
</a>
|
|
|
28 |
return (
|
29 |
<div
|
30 |
className={classNames(
|
31 |
+
"min-w-[300px] transition-all flex flex-col items-start justify-between duration-200 xl:max-w-sm w-2/3 xl:w-full bg-white border-slate-200 dark:bg-slate-900 border-r dark:border-slate-700/40 h-[calc(100%-56px)] overflow-auto fixed top-[56px] xl:top-0 left-0 xl:relative z-10 -translate-x-full xl:!translate-x-0",
|
32 |
{
|
33 |
"translate-x-0 h-[calc(100%-56px)]": open,
|
34 |
}
|
|
|
39 |
<li key={collection.key} className="block w-full">
|
40 |
<div
|
41 |
className={classNames(
|
42 |
+
"w-[calc(100%+1px)] p-4 border-b border-slate-200 dark:border-slate-700/70 text-slate-600 dark:text-slate-400 cursor-pointer hover:bg-slate-100 dark:hover:bg-slate-700/30 flex items-center justify-between transition-all duration-200 select-none active:bg-slate-200 dark:active:bg-indigo-600 active:text-slate-100",
|
43 |
{
|
44 |
+
"!bg-slate-200 dark:!bg-indigo-600 dark:hover:!bg-indigo-600 !border-slate-200 dark:!border-indigo-500 dark:!text-slate-200":
|
45 |
collections.includes(collection.key),
|
46 |
}
|
47 |
)}
|
|
|
68 |
</div>
|
69 |
</div>
|
70 |
{collections.includes(collection.key) && (
|
71 |
+
<div className="bg-slate-50 dark:bg-slate-700/20 w-full p-3 border-b border-slate-200 dark:border-slate-700/70">
|
72 |
<ul className="w-full">
|
73 |
{collection.endpoints.map((end, e) => (
|
74 |
<Link
|
75 |
key={e}
|
76 |
href={`/${collection.key}/${e}`}
|
77 |
className={classNames(
|
78 |
+
"text-slate-500 dark:text-slate-400 font-semibold text-xs flex items-center justify-start gap-2 rounded-md p-2.5 hover:bg-slate-200 dark:hover:bg-slate-600 dark:hover:bg-opacity-10 cursor-pointer border-t border-b border-transparent select-none",
|
79 |
{
|
80 |
+
"bg-slate-200 dark:bg-slate-600/20 !text-slate-800 dark:!text-slate-200 border-b !border-b-slate-50 !border-t-slate-300 dark:!border-b-slate-700/70 border-t dark:!border-t-slate-800":
|
81 |
pathname.includes(`/${collection.key}/${e}`),
|
82 |
}
|
83 |
)}
|
|
|
96 |
<a
|
97 |
href="https://huggingface.co/spaces/enzostvs/hub-api-playground/discussions/1"
|
98 |
target="_blank"
|
99 |
+
className="text-slate-500 dark:text-slate-300 dark:font-semibold text-sm p-5 flex w-full bg-transparent hover:bg-slate-100 border-slate-200 dark:bg-slate-950/20 dark:hover:bg-slate-950/40 border-t dark:border-slate-800"
|
100 |
>
|
101 |
Give Feedback
|
102 |
</a>
|
103 |
<a
|
104 |
href="https://huggingface.co/docs/hub/api"
|
105 |
target="_blank"
|
106 |
+
className="text-slate-500 dark:text-slate-300 dark:font-semibold text-sm p-5 flex w-full bg-transparent hover:bg-slate-100 border-slate-200 dark:bg-slate-950/20 dark:hover:bg-slate-950/40 border-t dark:border-slate-800"
|
107 |
>
|
108 |
See HUB API documentation
|
109 |
</a>
|
components/input/input.tsx
CHANGED
@@ -37,13 +37,13 @@ export const TextInput: React.FC<Props> = ({
|
|
37 |
<div className="flex items-center justify-start gap-2 relative">
|
38 |
{tooltip && (
|
39 |
<div className="group cursor-pointer">
|
40 |
-
<HiInformationCircle className="text-slate-500 group-hover:text-slate-300 text-xl" />
|
41 |
-
<div className="bg-slate-950/90 z-10 rounded-xl p-3 text-white absolute text-xs left-0 bottom-0 translate-y-[calc(100%+8px)] opacity-0 transition-all duration-200 group-hover:opacity-100 pointer-events-none group-hover:pointer-events-auto">
|
42 |
{tooltip}
|
43 |
</div>
|
44 |
</div>
|
45 |
)}
|
46 |
-
<label className="text-slate-400 text-sm font-medium capitalize">
|
47 |
{label}:
|
48 |
</label>
|
49 |
</div>
|
@@ -52,7 +52,7 @@ export const TextInput: React.FC<Props> = ({
|
|
52 |
value={value}
|
53 |
placeholder={placeholder}
|
54 |
onChange={handleInputChange}
|
55 |
-
className="transition-all duration-200 truncate w-full h-full px-4 py-
|
56 |
/>
|
57 |
</div>
|
58 |
);
|
|
|
37 |
<div className="flex items-center justify-start gap-2 relative">
|
38 |
{tooltip && (
|
39 |
<div className="group cursor-pointer">
|
40 |
+
<HiInformationCircle className="text-slate-400 dark:text-slate-500 group-hover:text-slate-600 dark:group-hover:text-slate-300 text-xl" />
|
41 |
+
<div className="bg-black dark:bg-slate-950/90 z-10 rounded-xl p-3 text-white absolute text-xs left-0 bottom-0 translate-y-[calc(100%+8px)] opacity-0 transition-all duration-200 group-hover:opacity-100 pointer-events-none group-hover:pointer-events-auto">
|
42 |
{tooltip}
|
43 |
</div>
|
44 |
</div>
|
45 |
)}
|
46 |
+
<label className="text-slate-500 dark:text-slate-400 text-sm dark:font-medium capitalize">
|
47 |
{label}:
|
48 |
</label>
|
49 |
</div>
|
|
|
52 |
value={value}
|
53 |
placeholder={placeholder}
|
54 |
onChange={handleInputChange}
|
55 |
+
className="transition-all text-sm duration-200 truncate w-full h-full px-4 py-3 bg-white dark:bg-slate-950/50 rounded-lg outline-none text-slate-600 dark:text-slate-200 placeholder:text-slate-400 dark:placeholder:text-slate-600 focus:ring-4 focus:ring-indigo-400/20 dark:focus:ring-indigo-600/50 border border-slate-200 dark:border-slate-950/50 focus:border-indigo-300 dark:focus:border-indigo-500"
|
56 |
/>
|
57 |
</div>
|
58 |
);
|
components/input/toggle.tsx
CHANGED
@@ -25,19 +25,19 @@ export const Toggle: React.FC<Props> = ({
|
|
25 |
<div className="flex items-center justify-start gap-2">
|
26 |
{tooltip && (
|
27 |
<div className="group cursor-pointer">
|
28 |
-
<HiInformationCircle className="text-slate-500 group-hover:text-slate-300 text-xl" />
|
29 |
-
<div className="bg-slate-950/90 z-10 min-w-[200px] rounded-xl p-3 text-white absolute text-xs left-0 bottom-0 translate-y-[calc(100%+8px)] opacity-0 transition-all duration-200 group-hover:opacity-100 pointer-events-none group-hover:pointer-events-auto">
|
30 |
{tooltip}
|
31 |
</div>
|
32 |
</div>
|
33 |
)}
|
34 |
-
<label className="text-slate-400 text-sm font-medium capitalize">
|
35 |
{label}:
|
36 |
</label>
|
37 |
</div>
|
38 |
<div
|
39 |
className={classNames(
|
40 |
-
"w-[
|
41 |
{
|
42 |
"bg-red-700": !checkedState,
|
43 |
"bg-green-500": checkedState,
|
@@ -47,10 +47,10 @@ export const Toggle: React.FC<Props> = ({
|
|
47 |
>
|
48 |
<div
|
49 |
className={classNames(
|
50 |
-
"rounded-full h-[
|
51 |
{
|
52 |
-
"
|
53 |
-
"
|
54 |
}
|
55 |
)}
|
56 |
/>
|
|
|
25 |
<div className="flex items-center justify-start gap-2">
|
26 |
{tooltip && (
|
27 |
<div className="group cursor-pointer">
|
28 |
+
<HiInformationCircle className="text-slate-400 dark:text-slate-500 group-hover:text-slate-600 dark:group-hover:text-slate-300 text-xl" />
|
29 |
+
<div className="bg-black dark:bg-slate-950/90 z-10 min-w-[200px] rounded-xl p-3 text-white absolute text-xs left-0 bottom-0 translate-y-[calc(100%+8px)] opacity-0 transition-all duration-200 group-hover:opacity-100 pointer-events-none group-hover:pointer-events-auto">
|
30 |
{tooltip}
|
31 |
</div>
|
32 |
</div>
|
33 |
)}
|
34 |
+
<label className="text-slate-500 dark:text-slate-400 text-sm dark:font-medium capitalize">
|
35 |
{label}:
|
36 |
</label>
|
37 |
</div>
|
38 |
<div
|
39 |
className={classNames(
|
40 |
+
"w-[32px] h-[20px] rounded-full px-[4px] relative cursor-pointer",
|
41 |
{
|
42 |
"bg-red-700": !checkedState,
|
43 |
"bg-green-500": checkedState,
|
|
|
47 |
>
|
48 |
<div
|
49 |
className={classNames(
|
50 |
+
"rounded-full h-[12px] w-[12px] bg-slate-50 shadow-xl absolute top-[4px] transition-all duration-200",
|
51 |
{
|
52 |
+
"translate-x-0": !checkedState,
|
53 |
+
"translate-x-full": checkedState,
|
54 |
}
|
55 |
)}
|
56 |
/>
|
index.d.ts
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
declare module "highlight.js/styles/atom-one-dark.css" {
|
2 |
+
const content: { [className: string]: string };
|
3 |
+
export default content;
|
4 |
+
}
|
5 |
+
|
6 |
+
declare module "highlight.js/styles/github.css" {
|
7 |
+
const content: { [className: string]: string };
|
8 |
+
export default content;
|
9 |
+
}
|
package-lock.json
CHANGED
@@ -10,6 +10,7 @@
|
|
10 |
"dependencies": {
|
11 |
"classnames": "^2.3.2",
|
12 |
"next": "13.5.6",
|
|
|
13 |
"react": "^18",
|
14 |
"react-dom": "^18",
|
15 |
"react-highlight": "^0.15.0",
|
@@ -3057,6 +3058,16 @@
|
|
3057 |
}
|
3058 |
}
|
3059 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3060 |
"node_modules/node-releases": {
|
3061 |
"version": "2.0.13",
|
3062 |
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
|
|
|
10 |
"dependencies": {
|
11 |
"classnames": "^2.3.2",
|
12 |
"next": "13.5.6",
|
13 |
+
"next-themes": "^0.4.6",
|
14 |
"react": "^18",
|
15 |
"react-dom": "^18",
|
16 |
"react-highlight": "^0.15.0",
|
|
|
3058 |
}
|
3059 |
}
|
3060 |
},
|
3061 |
+
"node_modules/next-themes": {
|
3062 |
+
"version": "0.4.6",
|
3063 |
+
"resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz",
|
3064 |
+
"integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==",
|
3065 |
+
"license": "MIT",
|
3066 |
+
"peerDependencies": {
|
3067 |
+
"react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc",
|
3068 |
+
"react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc"
|
3069 |
+
}
|
3070 |
+
},
|
3071 |
"node_modules/node-releases": {
|
3072 |
"version": "2.0.13",
|
3073 |
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
|
package.json
CHANGED
@@ -11,6 +11,7 @@
|
|
11 |
"dependencies": {
|
12 |
"classnames": "^2.3.2",
|
13 |
"next": "13.5.6",
|
|
|
14 |
"react": "^18",
|
15 |
"react-dom": "^18",
|
16 |
"react-highlight": "^0.15.0",
|
|
|
11 |
"dependencies": {
|
12 |
"classnames": "^2.3.2",
|
13 |
"next": "13.5.6",
|
14 |
+
"next-themes": "^0.4.6",
|
15 |
"react": "^18",
|
16 |
"react-dom": "^18",
|
17 |
"react-highlight": "^0.15.0",
|
tailwind.config.ts
CHANGED
@@ -1,17 +1,18 @@
|
|
1 |
-
import type { Config } from
|
2 |
|
3 |
const config: Config = {
|
|
|
4 |
content: [
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
],
|
9 |
theme: {
|
10 |
fontFamily: {
|
11 |
-
sans: [
|
12 |
-
code: [
|
13 |
-
}
|
14 |
},
|
15 |
plugins: [],
|
16 |
-
}
|
17 |
-
export default config
|
|
|
1 |
+
import type { Config } from "tailwindcss";
|
2 |
|
3 |
const config: Config = {
|
4 |
+
darkMode: "class",
|
5 |
content: [
|
6 |
+
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
7 |
+
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
8 |
+
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
9 |
],
|
10 |
theme: {
|
11 |
fontFamily: {
|
12 |
+
sans: ["var(--font-inter)", "sans-serif"],
|
13 |
+
code: ["var(--font-fira-code)", "monospace"],
|
14 |
+
},
|
15 |
},
|
16 |
plugins: [],
|
17 |
+
};
|
18 |
+
export default config;
|