"use client"; import { Badge } from "@/components/ui/badge"; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@/components/ui/collapsible"; import { cn } from "@/lib/utils"; import { ChevronRightIcon } from "lucide-react"; import type { ComponentProps, HTMLAttributes } from "react"; import { createContext, useContext, useMemo } from "react"; type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE"; interface SchemaParameter { name: string; type: string; required?: boolean; description?: string; location?: "path" | "query" | "header"; } interface SchemaProperty { name: string; type: string; required?: boolean; description?: string; properties?: SchemaProperty[]; items?: SchemaProperty; } interface SchemaDisplayContextType { method: HttpMethod; path: string; description?: string; parameters?: SchemaParameter[]; requestBody?: SchemaProperty[]; responseBody?: SchemaProperty[]; } const SchemaDisplayContext = createContext({ method: "GET", path: "", }); const methodStyles: Record = { DELETE: "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400", GET: "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400", PATCH: "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400", POST: "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400", PUT: "bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-400", }; export type SchemaDisplayHeaderProps = HTMLAttributes; export const SchemaDisplayHeader = ({ className, children, ...props }: SchemaDisplayHeaderProps) => (
{children}
); export type SchemaDisplayMethodProps = ComponentProps; export const SchemaDisplayMethod = ({ className, children, ...props }: SchemaDisplayMethodProps) => { const { method } = useContext(SchemaDisplayContext); return ( {children ?? method} ); }; export type SchemaDisplayPathProps = HTMLAttributes; export const SchemaDisplayPath = ({ className, children, ...props }: SchemaDisplayPathProps) => { const { path } = useContext(SchemaDisplayContext); // Highlight path parameters const highlightedPath = path.replaceAll( /\{([^}]+)\}/g, '{$1}' ); return ( ); }; export type SchemaDisplayDescriptionProps = HTMLAttributes; export const SchemaDisplayDescription = ({ className, children, ...props }: SchemaDisplayDescriptionProps) => { const { description } = useContext(SchemaDisplayContext); return (

{children ?? description}

); }; export type SchemaDisplayContentProps = HTMLAttributes; export const SchemaDisplayContent = ({ className, children, ...props }: SchemaDisplayContentProps) => (
{children}
); export type SchemaDisplayParameterProps = HTMLAttributes & SchemaParameter; export const SchemaDisplayParameter = ({ name, type, required, description, location, className, ...props }: SchemaDisplayParameterProps) => (
{name} {type} {location && ( {location} )} {required && ( required )}
{description && (

{description}

)}
); export type SchemaDisplayParametersProps = ComponentProps; export const SchemaDisplayParameters = ({ className, children, ...props }: SchemaDisplayParametersProps) => { const { parameters } = useContext(SchemaDisplayContext); return ( Parameters {parameters?.length}
{children ?? parameters?.map((param) => ( ))}
); }; export type SchemaDisplayPropertyProps = HTMLAttributes & SchemaProperty & { depth?: number; }; export const SchemaDisplayProperty = ({ name, type, required, description, properties, items, depth = 0, className, ...props }: SchemaDisplayPropertyProps) => { const hasChildren = properties || items; const paddingLeft = 40 + depth * 16; if (hasChildren) { return ( {name} {type} {required && ( required )} {description && (

{description}

)}
{properties?.map((prop) => ( ))} {items && ( )}
); } return (
{/* Spacer for alignment */} {name} {type} {required && ( required )}
{description && (

{description}

)}
); }; export type SchemaDisplayRequestProps = ComponentProps; export const SchemaDisplayRequest = ({ className, children, ...props }: SchemaDisplayRequestProps) => { const { requestBody } = useContext(SchemaDisplayContext); return ( Request Body
{children ?? requestBody?.map((prop) => ( ))}
); }; export type SchemaDisplayResponseProps = ComponentProps; export const SchemaDisplayResponse = ({ className, children, ...props }: SchemaDisplayResponseProps) => { const { responseBody } = useContext(SchemaDisplayContext); return ( Response
{children ?? responseBody?.map((prop) => ( ))}
); }; export type SchemaDisplayProps = HTMLAttributes & { method: HttpMethod; path: string; description?: string; parameters?: SchemaParameter[]; requestBody?: SchemaProperty[]; responseBody?: SchemaProperty[]; }; export const SchemaDisplay = ({ method, path, description, parameters, requestBody, responseBody, className, children, ...props }: SchemaDisplayProps) => { const contextValue = useMemo( () => ({ description, method, parameters, path, requestBody, responseBody, }), [description, method, parameters, path, requestBody, responseBody] ); return (
{children ?? ( <>
{description && } {parameters && parameters.length > 0 && ( )} {requestBody && requestBody.length > 0 && ( )} {responseBody && responseBody.length > 0 && ( )} )}
); }; export type SchemaDisplayBodyProps = HTMLAttributes; export const SchemaDisplayBody = ({ className, children, ...props }: SchemaDisplayBodyProps) => (
{children}
); export type SchemaDisplayExampleProps = HTMLAttributes; export const SchemaDisplayExample = ({ className, children, ...props }: SchemaDisplayExampleProps) => (
    {children}
  
);