From 73a9843d4e3f10bc66fb6cc0a33d7e13fd7a224d Mon Sep 17 00:00:00 2001
From: Wildan Nursahidan <>
Date: Sun, 25 May 2025 03:20:17 +0700
Subject: [PATCH] fix release version 1.11.0
---
CHANGELOG.md | 373 ---
README.md | 2 -
app/blog/[slug]/page.tsx | 92 -
app/blog/layout.tsx | 9 -
app/blog/page.tsx | 103 -
app/changelog/layout.tsx | 11 -
app/changelog/page.tsx | 42 -
app/docs/[[...slug]]/page.tsx | 8 +-
app/docs/layout.tsx | 7 +-
app/page.tsx | 4 +-
components/GithubStart.tsx | 44 +
components/changelog/change-group.tsx | 45 -
components/changelog/floating-version.tsx | 86 -
components/changelog/version-entry.tsx | 113 -
components/changelog/version-tag.tsx | 14 -
components/changelog/version-toc.tsx | 111 -
components/docs-breadcrumb.tsx | 2 +-
components/leftbar.tsx | 55 +-
components/markdown/ReleaseMdx.tsx | 107 +
components/markdown/mdx-provider.tsx | 34 +-
components/mob-toc.tsx | 142 +-
components/navbar.tsx | 22 +-
components/scroll-to-top.tsx | 96 +-
components/search.tsx | 24 +-
components/toc-observer.tsx | 249 +-
components/toc.tsx | 18 +-
components/ui/interactive-hover-button.tsx | 2 +-
.../docs/getting-started/changelog/index.mdx | 512 ++++
.../components/accordion/index.mdx | 4 +-
.../components/button/index.mdx | 4 +-
.../components/card-group/index.mdx | 4 +-
.../getting-started/components/card/index.mdx | 4 +-
.../components/code-block/index.mdx | 4 +-
.../components/image/index.mdx | 2 +-
.../getting-started/components/link/index.mdx | 2 +-
.../getting-started/components/note/index.mdx | 2 +-
.../components/release-note/index.mdx | 146 +-
.../components/stepper/index.mdx | 2 +-
.../getting-started/components/tabs/index.mdx | 2 +-
.../components/tooltips/index.mdx | 4 +-
.../components/youtube/index.mdx | 2 +-
.../getting-started/introduction/index.mdx | 1 -
.../project-structure/index.mdx | 26 +-
.../quick-start-guide/index.mdx | 238 +-
docu.json | 15 +-
hooks/index.ts | 2 +
hooks/useActiveSection.ts | 68 +
hooks/useScrollPosition.ts | 28 +
lib/markdown.ts | 45 +-
lib/toc.ts | 9 +
package-lock.json | 2363 +++--------------
package.json | 5 +-
styles/syntax.css | 10 -
53 files changed, 1985 insertions(+), 3334 deletions(-)
delete mode 100644 CHANGELOG.md
delete mode 100644 app/blog/[slug]/page.tsx
delete mode 100644 app/blog/layout.tsx
delete mode 100644 app/blog/page.tsx
delete mode 100644 app/changelog/layout.tsx
delete mode 100644 app/changelog/page.tsx
create mode 100644 components/GithubStart.tsx
delete mode 100644 components/changelog/change-group.tsx
delete mode 100644 components/changelog/floating-version.tsx
delete mode 100644 components/changelog/version-entry.tsx
delete mode 100644 components/changelog/version-tag.tsx
delete mode 100644 components/changelog/version-toc.tsx
create mode 100644 components/markdown/ReleaseMdx.tsx
create mode 100644 contents/docs/getting-started/changelog/index.mdx
create mode 100644 hooks/index.ts
create mode 100644 hooks/useActiveSection.ts
create mode 100644 hooks/useScrollPosition.ts
create mode 100644 lib/toc.ts
diff --git a/CHANGELOG.md b/CHANGELOG.md
deleted file mode 100644
index c340972..0000000
--- a/CHANGELOG.md
+++ /dev/null
@@ -1,373 +0,0 @@
-## [1.9.0] - 2025-05-19
-
-> New Keyboard component to show keyboard shortcut on docs page
-
-### Added
-
-- New Keyboard component with props show, type, children
-- Snippet keyboard component
-
-### Improved
-
-- Support custom content
-- Support platform type (mac or window)
-- Support automatic rendering of platform-specific key symbols
-- Rename lowercase to camelCase for markdown component
-
-## [1.8.5] - 2025-05-10
-
-> Add sponsor card on single docs page
-
-### Added
-
-- Expandables Leftbar
-- sponsor badges or ads
-- boolean show/hide `edit on github`
-- with the same code run anywhere (bun or nodejs)
-- add fronmatter (metadata) to playground editor
-
-### Improved
-
-- adjusment docu.json
-- adjustment navbar, footer and components
-
-### Fixed
-
-- bun compability rename .js to common js
-- cli manage packageManager on package.json
-- inconsistent design moved to better UI/UX
-- error handle render footer.social
-
-### Removed
-
-- remove confused and verbose cli on installer
-
-## [1.8.0] - 2025-03-01
-
-> Now looks more modern and clean which is a big change in layout and design
-
-### Added
-
-- Social footer
-- Toggle group
-- Site description {meta.description} in footer
-- Site title {meta.title} in footer
-
-### Improved
-
-- Header design changes
-- Footer design changes
-- New functions in theme provider
-- Object changes in docu.json
-
-### Fixed
-
-- Updates to path structure components
-- Groups to organize components
-
-## [1.7.0] - 2025-02-23
-
-> Remove the old function in the search dialog and replace it with a new and more optimal feature
-
-### Added
-
-- Up and down navigation : search dialog.tsx
-- Enter (return) to select : search dialog.tsx
-- Escape to close the dialog : search dialog.tsx
-
-### Improved
-
-- Maintenance for anchor components
-- Anchor.tsx adjustments for all elements that use it
-
-### Removed
-
-- Remove suboptimal search features
-
-## [1.6.0] - 2025-02-21
-
-> New Feature Card Groups with arrays for more Flexible Content
-
-### Added
-
-- Card Groups Components
-- Props : href to url link
-- Props : horizontal boolean
-
-### Improved
-
-- Card props styling
-- Compability for Cards components
-- {children} support for card content
-
-### Removed
-
-- remove unused props cards components
-
-## [1.5.0] - 2025-02-18
-
-> Minor Update - improved features and responsiveness on all devices
-
-### Added
-
-- New dialog footer on searchbox above @media 768px
-- Icon X for close dialog on searcbox as esc on medium screen
-
-### Improved
-
-- Responsive Leftbar components on large screen
-- Menu Trigger on medium screen
-- Responsive Navbar components on medium screen
-- Better UX for searchbox dialog
-- tooltips components can be written together with regular paragraphs
-
-### Fixed
-
-- Responsive issue
-- Compatibility for Bun
-- Changes postcss.config.js to .cjs for Bun
-- all CLI installer and updater not working
-- adjustments for package managers npm, pnpm, bun, yarn
-
-## [1.4.2] - 2025-02-16
-
-> Complex Content for Accordion Component props {children}
-
-### Added
-
-- New Props with {children} in accordion
-- Compatibility for markdown in accordion
-- Nested components inside an accordion
-- New icon on note components
-- add CLI npx @docubook/create@latest
-- add CLI npx @docubook/update@latest
-
-### Improved
-
-- Better UI design for accordion
-- Styling Note components on markdown
-- Change accordion output on playground
-- Change accordion output on snippet
-
-### Removed
-
-- Remove depcreated props on accordion
-- Remove CLI npx update_docu
-- Remove CLI npx create_docu
-
-## [1.4.0] - 2025-02-11
-
-> Floating Button Version with Dynamic Tag {version} on Changelog page
-
-### Added
-
-- New components / changelog floating-version.tsx
-- Button popover to open version-toc below @media 1024px
-- Dynamic tag by section ID #version
-- Dynamic url tag #version
-- Dynamic version indicator on floating version when scrolling section by ID
-
-### Improved
-
-- change icon version history
-- responsive version-toc
-- improvement components to changelog page
-
-## [1.3.8] - 2025-02-08
-
-> Responsive Table of Content
-
-### Added
-
-- Components terminal MagicUI
-- Components card Shadcn
-- New mob-toc for a better experience on mobile devices
-- New Components scroll to top button
-- Scroll to top :blog-post
-- Scroll to top :docs-post
-
-### Improved
-
-- lib/markdown for generated dynamic toc on markdown
-- Responsive Table of Content below @media 1024px
-- Improve docs page
-
-## [1.3.6] - 2025-02-01
-
-> Appears more modern editor for Docu Play
-
-
-
-### Added
-
-- Line Number for editor
-- editor.css
-
-### Improved
-
-- Better Design for Editor
-- Similar to Github Editor
-- Moved Handler Element (copy, download, reset and fullscreen) on Header
-
-## [1.3.5] - 2025-01-30
-
-> it's Easy to Write Markdown with Playground
-
-
-
-### Added
-
-- New Playground Page
-- New Playground Layout
-- Toolbar for Markdown Components
-- Fullscreen Mode to Focus Editing Your Content
-- Copy to Clipboard Your Content
-- Download Your Content as index.mdx
-- Reset Your Content without refresh the Browser
-- Only Large Screen for Better Experience
-
-## [1.3.1] - 2025-01-20
-
-> Snippet Feature to Easily Write Markdown and Call DocuBook Components
-
-
-
-### Added
-
-- New Feature Snippet for Markdown Components
-- Support Snippet for Visual Studio Code
-
-### Removed
-
-- remove props icon and props description for accordion components
-
-## [1.3.0] - 2024-12-31
-
-> Release Note Feature to Make it Easier to Write Changelogs
-
-### Added
-
-- New Release Note Feature
-- New Layout for Changelog page
-- New Changelog page
-- Add Release Note Component
-- Easily write release notes directly from the CHANGELOG.md file
-- TOC for versioning
-- Write with the markdown tag
-- Add lib / changelog.ts
-
-### Improved
-
-- Improvement Responsive feature image for Version Entry
-- Improvement Layout for changelog page
-- Improvement Padding on mobile devices
-- Only use containers of md size
-- Improvement syntax.css for ul>li classes
-
-### Fixed
-
-- Fix og:image not showing on Page.tsx
-- Fix text-indent on class li
-
-### Removed
-
-- Remove excessive padding
-- Remove Logo on Footer
-
-## [1.2.0] - 2024-12-22
-
-> New Accordion Component : Support content plain text, html and all markdown component
-
-### Added
-
-- add New Accordion
-
-### Improved
-
-- Props Improvement
-- Support Dynamic Content for Accordion
-
-## [1.1.0] - 2024-12-15
-
-> Minor Update : Easily manage set up with docu.json
-
-### Added
-
-- add docu.json file
-- add openGraph (title, description, image)
-- add Dynamic metadata
-- Generate metadata as openGraph
-- openGraph support for .mdx
-
-### Improved
-
-- routes-config from json
-- Frontmatter improvement
-- Edit the content of footer.tsx simply via the docu.json file
-- Edit the content of navbar.tsx simply via the docu.json file
-
-## [1.0.7] - 2024-12-14
-
-> Easily updates your DocuBook Version with CLI npx update_docu
-
-### Added
-
-- CLI npx update_docu (update features into docubook existing directory)
-- Playground (easily to written content)
-- New Button component
-- Navbar external link conditions
-- CLI npx create_docu
-
-### Improved
-
-- Searchbar Improvement
-- Navigation Improvement
-- Edit on Github Improvement
-
-### Removed
-- Remove CLI npx create-docu (on this version not usage dash `-`)
-
-## [1.0.6] - 2024-11-24
-
-> New Components, Fix and Improvement
-
-### Added
-
-- New Card component
-- New Tooltips component
-
-### Fixed
-
-- change root folder
-
-### Improved
-
-- logo on navbar & footer
-- easily change logo
-
-## [1.0.5] - 2024-11-16
-
-> Add New Features and Improvement for this version
-
-### Added
-
-- New Youtube component
-- edit this page - easily manage directory content via the github repo
-- support installation via cli commant npx create-docu
-
-### Improved
-
-- keyboard shortcut command + k or ctrl + k to open search dialog
-
-## [1.0.0] - 2024-11-10
-
-> Initial release of DocuBook to create interactive nested docs with MDX
-
-### Added
-
-- Initial release of DocuBook
-- Basic documentation structure
-- Markdown support with MDX
-- Responsive design
-- Search functionality
-- Dark mode support
diff --git a/README.md b/README.md
index fbec515..68f4d02 100644
--- a/README.md
+++ b/README.md
@@ -2,8 +2,6 @@
**DocuBook** is a documentation web project designed to provide a simple and user-friendly interface for accessing various types of documentation. This site is crafted for developers and teams who need quick access to references, guides, and essential documents.
-> **Note**: This application is a fork of [AriaDocs](https://github.com/nisabmohd/Aria-Docs), created by [Nisab Mohd](https://github.com/nisabmohd). DocuBook provides an alternative to the documentation solution found on [Mintlify](https://mintlify.com/), utilizing `.mdx` (Markdown + JSX) for content creation and management.
-
[](https://vercel.com/import/project?template=https://github.com/gitfromwildan/docubook)
diff --git a/app/blog/[slug]/page.tsx b/app/blog/[slug]/page.tsx
deleted file mode 100644
index 42951bc..0000000
--- a/app/blog/[slug]/page.tsx
+++ /dev/null
@@ -1,92 +0,0 @@
-import { Typography } from "@/components/typography";
-import { buttonVariants } from "@/components/ui/button";
-import { Author, getAllBlogStaticPaths, getBlogForSlug } from "@/lib/markdown";
-import { ArrowLeftIcon } from "lucide-react";
-import Link from "next/link";
-import { notFound } from "next/navigation";
-import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
-import { formatDate } from "@/lib/utils";
-import { ScrollToTop } from "@/components/scroll-to-top";
-
-type PageProps = {
- params: { slug: string };
-};
-
-export async function generateMetadata({ params: { slug } }: PageProps) {
- const res = await getBlogForSlug(slug);
- if (!res) return null;
- const { frontmatter } = res;
- return {
- title: frontmatter.title,
- description: frontmatter.description,
- };
-}
-
-export async function generateStaticParams() {
- const val = await getAllBlogStaticPaths();
- if (!val) return [];
- return val.map((it) => ({ slug: it }));
-}
-
-export default async function BlogPage({ params: { slug } }: PageProps) {
- const res = await getBlogForSlug(slug);
- if (!res) notFound();
- return (
-
-
-
Back to blog
-
-
-
- {formatDate(res.frontmatter.date)}
-
-
- {res.frontmatter.title}
-
-
-
-
- {res.content}
-
-
-
- );
-}
-
-function Authors({ authors }: { authors: Author[] }) {
- return (
-
- {authors.map((author) => {
- return (
-
-
-
-
- {author.username.slice(0, 2).toUpperCase()}
-
-
-
-
{author.username}
-
- @{author.handle}
-
-
-
- );
- })}
-
- );
-}
diff --git a/app/blog/layout.tsx b/app/blog/layout.tsx
deleted file mode 100644
index 6211155..0000000
--- a/app/blog/layout.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import { PropsWithChildren } from "react";
-
-export default function BlogLayout({ children }: PropsWithChildren) {
- return (
-
- {children}
-
- );
-}
diff --git a/app/blog/page.tsx b/app/blog/page.tsx
deleted file mode 100644
index 567db7c..0000000
--- a/app/blog/page.tsx
+++ /dev/null
@@ -1,103 +0,0 @@
-import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
-import { Author, BlogMdxFrontmatter, getAllBlogs } from "@/lib/markdown";
-import { formatDate2, stringToDate } from "@/lib/utils";
-import { getMetadata } from "@/app/layout";
-import Image from "next/image";
-import Link from "next/link";
-import { AuroraText } from "@/components/ui/aurora";
-import { ShineBorder } from "@/components/ui/shine-border";
-import docuConfig from "@/docu.json";
-
-export const metadata = getMetadata({
- title: "Blog",
- description: "Discover the latest updates, tutorials, and insights on DocuBook.",
-});
-const { meta } = docuConfig;
-export default async function BlogIndexPage() {
- const blogs = (await getAllBlogs()).sort(
- (a, b) => stringToDate(b.date).getTime() - stringToDate(a.date).getTime()
- );
- return (
-
-
-
# Stay Informed, Stay Ahead
-
- Blog Posts
-
-
- Explore updates, tips, and deep dives from the {meta.title}.
-
-
-
- {blogs.map((blog) => (
-
- ))}
-
-
- );
-}
-
-function BlogCard({
- date,
- title,
- description,
- slug,
- cover,
- authors,
-}: BlogMdxFrontmatter & { slug: string }) {
- return (
-
-
-
-
-
-
{title}
-
{description}
-
-
-
- Published on {formatDate2(date)}
-
-
-
-
- );
-}
-
-function AvatarGroup({ users, max = 4 }: { users: Author[]; max?: number }) {
- const displayUsers = users.slice(0, max);
- const remainingUsers = Math.max(users.length - max, 0);
-
- return (
-
- {displayUsers.map((user, index) => (
-
-
-
- {user.username.slice(0, 2).toUpperCase()}
-
-
- ))}
- {remainingUsers > 0 && (
-
- +{remainingUsers}
-
- )}
-
- );
-}
diff --git a/app/changelog/layout.tsx b/app/changelog/layout.tsx
deleted file mode 100644
index b77f34a..0000000
--- a/app/changelog/layout.tsx
+++ /dev/null
@@ -1,11 +0,0 @@
-export default function ChangelogLayout({
- children,
-}: {
- children: React.ReactNode;
-}) {
- return (
-
- {children}
-
- );
-}
\ No newline at end of file
diff --git a/app/changelog/page.tsx b/app/changelog/page.tsx
deleted file mode 100644
index 0caacf0..0000000
--- a/app/changelog/page.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import { Suspense } from "react";
-import { getChangelogEntries } from "@/lib/changelog";
-import { VersionEntry } from "@/components/changelog/version-entry";
-import { VersionToc } from "@/components/changelog/version-toc";
-import { FloatingVersionToc } from "@/components/changelog/floating-version";
-
-export default async function ChangelogPage() {
- const entries = await getChangelogEntries();
-
- return (
-
-
}>
-
({ version, date }))}
- />
-
-
-
-
-
-
- {entries.map((entry, index) => (
-
- ))}
-
-
-
- {/* Floating TOC for smaller screens */}
- {entries.length > 0 && (
- ({ version, date }))}
- />
- )}
-
- );
-}
diff --git a/app/docs/[[...slug]]/page.tsx b/app/docs/[[...slug]]/page.tsx
index 7022893..23a5a4e 100644
--- a/app/docs/[[...slug]]/page.tsx
+++ b/app/docs/[[...slug]]/page.tsx
@@ -8,7 +8,6 @@ import EditThisPage from "@/components/edit-on-github";
import { formatDate2 } from "@/lib/utils";
import docuConfig from "@/docu.json";
import MobToc from "@/components/mob-toc";
-import { ScrollToTop } from "@/components/scroll-to-top";
const { meta } = docuConfig;
@@ -78,11 +77,9 @@ export default async function DocsPage({ params: { slug = [] } }: PageProps) {
return (
-
+
+
-
-
-
{title}
{description}
@@ -101,7 +98,6 @@ export default async function DocsPage({ params: { slug = [] } }: PageProps) {
-
diff --git a/app/docs/layout.tsx b/app/docs/layout.tsx
index aa877c2..ec2544c 100644
--- a/app/docs/layout.tsx
+++ b/app/docs/layout.tsx
@@ -1,5 +1,4 @@
import { Leftbar } from "@/components/leftbar";
-import { MDXProviderWrapper } from "@/components/markdown/mdx-provider";
export default function DocsLayout({
children,
@@ -9,10 +8,8 @@ export default function DocsLayout({
return (
-
-
- {children}
-
+
+ {children}
);
diff --git a/app/page.tsx b/app/page.tsx
index ce3726d..b2c4f84 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -15,7 +15,7 @@ export default function Home() {
return (
@@ -25,7 +25,7 @@ export default function Home() {
)}
>
- 🚀 New Version - Release v1.9.0
+ 🚀 New Version - Release v1.11.0
diff --git a/components/GithubStart.tsx b/components/GithubStart.tsx
new file mode 100644
index 0000000..b6e9c80
--- /dev/null
+++ b/components/GithubStart.tsx
@@ -0,0 +1,44 @@
+'use client';
+
+import React, { useEffect, useState } from 'react';
+import Link from 'next/link';
+
+const GitHubStarButton: React.FC = () => {
+ const [stars, setStars] = useState
(null);
+
+ useEffect(() => {
+ fetch('https://api.github.com/repos/gitfromwildan/docubook')
+ .then((res) => res.json())
+ .then((data) => {
+ if (data.stargazers_count !== undefined) {
+ setStars(data.stargazers_count);
+ }
+ })
+ .catch((error) => console.error('Failed to fetch stars:', error));
+ }, []);
+
+ const formatStars = (count: number) =>
+ count >= 1000 ? `${(count / 1000).toFixed(1)}K` : `${count}`;
+
+ return (
+
+
+ {stars !== null ? formatStars(stars) : '...'}
+
+ );
+};
+
+export default GitHubStarButton;
diff --git a/components/changelog/change-group.tsx b/components/changelog/change-group.tsx
deleted file mode 100644
index d6548c8..0000000
--- a/components/changelog/change-group.tsx
+++ /dev/null
@@ -1,45 +0,0 @@
-"use client";
-
-import { cn } from "@/lib/utils";
-import { Badge } from "@/components/ui/badge";
-
-type ChangeType = "Added" | "Improved" | "Fixed" | "Deprecated" | "Removed";
-
-interface ChangeGroupProps {
- type: ChangeType;
- changes: string[];
- expanded: boolean;
-}
-
-const typeColors: Record = {
- Added: "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400",
- Improved: "bg-blue-500/10 text-blue-600 dark:text-blue-400",
- Fixed: "bg-amber-500/10 text-amber-600 dark:text-amber-400",
- Deprecated: "bg-red-500/10 text-red-600 dark:text-red-400",
- Removed: "bg-slate-500/10 text-slate-600 dark:text-slate-400"
-};
-
-export function ChangeGroup({ type, changes, expanded }: ChangeGroupProps) {
- const visibleChanges = expanded ? changes : changes.slice(0, 5);
- const hasMore = changes.length > 5;
-
- return (
-
-
- {type}
-
-
- {visibleChanges.map((change, i) => (
- -
- {change}
-
- ))}
- {!expanded && hasMore && (
- -
- +{changes.length - 5} more improvements
-
- )}
-
-
- );
-}
\ No newline at end of file
diff --git a/components/changelog/floating-version.tsx b/components/changelog/floating-version.tsx
deleted file mode 100644
index 4175564..0000000
--- a/components/changelog/floating-version.tsx
+++ /dev/null
@@ -1,86 +0,0 @@
-"use client";
-
-import { useState, useEffect } from "react";
-import { History } from "lucide-react";
-import { cn } from "@/lib/utils";
-import { Button } from "@/components/ui/button";
-import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
-import { ScrollArea } from "@/components/ui/scroll-area";
-import { Separator } from "@/components/ui/separator";
-
-interface FloatingVersionTocProps {
- versions: { version: string; date: string }[];
-}
-
-export function FloatingVersionToc({ versions }: FloatingVersionTocProps) {
- const [open, setOpen] = useState(false);
- const [activeVersion, setActiveVersion] = useState(versions[0]?.version || "");
-
- useEffect(() => {
- const handleIntersection = (entries: IntersectionObserverEntry[]) => {
- entries.forEach((entry) => {
- if (entry.isIntersecting) {
- setActiveVersion(entry.target.id.replace("version-", ""));
- }
- });
- };
-
- const observer = new IntersectionObserver(handleIntersection, {
- root: null,
- rootMargin: "-64px 0px -50% 0px",
- threshold: 0.25,
- });
-
- versions.forEach(({ version }) => {
- const section = document.getElementById(`version-${version}`);
- if (section) observer.observe(section);
- });
-
- return () => observer.disconnect();
- }, [versions]);
-
- const handleScrollToVersion = (version: string) => {
- const element = document.getElementById(`version-${version}`);
- if (element) {
- setTimeout(() => {
- element.scrollIntoView({ behavior: "smooth", block: "start" });
- }, 100);
- setActiveVersion(version);
- setOpen(false);
- }
- };
-
- return (
-
-
-
-
-
-
-
- Version History
-
- {versions.map(({ version }) => (
- -
-
-
-
- ))}
-
-
-
-
-
- );
-}
diff --git a/components/changelog/version-entry.tsx b/components/changelog/version-entry.tsx
deleted file mode 100644
index 1b89242..0000000
--- a/components/changelog/version-entry.tsx
+++ /dev/null
@@ -1,113 +0,0 @@
-"use client";
-
-import { useState } from "react";
-import { VersionTag } from "./version-tag";
-import { ChangeGroup } from "./change-group";
-import { formatDate2 } from "@/lib/utils";
-import { Button } from "@/components/ui/button";
-import Image from "next/image";
-import { ChevronDownIcon, ChevronUpIcon } from "lucide-react";
-import { Separator } from "@/components/ui/separator";
-
-interface VersionEntryProps {
- version: string;
- date: string;
- description?: string;
- image?: string;
- changes: {
- Added?: string[];
- Improved?: string[];
- Fixed?: string[];
- Deprecated?: string[];
- Removed?: string[];
- };
- isLast?: boolean;
-}
-
-export function VersionEntry({
- version,
- date,
- description,
- image,
- changes,
- isLast
-}: VersionEntryProps) {
- const [expanded, setExpanded] = useState(false);
-
- return (
-
-
- {/* Version header */}
-
-
-
-
-
-
- {description && (
-
{description}
- )}
-
- {image && (
-
-
-
- )}
-
-
- {/* Changes */}
-
- {Object.entries(changes).map(([type, items]) => (
- items && items.length > 0 && (
-
- )
- ))}
-
-
- {/* Show more/less button */}
- {Object.values(changes).some(items => items && items.length > 5) && (
-
- )}
-
-
- {/* Version divider */}
- {!isLast && (
-
-
-
- )}
-
- );
-}
diff --git a/components/changelog/version-tag.tsx b/components/changelog/version-tag.tsx
deleted file mode 100644
index d228b42..0000000
--- a/components/changelog/version-tag.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-"use client";
-
-import { cn } from "@/lib/utils";
-
-export function VersionTag({ version }: { version: string }) {
- return (
-
- v{version}
-
- );
-}
\ No newline at end of file
diff --git a/components/changelog/version-toc.tsx b/components/changelog/version-toc.tsx
deleted file mode 100644
index c32d2ca..0000000
--- a/components/changelog/version-toc.tsx
+++ /dev/null
@@ -1,111 +0,0 @@
-"use client";
-
-import { useEffect, useState } from "react";
-import { cn, formatDate2 } from "@/lib/utils";
-import { History, PanelLeftOpen, PanelLeftClose } from "lucide-react";
-import { ScrollArea } from "@/components/ui/scroll-area";
-import { Button } from "@/components/ui/button";
-
-interface VersionTocProps {
- versions: Array<{
- version: string;
- date: string;
- }>;
-}
-
-export function VersionToc({ versions }: VersionTocProps) {
- const [activeId, setActiveId] = useState(null);
- const [collapsed, setCollapsed] = useState(false);
-
- useEffect(() => {
- const hash = window.location.hash.slice(1);
- if (hash) {
- setActiveId(hash);
- }
-
- const observer = new IntersectionObserver(
- (entries) => {
- entries.forEach((entry) => {
- if (entry.isIntersecting) {
- const id = entry.target.id;
- setActiveId(id);
- window.history.pushState(null, "", `#${id}`);
- }
- });
- },
- {
- threshold: 0.2,
- rootMargin: "-20% 0px -60% 0px",
- }
- );
-
- versions.forEach(({ version }) => {
- const element = document.getElementById(`v${version}`);
- if (element) observer.observe(element);
- });
-
- return () => observer.disconnect();
- }, [versions]);
-
- return (
-
- );
-}
diff --git a/components/docs-breadcrumb.tsx b/components/docs-breadcrumb.tsx
index 1d1167c..8fad85a 100644
--- a/components/docs-breadcrumb.tsx
+++ b/components/docs-breadcrumb.tsx
@@ -10,7 +10,7 @@ import { Fragment } from "react";
export default function DocsBreadcrumb({ paths }: { paths: string[] }) {
return (
-
+
diff --git a/components/leftbar.tsx b/components/leftbar.tsx
index 16d8f3a..d0ebbc9 100644
--- a/components/leftbar.tsx
+++ b/components/leftbar.tsx
@@ -11,37 +11,49 @@ import { Logo, NavMenu } from "@/components/navbar";
import { Button } from "@/components/ui/button";
import { AlignLeftIcon, PanelLeftClose, PanelLeftOpen } from "lucide-react";
import { FooterButtons } from "@/components/footer";
-import { DialogTitle } from "@/components/ui/dialog";
+import { DialogTitle, DialogDescription } from "@/components/ui/dialog";
import { ScrollArea } from "@/components/ui/scroll-area";
import DocsMenu from "@/components/docs-menu";
import { ModeToggle } from "@/components/theme-toggle";
+// Toggle Button Component
+export function ToggleButton({
+ collapsed,
+ onToggle
+}: {
+ collapsed: boolean,
+ onToggle: () => void
+}) {
+ return (
+
+
+
+ )
+}
+
export function Leftbar() {
const [collapsed, setCollapsed] = useState(false);
+ const toggleCollapse = () => setCollapsed(prev => !prev);
return (
@@ -57,7 +69,10 @@ export function SheetLeftbar() {
- Menu
+ Navigation Menu
+
+ Main navigation menu with links to different sections
+
diff --git a/components/markdown/ReleaseMdx.tsx b/components/markdown/ReleaseMdx.tsx
new file mode 100644
index 0000000..be68292
--- /dev/null
+++ b/components/markdown/ReleaseMdx.tsx
@@ -0,0 +1,107 @@
+import React, { PropsWithChildren } from 'react';
+import { cn } from '@/lib/utils';
+import { PlusCircle, Wrench, Zap, AlertTriangle, XCircle } from 'lucide-react';
+
+interface ReleaseProps extends PropsWithChildren {
+ version: string;
+ title: string;
+ date?: string;
+}
+
+function Release({ version, title, date, children }: ReleaseProps) {
+
+ return (
+
+
+
+
+ v{version}
+
+ {date && (
+
+ {new Date(date).toLocaleDateString('en-US', {
+ year: 'numeric',
+ month: 'long',
+ day: 'numeric'
+ })}
+
+ )}
+
+
+ {title}
+
+
+
+ {children}
+
+
+ );
+}
+
+interface ChangesProps extends PropsWithChildren {
+ type: 'added' | 'fixed' | 'improved' | 'deprecated' | 'removed';
+}
+
+const typeConfig = {
+ added: {
+ label: 'Added',
+ className: 'bg-green-100 dark:bg-green-900/50 text-green-700 dark:text-green-300',
+ icon: PlusCircle,
+ },
+ fixed: {
+ label: 'Fixed',
+ className: 'bg-yellow-100 dark:bg-yellow-900/50 text-yellow-700 dark:text-yellow-300',
+ icon: Wrench,
+ },
+ improved: {
+ label: 'Improved',
+ className: 'bg-cyan-100 dark:bg-cyan-900/50 text-cyan-700 dark:text-cyan-300',
+ icon: Zap,
+ },
+ deprecated: {
+ label: 'Deprecated',
+ className: 'bg-orange-100 dark:bg-orange-900/50 text-orange-700 dark:text-orange-300',
+ icon: AlertTriangle,
+ },
+ removed: {
+ label: 'Removed',
+ className: 'bg-pink-100 dark:bg-pink-900/50 text-pink-700 dark:text-pink-300',
+ icon: XCircle,
+ },
+} as const;
+
+function Changes({ type, children }: ChangesProps) {
+ const config = typeConfig[type] || typeConfig.added;
+
+ return (
+
+
+
+ {React.Children.map(children, (child, index) => {
+ // Jika teks dimulai dengan - atau *, hapus karakter tersebut
+ const processedChild = typeof child === 'string'
+ ? child.trim().replace(/^[-*]\s+/, '')
+ : child;
+
+ return (
+ -
+ {processedChild}
+
+ );
+ })}
+
+
+ );
+}
+
+export { Release, Changes };
+
+export default {
+ Release,
+ Changes
+};
diff --git a/components/markdown/mdx-provider.tsx b/components/markdown/mdx-provider.tsx
index 551e60f..8265b8f 100644
--- a/components/markdown/mdx-provider.tsx
+++ b/components/markdown/mdx-provider.tsx
@@ -1,17 +1,29 @@
'use client';
-import { MDXProvider } from '@mdx-js/react';
-import { components } from './mdx-components';
+import { MDXRemote, MDXRemoteProps } from 'next-mdx-remote/rsc';
+import { Kbd } from './KeyboardMdx';
-// Create a properly typed components object
-const typedComponents = {
- ...components,
- // Add any default HTML elements you want to override
- // or keep their default behavior
- kbd: components.kbd as React.ComponentType>,
- Kbd: components.Kbd as React.ComponentType & { type?: 'window' | 'mac' }>,
+// Define components mapping
+const components = {
+ // Keyboard components
+ Kbd: Kbd as React.ComponentType & { type?: 'window' | 'mac' }>,
+ kbd: Kbd as React.ComponentType & { type?: 'window' | 'mac' }>,
};
-export function MDXProviderWrapper({ children }: { children: React.ReactNode }) {
- return {children};
+interface MDXProviderWrapperProps {
+ source: string;
+}
+
+export function MDXProviderWrapper({ source }: MDXProviderWrapperProps) {
+ return (
+
+
+
+ );
}
diff --git a/components/mob-toc.tsx b/components/mob-toc.tsx
index 7b81480..052affd 100644
--- a/components/mob-toc.tsx
+++ b/components/mob-toc.tsx
@@ -1,38 +1,128 @@
"use client";
-import { ListIcon } from "lucide-react";
+import { List, ChevronDown, ChevronUp } from "lucide-react";
import TocObserver from "./toc-observer";
-import {
- Accordion,
- AccordionContent,
- AccordionItem,
- AccordionTrigger,
-} from "@/components/ui/accordion";
+import * as React from "react";
+import { useRef, useMemo } from "react";
+import { usePathname } from "next/navigation";
+import { Button } from "./ui/button";
+import { motion, AnimatePresence } from "framer-motion";
+import { useScrollPosition, useActiveSection } from "@/hooks";
+import { TocItem } from "@/lib/toc";
interface MobTocProps {
- tocs: {
- level: number;
- text: string;
- href: string;
- }[];
+ tocs: TocItem[];
}
+const useClickOutside = (ref: React.RefObject, callback: () => void) => {
+ const handleClick = (e: MouseEvent) => {
+ if (ref.current && !ref.current.contains(e.target as Node)) {
+ callback();
+ }
+ };
+
+ React.useEffect(() => {
+ document.addEventListener('mousedown', handleClick);
+ return () => {
+ document.removeEventListener('mousedown', handleClick);
+ };
+ }, [ref, callback]);
+};
+
export default function MobToc({ tocs }: MobTocProps) {
+ const pathname = usePathname();
+ const [isExpanded, setIsExpanded] = React.useState(false);
+ const tocRef = useRef(null);
+ const contentRef = useRef(null);
+
+ // Use custom hooks
+ const { activeId, setActiveId } = useActiveSection(tocs);
+
+ // Only show on /docs pages
+ const isDocsPage = useMemo(() => pathname?.startsWith('/docs'), [pathname]);
+
+ // Toggle expanded state
+ const toggleExpanded = React.useCallback((e: React.MouseEvent) => {
+ e.stopPropagation();
+ setIsExpanded(prev => !prev);
+ }, []);
+
+ // Close TOC when clicking outside
+ useClickOutside(tocRef, () => {
+ if (isExpanded) {
+ setIsExpanded(false);
+ }
+ });
+
+ // Handle body overflow when TOC is expanded
+ React.useEffect(() => {
+ if (isExpanded) {
+ document.body.style.overflow = 'hidden';
+ } else {
+ document.body.style.overflow = '';
+ }
+
+ return () => {
+ document.body.style.overflow = '';
+ };
+ }, [isExpanded]);
+
+ // Don't render anything if not on docs page or no TOC items
+ if (!isDocsPage || !tocs?.length) return null;
+
+ const chevronIcon = isExpanded ? (
+
+ ) : (
+
+ );
+
return (
-
-
-
-
-
-
-
On this page
+
+
+
+
+
+
+
+ {isExpanded && (
+
+
+
+ )}
+
-
-
-
-
-
-
-
+
+
+
);
}
diff --git a/components/navbar.tsx b/components/navbar.tsx
index a86a917..cc00b89 100644
--- a/components/navbar.tsx
+++ b/components/navbar.tsx
@@ -34,14 +34,22 @@ export function Navbar() {
}
export function Logo() {
- const { navbar } = docuConfig; // Extract navbar from JSON
+ const { navbar } = docuConfig; // Extract navbar from JSON
- return (
-
-
- {navbar.logoText}
-
- );
+ return (
+
+
+
+
+ {navbar.logoText}
+
+ );
}
export function NavMenu({ isSheet = false }) {
diff --git a/components/scroll-to-top.tsx b/components/scroll-to-top.tsx
index 2ebbfb1..e072451 100644
--- a/components/scroll-to-top.tsx
+++ b/components/scroll-to-top.tsx
@@ -1,52 +1,86 @@
"use client";
import { ArrowUpIcon } from "lucide-react";
-import { useEffect, useState } from "react";
-import { Button } from "@/components/ui/button";
+import { useEffect, useState, useCallback } from "react";
+import Link from "next/link";
import { cn } from "@/lib/utils";
-export function ScrollToTop() {
- const [show, setShow] = useState(false);
+interface ScrollToTopProps {
+ className?: string;
+ showIcon?: boolean;
+ offset?: number; // Optional offset in pixels from the trigger point
+}
+
+export function ScrollToTop({
+ className,
+ showIcon = true,
+ offset = 0
+}: ScrollToTopProps) {
+ const [isVisible, setIsVisible] = useState(false);
+
+ const checkScroll = useCallback(() => {
+ // Calculate 50% of viewport height
+ const halfViewportHeight = window.innerHeight * 0.5;
+ // Check if scrolled past half viewport height (plus any offset)
+ const scrolledPastHalfViewport = window.scrollY > (halfViewportHeight + offset);
+
+ // Only update state if it changes to prevent unnecessary re-renders
+ if (scrolledPastHalfViewport !== isVisible) {
+ setIsVisible(scrolledPastHalfViewport);
+ }
+ }, [isVisible, offset]);
useEffect(() => {
- const handleScroll = () => {
- // Check if user has scrolled to bottom
- const scrolledToBottom =
- window.innerHeight + window.scrollY >= document.documentElement.scrollHeight - 100;
+ // Initial check
+ checkScroll();
- if (scrolledToBottom) {
- setShow(true);
- } else {
- setShow(false);
- }
+ // Set up scroll listener with debounce for better performance
+ let timeoutId: NodeJS.Timeout;
+ const handleScroll = () => {
+ if (timeoutId) clearTimeout(timeoutId);
+ timeoutId = setTimeout(checkScroll, 100);
};
- window.addEventListener("scroll", handleScroll);
- return () => window.removeEventListener("scroll", handleScroll);
+ window.addEventListener('scroll', handleScroll, { passive: true });
+
+ // Cleanup
+ return () => {
+ window.removeEventListener('scroll', handleScroll);
+ if (timeoutId) clearTimeout(timeoutId);
+ };
+ }, [checkScroll]);
+
+ const scrollToTop = useCallback((e: React.MouseEvent) => {
+ e.preventDefault();
+ window.scrollTo({
+ top: 0,
+ behavior: 'smooth'
+ });
}, []);
- const scrollToTop = () => {
- window.scrollTo({ top: 0, behavior: "smooth" });
- };
+ if (!isVisible) return null;
return (
-
+
+ {showIcon &&
}
+
Scroll to Top
+
);
}
diff --git a/components/search.tsx b/components/search.tsx
index 9ee3757..4860c45 100644
--- a/components/search.tsx
+++ b/components/search.tsx
@@ -12,6 +12,7 @@ import {
DialogTrigger,
DialogClose,
DialogTitle,
+ DialogDescription,
} from "@/components/ui/dialog";
import Anchor from "./anchor";
import { advanceSearch, cn } from "@/lib/utils";
@@ -110,16 +111,20 @@ export default function Search() {
- Search
+ Search Documentation
+
+
+ Search through the documentation
+
setSearchedInput(e.target.value)}
placeholder="Type something to search..."
autoFocus
- className="h-14 px-6 bg-transparent border-b text-[14px] outline-none"
+ className="h-14 px-6 bg-transparent border-b text-[14px] outline-none w-full"
+ aria-label="Search documentation"
/>
-
{filteredResults.length == 0 && searchedInput && (
No results found for{" "}
@@ -149,11 +154,20 @@ export default function Search() {
>
1 && "border-l pl-4"
)}
>
-
{item.title}
+
+
+ {item.title}
+
+ {isActive && (
+
+ Return
+
+
+ )}
diff --git a/components/toc-observer.tsx b/components/toc-observer.tsx
index 0709a81..2c274d0 100644
--- a/components/toc-observer.tsx
+++ b/components/toc-observer.tsx
@@ -3,26 +3,62 @@
import { getDocsTocs } from "@/lib/markdown";
import clsx from "clsx";
import Link from "next/link";
-import { useState, useRef, useEffect } from "react";
+import { useState, useRef, useEffect, useCallback } from "react";
+import { motion } from "framer-motion";
+import { ScrollToTop } from "./scroll-to-top";
+import { TocItem } from "@/lib/toc";
-type Props = { data: Awaited> };
+interface TocObserverProps {
+ data: TocItem[];
+ activeId?: string | null;
+ onActiveIdChange?: (id: string | null) => void;
+}
-export default function TocObserver({ data }: Props) {
- const [activeId, setActiveId] = useState(null);
+export default function TocObserver({
+ data,
+ activeId: externalActiveId,
+ onActiveIdChange
+}: TocObserverProps) {
+ const [internalActiveId, setInternalActiveId] = useState(null);
const observer = useRef(null);
+ const [clickedId, setClickedId] = useState(null);
+ const itemRefs = useRef