components/fumastudio/base-url.tsx "use client";
import { colors } from "@/components/fumastudio/colors";
import { useConfig } from "@/components/fumastudio/config-provider";
import { CheckCircleFilled } from "@/components/fumastudio/icons";
import {
MockRequest,
useMockRequest,
} from "@/components/fumastudio/mock-request";
import { Button } from "@/components/ui/button";
import { useClipboard } from "@/hooks/use-clipboard";
import { cn } from "@/lib/utils";
import { Copy } from "lucide-react";
import { useState } from "react";
const BaseURL = (props: { url: string; method: string }) => {
const tokens = props.url.match(/\/|{[^}]+}|[^/]+/g) ?? [];
const { isCopied, copyValue } = useClipboard();
const config = useConfig();
const showTryItButton = config?.enableTryItButton;
const [showTryItDialog, setShowTryItDialog] = useState(false);
return (
<div
className={`group grid grid-cols-[auto_1fr_auto] gap-x-2 mt-6 border border-input p-2.5 rounded-xl items-center cursor-pointer ${showTryItButton ? "h-[3.3rem]" : "h-12"}`}>
<div className="flex justify-center">
<p
className={`rounded-lg font-bold px-1.5 py-0.5 text-sm leading-5 ${colors(props.method)}`}>
{props.method}
</p>
</div>
{/* URL parts */}
<div
className="overflow-x-auto no-scrollbar"
onClick={() => copyValue(props.url)}>
<div className="flex justify-start items-center gap-0.5 font-mono text-sm whitespace-nowrap">
{tokens.map((item, index) => {
if (!item) return null;
const key = `${item}-${index}`;
if (item === "/") {
return (
<span
key={key}
className="text-gray-400">
{item}
</span>
);
}
if (
item.startsWith("{") &&
item.endsWith("}")
) {
return (
<span
key={key}
className={`font-medium rounded-md px-px border-2 min-w-max ${colors(props.method, { isSpecial: true })}`}>
{item}
</span>
);
}
if (item.startsWith(":")) {
return (
<span
key={key}
className={`font-medium rounded-md px-px border-2 min-w-max ${colors(props.method, { isSpecial: true })}`}>
{item}
</span>
);
}
return (
<span
key={key}
className="font-medium text-sm text-gray-800 dark:text-white min-w-max">
{item}
</span>
);
})}
</div>
</div>
<div className="flex items-center justify-start text-muted-foreground gap-x-2.5">
{!isCopied && (
<Copy className="size-4 cursor-pointer" />
)}
{isCopied && (
<CheckCircleFilled className="size-5 cursor-pointer" />
)}
{showTryItButton && (
<MockRequest
url={props.url}
open={showTryItDialog}
onOpenChange={setShowTryItDialog}>
<Button
className="rounded-lg hidden md:flex cursor-pointer border border-input text-sm font-mono leading-5 tracking-tighter"
size="sm"
onClick={() =>
setShowTryItDialog(
!showTryItDialog,
)
}>
Try it
</Button>
</MockRequest>
)}
</div>
</div>
);
};
const MockRequestBaseURL = (props: { className?: string; url: string }) => {
const { baseURL, selectedRequest } = useMockRequest();
// (...) placeholder for the baseURL
const url = `...${props.url || ""}`;
const method = selectedRequest?.method || "GET";
const tokens = url.match(/\/|{[^}]+}|[^/]+/g) ?? [];
const { isCopied, copyValue } = useClipboard();
return (
<div
className={cn(
"group grid grid-cols-[auto_1fr_auto] gap-x-2 border border-input p-1.5 rounded-lg items-center cursor-pointer h-9",
props.className,
)}>
<div className="flex justify-center">
<p
className={`rounded-lg font-bold px-1.5 py-0.5 text-sm leading-5 ${colors(method)}`}>
{method}
</p>
</div>
{/* URL parts */}
<div
className="overflow-x-auto scrollbar-hide"
onClick={() => copyValue(url)}>
<div className="flex justify-start items-center gap-0.5 font-mono text-sm whitespace-nowrap">
{tokens.map((item, index) => {
if (!item) return null;
const key = `${item}-${index}`;
if (item === "/") {
return (
<span
key={key}
className="text-gray-400">
{item}
</span>
);
}
if (
item.startsWith("{") &&
item.endsWith("}")
) {
return (
<span
key={key}
className={`font-medium rounded-md px-px border-2 min-w-max ${colors(method, { isSpecial: true })}`}>
{item}
</span>
);
}
if (item.startsWith("...")) {
return (
<span
key={key}
className={`font-medium italic transition-all duration-500 group rounded-md px-px border-2 min-w-max ${colors(method, { isSpecial: true })}`}>
<span className="block group-hover:hidden">
{item}
</span>
<span className="hidden group-hover:flex">
{baseURL}
</span>
</span>
);
}
if (item.startsWith(":")) {
return (
<span
key={key}
className={`font-medium rounded-md px-px border-2 min-w-max ${colors(method, { isSpecial: true })}`}>
{item}
</span>
);
}
return (
<span
key={key}
className="font-medium text-sm text-gray-800 dark:text-white min-w-max">
{item}
</span>
);
})}
</div>
</div>
<div className=" hidden md:group-hover:flex items-center mr-0.5 text-muted-foreground">
{!isCopied && (
<Copy className="size-4 cursor-pointer" />
)}
{isCopied && (
<CheckCircleFilled className="size-5 cursor-pointer" />
)}
</div>
</div>
);
};
export { BaseURL, MockRequestBaseURL };