|
|
@@ -10,55 +10,15 @@ import {
|
|
|
SheetContent,
|
|
|
SheetTitle,
|
|
|
} from "@/components/ui/sheet";
|
|
|
-
|
|
|
-const navigation = [
|
|
|
- {
|
|
|
- title: "Getting Started",
|
|
|
- items: [
|
|
|
- { title: "Introduction", href: "/docs" },
|
|
|
- { title: "Installation", href: "/docs/installation" },
|
|
|
- { title: "Quick Start", href: "/docs/quick-start" },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- title: "Core Concepts",
|
|
|
- items: [
|
|
|
- { title: "Catalog", href: "/docs/catalog" },
|
|
|
- { title: "Registry", href: "/docs/registry" },
|
|
|
- { title: "Data Binding", href: "/docs/data-binding" },
|
|
|
- { title: "Actions", href: "/docs/actions" },
|
|
|
- { title: "Visibility", href: "/docs/visibility" },
|
|
|
- { title: "Validation", href: "/docs/validation" },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- title: "Guides",
|
|
|
- items: [
|
|
|
- { title: "AI SDK Integration", href: "/docs/ai-sdk" },
|
|
|
- { title: "Streaming", href: "/docs/streaming" },
|
|
|
- { title: "Code Export", href: "/docs/code-export" },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- title: "API Reference",
|
|
|
- items: [
|
|
|
- { title: "@json-render/core", href: "/docs/api/core" },
|
|
|
- { title: "@json-render/react", href: "/docs/api/react" },
|
|
|
- { title: "@json-render/codegen", href: "/docs/api/codegen" },
|
|
|
- ],
|
|
|
- },
|
|
|
-];
|
|
|
-
|
|
|
-// Flatten all pages for current page lookup
|
|
|
-const allPages = navigation.flatMap((section) => section.items);
|
|
|
+import { docsNavigation, allDocsPages } from "@/lib/docs-navigation";
|
|
|
|
|
|
export function DocsMobileNav() {
|
|
|
const [open, setOpen] = useState(false);
|
|
|
const pathname = usePathname();
|
|
|
|
|
|
const currentPage = useMemo(() => {
|
|
|
- const page = allPages.find((page) => page.href === pathname);
|
|
|
- return page ?? allPages[0];
|
|
|
+ const page = allDocsPages.find((page) => page.href === pathname);
|
|
|
+ return page ?? allDocsPages[0];
|
|
|
}, [pathname]);
|
|
|
|
|
|
return (
|
|
|
@@ -72,27 +32,49 @@ export function DocsMobileNav() {
|
|
|
<SheetContent className="overflow-y-auto p-6">
|
|
|
<SheetTitle className="mb-6">Table of Contents</SheetTitle>
|
|
|
<nav className="space-y-6">
|
|
|
- {navigation.map((section) => (
|
|
|
+ {docsNavigation.map((section) => (
|
|
|
<div key={section.title}>
|
|
|
<h4 className="text-xs font-medium text-muted-foreground uppercase tracking-wider mb-2">
|
|
|
{section.title}
|
|
|
</h4>
|
|
|
<ul className="space-y-1">
|
|
|
- {section.items.map((item) => (
|
|
|
- <li key={item.href}>
|
|
|
- <Link
|
|
|
- href={item.href}
|
|
|
- onClick={() => setOpen(false)}
|
|
|
- className={`text-sm block py-2 transition-colors ${
|
|
|
- pathname === item.href
|
|
|
- ? "text-primary font-medium"
|
|
|
- : "text-muted-foreground hover:text-foreground"
|
|
|
- }`}
|
|
|
- >
|
|
|
- {item.title}
|
|
|
- </Link>
|
|
|
- </li>
|
|
|
- ))}
|
|
|
+ {section.items.map((item) => {
|
|
|
+ const isExternal = item.external;
|
|
|
+ return (
|
|
|
+ <li key={item.href}>
|
|
|
+ <Link
|
|
|
+ href={item.href}
|
|
|
+ onClick={() => setOpen(false)}
|
|
|
+ {...(isExternal && {
|
|
|
+ target: "_blank",
|
|
|
+ rel: "noopener noreferrer",
|
|
|
+ })}
|
|
|
+ className={`text-sm block py-2 transition-colors ${
|
|
|
+ pathname === item.href
|
|
|
+ ? "text-primary font-medium"
|
|
|
+ : "text-muted-foreground hover:text-foreground"
|
|
|
+ } ${isExternal ? "inline-flex items-center gap-1" : ""}`}
|
|
|
+ >
|
|
|
+ {item.title}
|
|
|
+ {isExternal && (
|
|
|
+ <svg
|
|
|
+ className="w-3 h-3"
|
|
|
+ fill="none"
|
|
|
+ stroke="currentColor"
|
|
|
+ viewBox="0 0 24 24"
|
|
|
+ >
|
|
|
+ <path
|
|
|
+ strokeLinecap="round"
|
|
|
+ strokeLinejoin="round"
|
|
|
+ strokeWidth={2}
|
|
|
+ d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
|
+ />
|
|
|
+ </svg>
|
|
|
+ )}
|
|
|
+ </Link>
|
|
|
+ </li>
|
|
|
+ );
|
|
|
+ })}
|
|
|
</ul>
|
|
|
</div>
|
|
|
))}
|