version 1.12.0 :add File Tree

This commit is contained in:
Wildan Nursahidan
2025-05-28 11:21:37 +07:00
parent 561039ae4d
commit 253166a6ee
12 changed files with 454 additions and 8714 deletions

86
.gitignore vendored
View File

@@ -1,39 +1,99 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
# Dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz
.pnp.cjs
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
# testing
# Testing
/coverage
/.nyc_output
# next.js
# Next.js
/.next/
/out/
/.swc
.next/
out/
# production
# Production
/build
# misc
.DS_Store
*.pem
# Environment variables
.env*.local
.env
.env.development
.env.test
.env.production
# debug
# Debug logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# local env files
.env*.local
# Editor directories and files
.idea
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# vercel
# System files
.DS_Store
Thumbs.db
# Vercel
.vercel
# typescript
# TypeScript
*.tsbuildinfo
next-env.d.ts
# bun
# Package managers
package-lock.json
yarn.lock
bun.lock
pnpm-lock.yaml
# Build outputs
.next
out
# Local development
.cache
.temp
.tmp
# Testing
/coverage
/__tests__/__snapshots__/
# Logs
logs
*.log
# Misc
*.pem
*.p12
*.key
*.crt
*.cer
*.p7b
*.p7c
*.p7s
*.pfx
*.der
*.sst
*.stl

53
.vscode/file-tree.code-snippets vendored Normal file
View File

@@ -0,0 +1,53 @@
{
"File Tree Component": {
"prefix": "filetree",
"body": [
"<Files>",
" <Folder name=\"${1:folder-name}\">",
" <File name=\"${2:file-name}\" />",
" <Folder name=\"${3:subfolder}\">",
" <File name=\"${4:file.tsx}\" />",
" </Folder>\n$0",
" </Folder>",
"</Files>"
],
"description": "DocuBook File Tree component with nested structure"
},
"File Tree Minimal": {
"prefix": "filetree-mini",
"body": [
"<Files>\n <Folder name=\"${1:folder}\">\n <File name=\"${2:file}\" />\n </Folder>\n</Files>$0"
],
"description": "Minimal DocuBook File Tree component"
},
"File Tree Complex": {
"prefix": "filetree-complex",
"body": [
"<Files>",
" <Folder name=\"${1:project-root}\">",
" <File name=\"package.json\" />",
" <File name=\"tsconfig.json\" />",
" <Folder name=\"src\">",
" <File name=\"index.ts\" />",
" <Folder name=\"components\">",
" <File name=\"${2:Component}.tsx\" />",
" <File name=\"${3:Component}.types.ts\" />",
" <File name=\"index.ts\" />",
" </Folder>\n$0",
" </Folder>",
" </Folder>",
"</Files>"
],
"description": "Complex DocuBook File Tree with common project structure"
},
"File Tree Folder": {
"prefix": "folder",
"body": "<Folder name=\"${1:folder-name}\">\n $0\n</Folder>",
"description": "DocuBook Folder component for file trees"
},
"File Tree File": {
"prefix": "file",
"body": "<File name=\"${1:file-name}\" />$0",
"description": "DocuBook File component for file trees"
}
}

49
.vscode/release.code-snippets vendored Normal file
View File

@@ -0,0 +1,49 @@
{
"Release Note Component": {
"prefix": "release",
"body": [
"<Release version=\"$1\" date=\"${2:$CURRENT_YEAR-${CURRENT_MONTH}-${CURRENT_DATE}}\" title=\"$3\">",
" <Changes type=\"added\">",
" - $4",
" </Changes>",
"",
" <Changes type=\"fixed\">",
" - $5",
" </Changes>",
"",
" <Changes type=\"improved\">",
" - $6",
" </Changes>",
"",
" <Changes type=\"deprecated\">",
" - $7",
" </Changes>",
"",
" <Changes type=\"removed\">",
" - $8",
" </Changes>",
"</Release>"
],
"description": "DocuBook Release Note component with all change types"
},
"Release Note Simple": {
"prefix": "release-simple",
"body": [
"<Release version=\"$1\" date=\"${2:$CURRENT_YEAR-${CURRENT_MONTH}-${CURRENT_DATE}}\" title=\"$3\">",
" <Changes type=\"$4\">",
" - $5",
" </Changes>\n$0",
"</Release>"
],
"description": "Simple DocuBook Release Note component with one change type"
},
"Changes Only": {
"prefix": "changes",
"body": [
"<Changes type=\"$1\">",
" - $2",
"</Changes>"
],
"description": "DocuBook Changes component for individual change items"
}
}

View File

@@ -3,7 +3,7 @@
**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.
[![Deploy with
Vercel](https://vercel.com/button)](https://vercel.com/import/project?template=https://github.com/gitfromwildan/docubook)
Vercel](https://vercel.com/button)](https://vercel.com/import/project?template=https://github.com/DocuBook/docubook)
## Features

View File

@@ -25,7 +25,7 @@ export default function Home() {
)}
>
<AnimatedShinyText className="inline-flex items-center justify-center px-4 py-1 transition ease-out hover:text-neutral-100 hover:duration-300 hover:dark:text-neutral-200">
<span>🚀 New Version - Release v1.11.0</span>
<span>🚀 New Version - Release v1.12.0</span>
<ArrowRightIcon className="ml-1 size-3 transition-transform duration-300 ease-in-out group-hover:translate-x-0.5" />
</AnimatedShinyText>
</div>

View File

@@ -0,0 +1,119 @@
'use client';
import React, { useState, ReactNode, Children, isValidElement, cloneElement } from 'react';
import { ChevronRight, ChevronDown, File as FileIcon, Folder as FolderIcon, FolderOpen } from 'lucide-react';
interface FileTreeProps {
children: ReactNode;
defaultOpen?: boolean;
}
interface FileProps {
name: string;
children?: ReactNode;
}
const FileComponent = ({ name }: FileProps) => {
const [isHovered, setIsHovered] = useState(false);
return (
<div
className={`
flex items-center gap-2 py-1.5 pl-7 pr-3 text-sm
transition-all duration-200 ease-in-out rounded-md
${isHovered
? 'bg-blue-50 dark:bg-blue-900/30'
: 'hover:bg-gray-50 dark:hover:bg-gray-800/50'}
`}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
<FileIcon className={`h-3.5 w-3.5 transition-colors ${isHovered ? 'text-blue-500' : 'text-gray-400 dark:text-gray-500'}`} />
<span className="font-mono text-sm text-gray-700 dark:text-gray-300">{name}</span>
{isHovered && (
<span className="ml-auto text-xs text-gray-400 dark:text-gray-500">
{name.split('.').pop()?.toUpperCase()}
</span>
)}
</div>
);
};
const FolderComponent = ({ name, children }: FileProps) => {
const [isOpen, setIsOpen] = useState(true); // Set to true by default
const [isHovered, setIsHovered] = useState(false);
const hasChildren = React.Children.count(children) > 0;
return (
<div className="relative">
<div
className={`
flex items-center gap-2 py-1.5 pl-4 pr-3 rounded-md cursor-pointer
transition-all duration-200 ease-in-out
${isHovered ? 'bg-gray-50 dark:bg-gray-800/50' : ''}
${isOpen ? 'text-blue-600 dark:text-blue-400' : 'text-gray-800 dark:text-gray-200'}
`}
onClick={() => setIsOpen(!isOpen)}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
{hasChildren ? (
<ChevronRight
className={`h-3.5 w-3.5 transition-transform duration-200 ${isOpen ? 'transform rotate-90' : ''}`}
/>
) : (
<div className="w-3.5" />
)}
{isOpen ? (
<FolderOpen className="h-4 w-4 text-blue-500 dark:text-blue-400" />
) : (
<FolderIcon className="h-4 w-4 text-blue-400 dark:text-blue-500" />
)}
<span className="font-medium">{name}</span>
</div>
{isOpen && hasChildren && (
<div className="ml-5 border-l-2 border-gray-100 dark:border-gray-700/50 pl-2">
{children}
</div>
)}
</div>
);
};
export const Files = ({ children }: { children: ReactNode }) => {
return (
<div className="
rounded-xl border border-gray-100 dark:border-gray-700/50
bg-white/50 dark:bg-gray-800/30 backdrop-blur-sm
shadow-sm overflow-hidden
transition-all duration-200
hover:shadow-md hover:border-gray-200 dark:hover:border-gray-600/50
">
<div className="p-2">
{Children.map(children, (child, index) => {
if (isValidElement(child)) {
return cloneElement(child, { key: index });
}
return null;
})}
</div>
</div>
);
};
export const Folder = ({ name, children }: FileProps) => {
return <FolderComponent name={name}>{children}</FolderComponent>;
};
export const File = ({ name }: FileProps) => {
return <FileComponent name={name} />;
};
// MDX Components
export const FileTreeMdx = {
Files,
File,
Folder,
};
export default FileTreeMdx;

View File

@@ -8,6 +8,44 @@ date: 24-05-2025
> This changelog contains a list of all the changes made to the DocuBook template. It will be updated with each new release and will include information about new features, bug fixes, and other improvements.
<div className="sr-only">
### v 1.12.0
</div>
<Release version="1.12.0" date="2025-05-28" title="New File Tree Component and enhancements for existing components or features">
<Changes type="added">
- New FileTree component for displaying hierarchical file structures
- Support for nested folders and files with expand/collapse functionality
- Hover effects showing file extensions
- Dark mode support with modern styling
- Keyboard navigation and accessibility features
- add toc-observer data attribute to detect toc section
- cli to copy from path npm registry
</Changes>
<Changes type="improved">
- search dialog hover effect return key
- search icon showing on mobile screens
</Changes>
<Changes type="fixed">
- fix search dialog on mobile screens
- fix release note component eslint error on mdx when rendering
- fix mob-toc callback function
- fix toc height issue when toc section is longer than screen height
</Changes>
<Changes type="removed">
- remove prompts depedencies
- remove degit depedencies
- remove prompts functions
- remove degit functions
- remove prompts and degit from package.json
- remove clone repository using git
</Changes>
</Release>
<Note type="note" title="Note">
on this version `1.12.0`, we remove clone repository using git and replace it with cli to copy from path npm registry
</Note>
<div className="sr-only">
### v 1.11.0
</div>

View File

@@ -0,0 +1,109 @@
---
title: File Tree Component
description: A customizable file tree component for displaying hierarchical file structures in your documentation.
date: 28-05-2025
---
The File Tree component allows you to display hierarchical file structures in your documentation with collapsible folders and files.
## Basic Usage
```
<Files>
<Folder name="src">
<File name="App.tsx" />
<File name="index.tsx" />
<Folder name="components">
<File name="Button.tsx" />
<File name="Card.tsx" />
</Folder>
<Folder name="pages">
<File name="Home.tsx" />
<File name="About.tsx" />
</Folder>
</Folder>
</Files>
```
Render As:
<Files>
<Folder name="src">
<File name="App.tsx" />
<File name="index.tsx" />
<Folder name="components">
<File name="Button.tsx" />
<File name="Card.tsx" />
</Folder>
<Folder name="pages">
<File name="Home.tsx" />
<File name="About.tsx" />
</Folder>
</Folder>
</Files>
## Props
### Files
The root component that wraps the entire file tree.
### Folder
| Prop | Type | Required | Description |
|----------|----------|----------|---------------------------------------|
| name | string | Yes | The name of the folder |
| children | ReactNode | No | Child elements (File or Folder) |
### File
| Prop | Type | Required | Description |
|------|--------|----------|----------------------------|
| name | string | Yes | The name of the file |
## Examples
### Nested Folder Structure
```
<Files>
<Folder name="project-root">
<File name="package.json" />
<File name="tsconfig.json" />
<Folder name="src">
<File name="index.ts" />
<Folder name="components">
<File name="Button.tsx" />
<File name="Card.tsx" />
</Folder>
</Folder>
</Folder>
</Files>
```
### Minimal Example
```
<Files>
<Folder name="components">
<File name="Button.tsx" />
<File name="Input.tsx" />
</Folder>
</Files>
```
## Best Practices
1. Keep the nesting level reasonable (recommended max 3-4 levels deep)
2. Use clear and descriptive names for files and folders
3. Consider the user experience when displaying large file structures
4. Use consistent naming conventions throughout your file tree
## Accessibility
The File Tree component includes built-in accessibility features:
- Keyboard navigation support
- ARIA attributes for screen readers
- Focus management for interactive elements
- High contrast mode support

View File

@@ -14,11 +14,6 @@
"footer": {
"copyright": "DocuBook",
"social": [
{
"name": "Gitlab",
"url": "https://gitlab.com/mywildancloud",
"iconName": "GitlabIcon"
},
{
"name": "Instagram",
"url": "https://www.instagram.com/wildan.nrs",
@@ -48,7 +43,7 @@
"favicon": "/favicon.ico"
},
"repository": {
"url": "https://github.com/gitfromwildan/docubook",
"url": "https://github.com/DocuBook/docubook",
"editPathTemplate": "/blob/main/{filePath}",
"editLink": true
},
@@ -58,7 +53,7 @@
"title": "Vercel",
"description": "Deploy your DocuBook app with zero configuration.",
"image": "/images/vercel.png",
"url": "https://vercel.com/import/project?template=https://github.com/gitfromwildan/docubook"
"url": "https://vercel.com/import/project?template=https://github.com/DocuBook/docubook"
}
},
"routes": [
@@ -80,6 +75,7 @@
{ "title": "Card", "href": "/card" },
{ "title": "Card Group", "href": "/card-group" },
{ "title": "Code Block", "href": "/code-block" },
{ "title": "File Tree", "href": "/file-tree" },
{ "title": "Image", "href": "/image" },
{ "title": "Keyboard", "href": "/keyboard" },
{ "title": "Link", "href": "/link" },

View File

@@ -26,6 +26,7 @@ import Accordion from "@/components/markdown/AccordionMdx";
import CardGroup from "@/components/markdown/CardGroupMdx";
import Kbd from "@/components/markdown/KeyboardMdx";
import { Release, Changes } from "@/components/markdown/ReleaseMdx";
import { File, Files, Folder } from "@/components/markdown/FileTreeMdx";
// add custom components
const components = {
@@ -47,8 +48,13 @@ const components = {
Accordion,
CardGroup,
Kbd,
// Release Note Components
Release,
Changes,
// File Tree Components
File,
Files,
Folder,
};
// can be used for other pages like blogs, Guides etc
@@ -181,64 +187,3 @@ const postProcess = () => (tree: any) => {
}
});
};
// export type Author = {
// avatar?: string;
// handle: string;
// username: string;
// handleUrl: string;
// };
// Blog related types and functions have been removed
/*
export type BlogMdxFrontmatter = BaseMdxFrontmatter & {
date: string;
authors: Author[];
cover: string;
};
export async function getAllBlogStaticPaths() {
try {
const blogFolder = path.join(process.cwd(), "/contents/blogs/");
const res = await fs.readdir(blogFolder);
return res.map((file) => file.split(".")[0]);
} catch (err) {
console.log(err);
return [];
}
}
export async function getAllBlogs() {
const blogFolder = path.join(process.cwd(), "/contents/blogs/");
const files = await fs.readdir(blogFolder);
const uncheckedRes = await Promise.all(
files.map(async (file) => {
try {
const filepath = path.join(process.cwd(), `/contents/blogs/${file}`);
const rawMdx = await fs.readFile(filepath, "utf-8");
return {
...justGetFrontmatterFromMD<BlogMdxFrontmatter>(rawMdx),
slug: file.split(".")[0],
};
} catch (err) {
console.log(err);
return null;
}
})
);
return uncheckedRes.filter((it) => !!it) as (BlogMdxFrontmatter & {
slug: string;
})[];
}
export async function getBlogForSlug(slug: string) {
try {
const blogFile = path.join(process.cwd(), "/contents/blogs/", `${slug}.mdx`);
const rawMdx = await fs.readFile(blogFile, "utf-8");
return await parseMdx<BlogMdxFrontmatter>(rawMdx);
} catch (err) {
console.log(err);
return null;
}
}
*/

8628
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "docubook",
"version": "1.11.0",
"version": "1.12.0",
"private": true,
"scripts": {
"dev": "next dev",
@@ -54,6 +54,5 @@
"postcss": "^8",
"tailwindcss": "^3.4.10",
"typescript": "^5"
},
"packageManager": "npm@11.3.0"
}
}