@docubook/create 1.12.0 → 1.13.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/dist/.vscode/card.code-snippets +52 -14
- package/src/dist/.vscode/table.code-snippets +10 -18
- package/src/dist/app/page.tsx +2 -2
- package/src/dist/components/context-popover.tsx +133 -0
- package/src/dist/components/docs-menu.tsx +39 -21
- package/src/dist/components/footer.tsx +4 -2
- package/src/dist/components/leftbar.tsx +10 -4
- package/src/dist/components/markdown/CardGroupMdx.tsx +1 -1
- package/src/dist/components/markdown/CardMdx.tsx +5 -4
- package/src/dist/components/markdown/FileTreeMdx.tsx +52 -33
- package/src/dist/components/markdown/KeyboardMdx.tsx +1 -1
- package/src/dist/components/markdown/NoteMdx.tsx +1 -1
- package/src/dist/components/markdown/StepperMdx.tsx +2 -2
- package/src/dist/components/markdown/TooltipsMdx.tsx +6 -3
- package/src/dist/components/navbar.tsx +3 -3
- package/src/dist/components/search.tsx +36 -4
- package/src/dist/components/sublink.tsx +7 -6
- package/src/dist/components/theme-toggle.tsx +10 -10
- package/src/dist/components/toc-observer.tsx +9 -9
- package/src/dist/contents/docs/{getting-started/changelog → changelog/version-1}/index.mdx +45 -3
- package/src/dist/contents/docs/components/accordion/index.mdx +86 -0
- package/src/dist/contents/docs/components/button/index.mdx +40 -0
- package/src/dist/contents/docs/{getting-started/components → components}/card/index.mdx +9 -11
- package/src/dist/contents/docs/{getting-started/components → components}/card-group/index.mdx +2 -4
- package/src/dist/contents/docs/{getting-started/components → components}/code-block/index.mdx +2 -4
- package/src/dist/contents/docs/{getting-started/components → components}/file-tree/index.mdx +3 -3
- package/src/dist/contents/docs/{getting-started/components → components}/index.mdx +1 -1
- package/src/dist/contents/docs/{getting-started/components → components}/keyboard/index.mdx +3 -3
- package/src/dist/contents/docs/{getting-started/components → components}/note/index.mdx +4 -6
- package/src/dist/contents/docs/{getting-started/components → components}/release-note/index.mdx +2 -2
- package/src/dist/contents/docs/{getting-started/components → components}/stepper/index.mdx +2 -4
- package/src/dist/contents/docs/{getting-started/components → components}/tabs/index.mdx +4 -4
- package/src/dist/contents/docs/{getting-started/components → components}/tooltips/index.mdx +1 -1
- package/src/dist/contents/docs/{getting-started/components → components}/youtube/index.mdx +7 -5
- package/src/dist/contents/docs/getting-started/customize/index.mdx +0 -2
- package/src/dist/contents/docs/getting-started/index.mdx +9 -0
- package/src/dist/contents/docs/getting-started/installation/index.mdx +1 -1
- package/src/dist/contents/docs/getting-started/introduction/index.mdx +1 -1
- package/src/dist/contents/docs/getting-started/quick-start-guide/index.mdx +78 -60
- package/src/dist/contents/docs/getting-started/theme-colors/coffee/index.mdx +167 -0
- package/src/dist/contents/docs/getting-started/theme-colors/default/index.mdx +163 -0
- package/src/dist/contents/docs/getting-started/theme-colors/freshlime/index.mdx +164 -0
- package/src/dist/contents/docs/getting-started/theme-colors/index.mdx +9 -0
- package/src/dist/contents/docs/getting-started/theme-colors/llms/index.mdx +66 -0
- package/src/dist/docu.json +56 -23
- package/src/dist/lib/routes-config.ts +8 -1
- package/src/dist/package.json +1 -1
- package/src/dist/styles/globals.css +50 -67
- package/src/dist/styles/syntax.css +24 -29
- package/src/dist/tailwind.config.ts +0 -1
- package/bun.lock +0 -102
- package/src/dist/.vscode/extensions.json +0 -3
- package/src/dist/contents/docs/getting-started/components/accordion/index.mdx +0 -72
- package/src/dist/contents/docs/getting-started/components/button/index.mdx +0 -42
- package/src/dist/styles/editor.css +0 -57
- /package/src/dist/contents/docs/{getting-started/components → components}/custom/index.mdx +0 -0
- /package/src/dist/contents/docs/{getting-started/components → components}/image/index.mdx +0 -0
- /package/src/dist/contents/docs/{getting-started/components → components}/link/index.mdx +0 -0
package/package.json
CHANGED
|
@@ -1,16 +1,54 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
2
|
+
"Docu Card Group": {
|
|
3
|
+
"prefix": "card-group",
|
|
4
|
+
"body": [
|
|
5
|
+
"<CardGroup cols={${1:2}}>",
|
|
6
|
+
" <Card title=\"${2:Card Title}\" icon=\"${3:Home}\">",
|
|
7
|
+
" ${4:Card content goes here. You can add **markdown** content.}",
|
|
8
|
+
" </Card>",
|
|
9
|
+
" <Card title=\"${5:Another Card}\" icon=\"${6:Settings}\">",
|
|
10
|
+
" ${7:More content here.}",
|
|
11
|
+
" </Card>",
|
|
12
|
+
"</CardGroup>"
|
|
13
|
+
],
|
|
14
|
+
"description": "Create a group of cards in a responsive grid"
|
|
15
|
+
},
|
|
16
|
+
"Docu Card": {
|
|
17
|
+
"prefix": "card",
|
|
18
|
+
"body": [
|
|
19
|
+
"<Card ",
|
|
20
|
+
" title=\"${1:Card Title}\"",
|
|
21
|
+
" icon=\"${2:Home}\"",
|
|
22
|
+
" href=\"${3:/optional-link}\"",
|
|
23
|
+
" ${4:horizontal}>",
|
|
24
|
+
" ${5:Card content goes here. You can add **markdown** content.}",
|
|
25
|
+
"</Card>"
|
|
26
|
+
],
|
|
27
|
+
"description": "Create a single card component"
|
|
28
|
+
},
|
|
29
|
+
"Docu Horizontal Card": {
|
|
30
|
+
"prefix": "card-horizontal",
|
|
31
|
+
"body": [
|
|
32
|
+
"<Card ",
|
|
33
|
+
" title=\"${1:Card Title}\"",
|
|
34
|
+
" icon=\"${2:Home}\"",
|
|
35
|
+
" href=\"${3:/optional-link}\"",
|
|
36
|
+
" horizontal>",
|
|
37
|
+
" ${4:Content appears next to the icon in a horizontal layout.}",
|
|
38
|
+
"</Card>"
|
|
39
|
+
],
|
|
40
|
+
"description": "Create a horizontal card layout"
|
|
41
|
+
},
|
|
42
|
+
"Docu Card With Link": {
|
|
43
|
+
"prefix": "card-link",
|
|
44
|
+
"body": [
|
|
45
|
+
"<Card ",
|
|
46
|
+
" title=\"${1:Card Title}\"",
|
|
47
|
+
" icon=\"${2:ExternalLink}\"",
|
|
48
|
+
" href=\"${3:https://example.com}\">",
|
|
49
|
+
" ${4:This card is clickable and links to an external URL.}",
|
|
50
|
+
"</Card>"
|
|
51
|
+
],
|
|
52
|
+
"description": "Create a clickable card that links to a URL"
|
|
16
53
|
}
|
|
54
|
+
}
|
|
@@ -1,20 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"| Syntax Highlighting | Highlight code for better readability. |",
|
|
12
|
-
"| Code Line Highlighting & Titles | Highlight specific lines with descriptive titles. |",
|
|
13
|
-
"| Interactive Code Blocks | Language-specific and interactive code display. |",
|
|
14
|
-
"| Custom Markdown Components | Embed custom, reusable components in your docs. |",
|
|
15
|
-
"| Static Site Generation | Generate a static, high-performance site. |",
|
|
16
|
-
"| SEO-Optimized | Structured for optimal search engine indexing. |"
|
|
17
|
-
],
|
|
18
|
-
"description": "Create a DocuTable component on markdown."
|
|
19
|
-
}
|
|
2
|
+
"DocuTable": {
|
|
3
|
+
"prefix": "table",
|
|
4
|
+
"body": [
|
|
5
|
+
"| **${1:Header 1}** | **${2:Header 2}** |",
|
|
6
|
+
"| ---------------- | ---------------- |",
|
|
7
|
+
"| ${3:Row 1, Col 1} | ${4:Row 1, Col 2} |",
|
|
8
|
+
"| ${5:Row 2, Col 1} | ${6:Row 2, Col 2} |"
|
|
9
|
+
],
|
|
10
|
+
"description": "Create a simple 2x2 markdown table"
|
|
20
11
|
}
|
|
12
|
+
}
|
package/src/dist/app/page.tsx
CHANGED
|
@@ -15,7 +15,7 @@ export default function Home() {
|
|
|
15
15
|
return (
|
|
16
16
|
<div className="flex flex-col items-center justify-center px-2 py-8 text-center sm:py-36">
|
|
17
17
|
<Link
|
|
18
|
-
href="/docs/
|
|
18
|
+
href="/docs/changelog/version-1"
|
|
19
19
|
className="mb-5 sm:text-lg flex items-center gap-2 underline underline-offset-4 sm:-mt-12"
|
|
20
20
|
>
|
|
21
21
|
<div className="z-10 flex min-h-10 items-center justify-center max-[800px]:mt-10">
|
|
@@ -25,7 +25,7 @@ export default function Home() {
|
|
|
25
25
|
)}
|
|
26
26
|
>
|
|
27
27
|
<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">
|
|
28
|
-
<span>🚀 New Version - Release v1.
|
|
28
|
+
<span>🚀 New Version - Release v1.13.5</span>
|
|
29
29
|
<ArrowRightIcon className="ml-1 size-3 transition-transform duration-300 ease-in-out group-hover:translate-x-0.5" />
|
|
30
30
|
</AnimatedShinyText>
|
|
31
31
|
</div>
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { usePathname, useRouter } from "next/navigation";
|
|
4
|
+
import { useState, useEffect } from "react";
|
|
5
|
+
import { ROUTES, EachRoute } from "@/lib/routes-config";
|
|
6
|
+
import { cn } from "@/lib/utils";
|
|
7
|
+
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
|
8
|
+
import { Button } from "@/components/ui/button";
|
|
9
|
+
import * as LucideIcons from "lucide-react";
|
|
10
|
+
import { ChevronsUpDown, Check, type LucideIcon } from "lucide-react";
|
|
11
|
+
|
|
12
|
+
interface ContextPopoverProps {
|
|
13
|
+
className?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Get all root-level routes with context
|
|
17
|
+
function getContextRoutes(): EachRoute[] {
|
|
18
|
+
return ROUTES.filter(route => route.context);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Get the first item's href from a route
|
|
22
|
+
function getFirstItemHref(route: EachRoute): string {
|
|
23
|
+
return route.items?.[0]?.href ? `${route.href}${route.items[0].href}` : route.href;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Get the active context route from the current path
|
|
27
|
+
function getActiveContextRoute(path: string): EachRoute | undefined {
|
|
28
|
+
if (!path.startsWith('/docs')) return undefined;
|
|
29
|
+
const docPath = path.replace(/^\/docs/, '');
|
|
30
|
+
return getContextRoutes().find(route => docPath.startsWith(route.href));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Get icon component by name
|
|
34
|
+
function getIcon(name: string) {
|
|
35
|
+
const Icon = LucideIcons[name as keyof typeof LucideIcons] as LucideIcon | undefined;
|
|
36
|
+
if (!Icon) return <LucideIcons.FileQuestion className="h-4 w-4" />;
|
|
37
|
+
return <Icon className="h-4 w-4" />;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default function ContextPopover({ className }: ContextPopoverProps) {
|
|
41
|
+
const pathname = usePathname();
|
|
42
|
+
const router = useRouter();
|
|
43
|
+
const [activeRoute, setActiveRoute] = useState<EachRoute>();
|
|
44
|
+
const contextRoutes = getContextRoutes();
|
|
45
|
+
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
if (pathname.startsWith("/docs")) {
|
|
48
|
+
setActiveRoute(getActiveContextRoute(pathname));
|
|
49
|
+
} else {
|
|
50
|
+
setActiveRoute(undefined);
|
|
51
|
+
}
|
|
52
|
+
}, [pathname]);
|
|
53
|
+
|
|
54
|
+
if (!pathname.startsWith("/docs") || contextRoutes.length === 0) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<Popover>
|
|
60
|
+
<PopoverTrigger asChild>
|
|
61
|
+
<Button
|
|
62
|
+
variant="ghost"
|
|
63
|
+
className={cn(
|
|
64
|
+
"w-full max-w-[240px] flex items-center justify-between font-semibold text-foreground px-0 pt-8",
|
|
65
|
+
"hover:bg-transparent hover:text-foreground",
|
|
66
|
+
className
|
|
67
|
+
)}
|
|
68
|
+
>
|
|
69
|
+
<div className="flex items-center gap-2">
|
|
70
|
+
{activeRoute?.context?.icon && (
|
|
71
|
+
<span className="text-primary bg-primary/10 border border-primary dark:border dark:border-accent dark:bg-accent/10 dark:text-accent rounded p-0.5">
|
|
72
|
+
{getIcon(activeRoute.context.icon)}
|
|
73
|
+
</span>
|
|
74
|
+
)}
|
|
75
|
+
<span className="truncate text-sm">
|
|
76
|
+
{activeRoute?.context?.title || activeRoute?.title || 'Select context'}
|
|
77
|
+
</span>
|
|
78
|
+
</div>
|
|
79
|
+
<ChevronsUpDown className="h-4 w-4 text-foreground/50" />
|
|
80
|
+
</Button>
|
|
81
|
+
</PopoverTrigger>
|
|
82
|
+
<PopoverContent
|
|
83
|
+
className="w-64 p-2"
|
|
84
|
+
align="start"
|
|
85
|
+
sideOffset={6}
|
|
86
|
+
>
|
|
87
|
+
<div className="space-y-1">
|
|
88
|
+
{contextRoutes.map((route) => {
|
|
89
|
+
const isActive = activeRoute?.href === route.href;
|
|
90
|
+
const firstItemPath = getFirstItemHref(route);
|
|
91
|
+
const contextPath = `/docs${firstItemPath}`;
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<button
|
|
95
|
+
key={route.href}
|
|
96
|
+
onClick={() => router.push(contextPath)}
|
|
97
|
+
className={cn(
|
|
98
|
+
"relative flex w-full items-center gap-2 rounded px-2 py-1.5 text-sm",
|
|
99
|
+
"text-left outline-none transition-colors",
|
|
100
|
+
isActive
|
|
101
|
+
? "bg-primary/20 text-primary dark:bg-accent/20 dark:text-accent"
|
|
102
|
+
: "text-foreground/80 hover:bg-primary/20 dark:text-foreground/60 dark:hover:bg-accent/20"
|
|
103
|
+
)}
|
|
104
|
+
>
|
|
105
|
+
{route.context?.icon && (
|
|
106
|
+
<span className={cn(
|
|
107
|
+
"flex h-4 w-4 items-center justify-center",
|
|
108
|
+
isActive ? "text-primary dark:text-accent" : "text-foreground/60"
|
|
109
|
+
)}>
|
|
110
|
+
{getIcon(route.context.icon)}
|
|
111
|
+
</span>
|
|
112
|
+
)}
|
|
113
|
+
<div className="flex-1 min-w-0 overflow-hidden">
|
|
114
|
+
<div className="truncate font-medium">
|
|
115
|
+
{route.context?.title || route.title}
|
|
116
|
+
</div>
|
|
117
|
+
{route.context?.description && (
|
|
118
|
+
<div className="text-xs text-muted-foreground truncate text-ellipsis overflow-hidden max-w-full">
|
|
119
|
+
{route.context.description}
|
|
120
|
+
</div>
|
|
121
|
+
)}
|
|
122
|
+
</div>
|
|
123
|
+
{isActive && (
|
|
124
|
+
<Check className="h-3.5 w-3.5" />
|
|
125
|
+
)}
|
|
126
|
+
</button>
|
|
127
|
+
);
|
|
128
|
+
})}
|
|
129
|
+
</div>
|
|
130
|
+
</PopoverContent>
|
|
131
|
+
</Popover>
|
|
132
|
+
);
|
|
133
|
+
}
|
|
@@ -1,44 +1,62 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { ROUTES } from "@/lib/routes-config";
|
|
3
|
+
import { ROUTES, EachRoute } from "@/lib/routes-config";
|
|
4
4
|
import SubLink from "./sublink";
|
|
5
5
|
import { usePathname } from "next/navigation";
|
|
6
|
+
import { cn } from "@/lib/utils";
|
|
6
7
|
|
|
7
8
|
interface DocsMenuProps {
|
|
8
9
|
isSheet?: boolean;
|
|
9
10
|
className?: string;
|
|
10
11
|
}
|
|
11
12
|
|
|
13
|
+
// Get the current context from the path
|
|
14
|
+
function getCurrentContext(path: string): string | undefined {
|
|
15
|
+
if (!path.startsWith('/docs')) return undefined;
|
|
16
|
+
|
|
17
|
+
// Extract the first segment after /docs/
|
|
18
|
+
const match = path.match(/^\/docs\/([^\/]+)/);
|
|
19
|
+
return match ? match[1] : undefined;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Get the route that matches the current context
|
|
23
|
+
function getContextRoute(contextPath: string): EachRoute | undefined {
|
|
24
|
+
return ROUTES.find(route => {
|
|
25
|
+
const normalizedHref = route.href.replace(/^\/+|\/+$/g, '');
|
|
26
|
+
return normalizedHref === contextPath;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
12
30
|
export default function DocsMenu({ isSheet = false, className = "" }: DocsMenuProps) {
|
|
13
31
|
const pathname = usePathname();
|
|
14
32
|
|
|
15
33
|
// Skip rendering if not on a docs page
|
|
16
34
|
if (!pathname.startsWith("/docs")) return null;
|
|
17
35
|
|
|
36
|
+
// Get the current context
|
|
37
|
+
const currentContext = getCurrentContext(pathname);
|
|
38
|
+
|
|
39
|
+
// Get the route for the current context
|
|
40
|
+
const contextRoute = currentContext ? getContextRoute(currentContext) : undefined;
|
|
41
|
+
|
|
42
|
+
// If no context route is found, don't render anything
|
|
43
|
+
if (!contextRoute) return null;
|
|
44
|
+
|
|
18
45
|
return (
|
|
19
46
|
<nav
|
|
20
47
|
aria-label="Documentation navigation"
|
|
21
|
-
className={className}
|
|
48
|
+
className={cn("transition-all duration-200", className)}
|
|
22
49
|
>
|
|
23
|
-
<ul className="flex flex-col gap-
|
|
24
|
-
{
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
isSheet,
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
return (
|
|
37
|
-
<li key={`${item.title}-${index}`}>
|
|
38
|
-
<SubLink {...modifiedItems} />
|
|
39
|
-
</li>
|
|
40
|
-
);
|
|
41
|
-
})}
|
|
50
|
+
<ul className="flex flex-col gap-1.5 py-4">
|
|
51
|
+
{/* Display only the items from the current context */}
|
|
52
|
+
<li key={contextRoute.title}>
|
|
53
|
+
<SubLink
|
|
54
|
+
{...contextRoute}
|
|
55
|
+
href={`/docs${contextRoute.href}`}
|
|
56
|
+
level={0}
|
|
57
|
+
isSheet={isSheet}
|
|
58
|
+
/>
|
|
59
|
+
</li>
|
|
42
60
|
</ul>
|
|
43
61
|
</nav>
|
|
44
62
|
);
|
|
@@ -63,8 +63,9 @@ export function FooterButtons() {
|
|
|
63
63
|
target="_blank"
|
|
64
64
|
rel="noopener noreferrer"
|
|
65
65
|
aria-label={item.name}
|
|
66
|
+
className="text-muted-foreground hover:text-foreground transition-colors"
|
|
66
67
|
>
|
|
67
|
-
<IconComponent className="w-4 h-4
|
|
68
|
+
<IconComponent className="w-4 h-4" />
|
|
68
69
|
</Link>
|
|
69
70
|
);
|
|
70
71
|
})}
|
|
@@ -79,7 +80,8 @@ export function MadeWith() {
|
|
|
79
80
|
<span className="text-primary">
|
|
80
81
|
<Link href="https://www.docubook.pro" target="_blank" rel="noopener noreferrer" className="underline underline-offset-2 text-muted-foreground">
|
|
81
82
|
DocuBook
|
|
82
|
-
</Link
|
|
83
|
+
</Link>
|
|
84
|
+
</span>
|
|
83
85
|
</>
|
|
84
86
|
);
|
|
85
87
|
}
|
|
@@ -10,11 +10,11 @@ import {
|
|
|
10
10
|
import { Logo, NavMenu } from "@/components/navbar";
|
|
11
11
|
import { Button } from "@/components/ui/button";
|
|
12
12
|
import { AlignLeftIcon, PanelLeftClose, PanelLeftOpen } from "lucide-react";
|
|
13
|
-
import { FooterButtons } from "@/components/footer";
|
|
14
13
|
import { DialogTitle, DialogDescription } from "@/components/ui/dialog";
|
|
15
14
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
|
16
15
|
import DocsMenu from "@/components/docs-menu";
|
|
17
16
|
import { ModeToggle } from "@/components/theme-toggle";
|
|
17
|
+
import ContextPopover from "@/components/context-popover";
|
|
18
18
|
|
|
19
19
|
// Toggle Button Component
|
|
20
20
|
export function ToggleButton({
|
|
@@ -52,9 +52,14 @@ export function Leftbar() {
|
|
|
52
52
|
${collapsed ? "w-[24px]" : "w-[280px]"} flex flex-col pr-2`}
|
|
53
53
|
>
|
|
54
54
|
<ToggleButton collapsed={collapsed} onToggle={toggleCollapse} />
|
|
55
|
-
{/* Scrollable
|
|
55
|
+
{/* Scrollable Content */}
|
|
56
56
|
<ScrollArea className="flex-1 px-0.5 pb-4">
|
|
57
|
-
{!collapsed &&
|
|
57
|
+
{!collapsed && (
|
|
58
|
+
<div className="space-y-2">
|
|
59
|
+
<ContextPopover />
|
|
60
|
+
<DocsMenu />
|
|
61
|
+
</div>
|
|
62
|
+
)}
|
|
58
63
|
</ScrollArea>
|
|
59
64
|
</aside>
|
|
60
65
|
);
|
|
@@ -82,7 +87,8 @@ export function SheetLeftbar() {
|
|
|
82
87
|
<div className="flex flex-col gap-2.5 mt-3 mx-2 px-5">
|
|
83
88
|
<NavMenu isSheet />
|
|
84
89
|
</div>
|
|
85
|
-
<div className="mx-2 px-5">
|
|
90
|
+
<div className="mx-2 px-5 space-y-2">
|
|
91
|
+
<ContextPopover />
|
|
86
92
|
<DocsMenu isSheet />
|
|
87
93
|
</div>
|
|
88
94
|
<div className="flex w-2/4 px-5">
|
|
@@ -20,8 +20,9 @@ const Card: React.FC<CardProps> = ({ title, icon, href, horizontal, children, cl
|
|
|
20
20
|
const content = (
|
|
21
21
|
<div
|
|
22
22
|
className={clsx(
|
|
23
|
-
"border rounded-lg shadow-sm p-4 transition-all duration-200
|
|
24
|
-
"
|
|
23
|
+
"border rounded-lg shadow-sm p-4 transition-all duration-200",
|
|
24
|
+
"bg-card text-card-foreground border-border",
|
|
25
|
+
"hover:bg-accent/5 hover:border-accent/30",
|
|
25
26
|
"flex gap-2",
|
|
26
27
|
horizontal ? "flex-row items-center gap-1" : "flex-col space-y-1",
|
|
27
28
|
className
|
|
@@ -29,8 +30,8 @@ const Card: React.FC<CardProps> = ({ title, icon, href, horizontal, children, cl
|
|
|
29
30
|
>
|
|
30
31
|
{Icon && <Icon className="w-5 h-5 text-primary flex-shrink-0" />}
|
|
31
32
|
<div className="flex-1 min-w-0 my-auto h-full">
|
|
32
|
-
<span className="text-base font-semibold">{title}</span>
|
|
33
|
-
<div className="text-sm text-
|
|
33
|
+
<span className="text-base font-semibold text-foreground">{title}</span>
|
|
34
|
+
<div className="text-sm text-muted-foreground -mt-3">{children}</div>
|
|
34
35
|
</div>
|
|
35
36
|
</div>
|
|
36
37
|
);
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import React, { useState, ReactNode, Children, isValidElement, cloneElement } from 'react';
|
|
4
|
-
import { ChevronRight,
|
|
5
|
-
|
|
6
|
-
interface FileTreeProps {
|
|
7
|
-
children: ReactNode;
|
|
8
|
-
defaultOpen?: boolean;
|
|
9
|
-
}
|
|
4
|
+
import { ChevronRight, File as FileIcon, Folder as FolderIcon, FolderOpen } from 'lucide-react';
|
|
10
5
|
|
|
11
6
|
interface FileProps {
|
|
12
7
|
name: string;
|
|
@@ -15,24 +10,27 @@ interface FileProps {
|
|
|
15
10
|
|
|
16
11
|
const FileComponent = ({ name }: FileProps) => {
|
|
17
12
|
const [isHovered, setIsHovered] = useState(false);
|
|
13
|
+
const fileExtension = name.split('.').pop()?.toUpperCase();
|
|
18
14
|
|
|
19
15
|
return (
|
|
20
16
|
<div
|
|
21
17
|
className={`
|
|
22
|
-
flex items-center gap-2 py-1.5 pl-7 pr-3 text-sm
|
|
23
|
-
transition-
|
|
24
|
-
${isHovered
|
|
25
|
-
? 'bg-blue-50 dark:bg-blue-900/30'
|
|
26
|
-
: 'hover:bg-gray-50 dark:hover:bg-gray-800/50'}
|
|
18
|
+
flex items-center gap-2 py-1.5 pl-7 pr-3 text-sm rounded-md
|
|
19
|
+
transition-colors duration-150 cursor-default select-none
|
|
20
|
+
${isHovered ? 'bg-accent/10' : 'hover:bg-muted/50'}
|
|
27
21
|
`}
|
|
28
22
|
onMouseEnter={() => setIsHovered(true)}
|
|
29
23
|
onMouseLeave={() => setIsHovered(false)}
|
|
24
|
+
tabIndex={-1}
|
|
30
25
|
>
|
|
31
|
-
<FileIcon className={`
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
26
|
+
<FileIcon className={`
|
|
27
|
+
h-3.5 w-3.5 flex-shrink-0 transition-colors
|
|
28
|
+
${isHovered ? 'text-accent' : 'text-muted-foreground'}
|
|
29
|
+
`} />
|
|
30
|
+
<span className="font-mono text-sm text-foreground truncate">{name}</span>
|
|
31
|
+
{isHovered && fileExtension && (
|
|
32
|
+
<span className="ml-auto text-xs text-muted-foreground/80">
|
|
33
|
+
{fileExtension}
|
|
36
34
|
</span>
|
|
37
35
|
)}
|
|
38
36
|
</div>
|
|
@@ -48,31 +46,49 @@ const FolderComponent = ({ name, children }: FileProps) => {
|
|
|
48
46
|
<div className="relative">
|
|
49
47
|
<div
|
|
50
48
|
className={`
|
|
51
|
-
flex items-center gap-2 py-1.5 pl-4 pr-3 rounded-md
|
|
52
|
-
transition-
|
|
53
|
-
${isHovered ? 'bg-
|
|
54
|
-
${isOpen ? 'text-
|
|
49
|
+
flex items-center gap-2 py-1.5 pl-4 pr-3 rounded-md
|
|
50
|
+
transition-colors duration-150 select-none
|
|
51
|
+
${isHovered ? 'bg-muted/60' : ''}
|
|
52
|
+
${isOpen ? 'text-foreground' : 'text-foreground/80'}
|
|
53
|
+
${hasChildren ? 'cursor-pointer' : 'cursor-default'}
|
|
55
54
|
`}
|
|
56
|
-
onClick={() => setIsOpen(!isOpen)}
|
|
55
|
+
onClick={() => hasChildren && setIsOpen(!isOpen)}
|
|
57
56
|
onMouseEnter={() => setIsHovered(true)}
|
|
58
57
|
onMouseLeave={() => setIsHovered(false)}
|
|
58
|
+
tabIndex={-1}
|
|
59
|
+
onKeyDown={(e) => e.preventDefault()}
|
|
59
60
|
>
|
|
60
61
|
{hasChildren ? (
|
|
61
62
|
<ChevronRight
|
|
62
|
-
className={`
|
|
63
|
+
className={`
|
|
64
|
+
h-3.5 w-3.5 flex-shrink-0 transition-transform duration-200
|
|
65
|
+
${isOpen ? 'rotate-90' : ''}
|
|
66
|
+
${isHovered ? 'text-foreground/70' : 'text-muted-foreground'}
|
|
67
|
+
`}
|
|
63
68
|
/>
|
|
64
69
|
) : (
|
|
65
70
|
<div className="w-3.5" />
|
|
66
71
|
)}
|
|
67
72
|
{isOpen ? (
|
|
68
|
-
<FolderOpen className=
|
|
73
|
+
<FolderOpen className={`
|
|
74
|
+
h-4 w-4 flex-shrink-0 transition-colors
|
|
75
|
+
${isHovered ? 'text-accent' : 'text-muted-foreground'}
|
|
76
|
+
`} />
|
|
69
77
|
) : (
|
|
70
|
-
<FolderIcon className=
|
|
78
|
+
<FolderIcon className={`
|
|
79
|
+
h-4 w-4 flex-shrink-0 transition-colors
|
|
80
|
+
${isHovered ? 'text-accent/80' : 'text-muted-foreground/80'}
|
|
81
|
+
`} />
|
|
71
82
|
)}
|
|
72
|
-
<span className=
|
|
83
|
+
<span className={`
|
|
84
|
+
font-medium transition-colors duration-150
|
|
85
|
+
${isHovered ? 'text-accent' : ''}
|
|
86
|
+
`}>
|
|
87
|
+
{name}
|
|
88
|
+
</span>
|
|
73
89
|
</div>
|
|
74
90
|
{isOpen && hasChildren && (
|
|
75
|
-
<div className="ml-5 border-l-2 border-
|
|
91
|
+
<div className="ml-5 border-l-2 border-muted/50 pl-2">
|
|
76
92
|
{children}
|
|
77
93
|
</div>
|
|
78
94
|
)}
|
|
@@ -82,13 +98,16 @@ const FolderComponent = ({ name, children }: FileProps) => {
|
|
|
82
98
|
|
|
83
99
|
export const Files = ({ children }: { children: ReactNode }) => {
|
|
84
100
|
return (
|
|
85
|
-
<div
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
101
|
+
<div
|
|
102
|
+
className="
|
|
103
|
+
rounded-xl border border-muted/50
|
|
104
|
+
bg-card/50 backdrop-blur-sm
|
|
105
|
+
shadow-sm overflow-hidden
|
|
106
|
+
transition-all duration-200
|
|
107
|
+
hover:shadow-md hover:border-muted/60
|
|
108
|
+
"
|
|
109
|
+
onKeyDown={(e) => e.preventDefault()}
|
|
110
|
+
>
|
|
92
111
|
<div className="p-2">
|
|
93
112
|
{Children.map(children, (child, index) => {
|
|
94
113
|
if (isValidElement(child)) {
|
|
@@ -88,7 +88,7 @@ const KbdComponent: React.FC<KbdProps> = ({
|
|
|
88
88
|
|
|
89
89
|
return (
|
|
90
90
|
<kbd
|
|
91
|
-
className="inline-flex items-center justify-center px-2 py-1 mx-0.5 text-xs font-mono font-medium text-
|
|
91
|
+
className="inline-flex items-center justify-center px-2 py-1 mx-0.5 text-xs font-mono font-medium text-foreground bg-secondary/70 border rounded-md"
|
|
92
92
|
{...props}
|
|
93
93
|
>
|
|
94
94
|
{renderContent()}
|
|
@@ -29,7 +29,7 @@ export default function Note({
|
|
|
29
29
|
"dark:bg-stone-950/25 bg-stone-50": type === "note",
|
|
30
30
|
"dark:bg-red-950 bg-red-100 border-red-200 dark:border-red-900":
|
|
31
31
|
type === "danger",
|
|
32
|
-
"
|
|
32
|
+
"bg-orange-50 border-orange-200 dark:border-orange-900 dark:bg-orange-900/50":
|
|
33
33
|
type === "warning",
|
|
34
34
|
"dark:bg-green-950 bg-green-100 border-green-200 dark:border-green-900":
|
|
35
35
|
type === "success",
|
|
@@ -11,13 +11,13 @@ export function Stepper({ children }: PropsWithChildren) {
|
|
|
11
11
|
return (
|
|
12
12
|
<div
|
|
13
13
|
className={cn(
|
|
14
|
-
"border-l pl-9 ml-3 relative",
|
|
14
|
+
"border-l border-muted pl-9 ml-3 relative",
|
|
15
15
|
clsx({
|
|
16
16
|
"pb-5 ": index < length - 1,
|
|
17
17
|
})
|
|
18
18
|
)}
|
|
19
19
|
>
|
|
20
|
-
<div className="bg-muted w-8 h-8 text-xs font-medium rounded-md border flex items-center justify-center absolute -left-4 font-code">
|
|
20
|
+
<div className="bg-muted text-muted-foreground w-8 h-8 text-xs font-medium rounded-md border border-border/50 flex items-center justify-center absolute -left-4 font-code">
|
|
21
21
|
{index + 1}
|
|
22
22
|
</div>
|
|
23
23
|
{child}
|
|
@@ -11,14 +11,17 @@ const Tooltip: React.FC<TooltipProps> = ({ text, tip }) => {
|
|
|
11
11
|
|
|
12
12
|
return (
|
|
13
13
|
<span
|
|
14
|
-
className="relative inline-
|
|
14
|
+
className="relative inline-flex items-center cursor-help text-primary hover:text-primary/80 transition-colors"
|
|
15
15
|
onMouseEnter={() => setVisible(true)}
|
|
16
16
|
onMouseLeave={() => setVisible(false)}
|
|
17
17
|
>
|
|
18
|
-
|
|
18
|
+
<span className="border-b border-dashed border-primary/60 pb-0.5">
|
|
19
|
+
{text}
|
|
20
|
+
</span>
|
|
19
21
|
{visible && (
|
|
20
|
-
<span className="absolute bottom-full left-1/2 -translate-x-1/2 mb-
|
|
22
|
+
<span className="absolute bottom-full left-1/2 -translate-x-1/2 mb-3 w-64 bg-popover text-popover-foreground text-sm p-3 rounded-md shadow-lg border border-border/50 break-words text-left z-50">
|
|
21
23
|
{tip}
|
|
24
|
+
<span className="absolute -bottom-1.5 left-1/2 -translate-x-1/2 w-3 h-3 bg-popover rotate-45 border-b border-r border-border/50 -z-10" />
|
|
22
25
|
</span>
|
|
23
26
|
)}
|
|
24
27
|
</span>
|