boltdocs 1.0.1 → 1.3.0
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/dist/{CodeBlock-37XMKCYY.mjs → CodeBlock-V3Z5EKGR.mjs} +0 -1
- package/dist/{PackageManagerTabs-4NWXLXQO.mjs → PackageManagerTabs-XEKI3L7P.mjs} +0 -2
- package/dist/{SearchDialog-FTOQZ763.mjs → SearchDialog-5EDRACEG.mjs} +1 -2
- package/dist/{SearchDialog-ZAZXYIFX.css → SearchDialog-X57WPTNN.css} +57 -129
- package/dist/{Video-I6QY4X7J.mjs → Video-KNTY5BNO.mjs} +0 -1
- package/dist/cache-EHR7SXRU.mjs +12 -0
- package/dist/chunk-GSYECEZY.mjs +381 -0
- package/dist/{chunk-ZFCOLEXN.mjs → chunk-NS7WHDYA.mjs} +234 -426
- package/dist/client/index.css +57 -129
- package/dist/client/index.d.mts +39 -8
- package/dist/client/index.d.ts +39 -8
- package/dist/client/index.js +557 -564
- package/dist/client/index.mjs +305 -18
- package/dist/client/ssr.css +57 -129
- package/dist/client/ssr.d.mts +1 -1
- package/dist/client/ssr.d.ts +1 -1
- package/dist/client/ssr.js +257 -558
- package/dist/client/ssr.mjs +1 -2
- package/dist/{config-D2XmHJYe.d.mts → config-BD5ZHz15.d.mts} +7 -0
- package/dist/{config-D2XmHJYe.d.ts → config-BD5ZHz15.d.ts} +7 -0
- package/dist/node/index.d.mts +2 -2
- package/dist/node/index.d.ts +2 -2
- package/dist/node/index.js +457 -118
- package/dist/node/index.mjs +144 -147
- package/dist/{index-CRQKWAeo.d.mts → types-CvrzTbEX.d.mts} +1 -28
- package/dist/{index-CRQKWAeo.d.ts → types-CvrzTbEX.d.ts} +1 -28
- package/package.json +2 -2
- package/src/client/app/index.tsx +32 -110
- package/src/client/app/preload.tsx +1 -1
- package/src/client/index.ts +1 -1
- package/src/client/ssr.tsx +2 -1
- package/src/client/theme/components/Playground/Playground.tsx +40 -2
- package/src/client/theme/components/mdx/mdx-components.css +39 -20
- package/src/client/theme/styles/markdown.css +4 -4
- package/src/client/theme/styles.css +0 -1
- package/src/client/theme/ui/Breadcrumbs/Breadcrumbs.tsx +1 -1
- package/src/client/theme/ui/LanguageSwitcher/LanguageSwitcher.tsx +1 -1
- package/src/client/theme/ui/Layout/Layout.tsx +3 -14
- package/src/client/theme/ui/Layout/responsive.css +0 -4
- package/src/client/theme/ui/Link/Link.tsx +52 -0
- package/src/client/theme/ui/Navbar/Navbar.tsx +1 -1
- package/src/client/theme/ui/NotFound/NotFound.tsx +0 -1
- package/src/client/theme/ui/OnThisPage/OnThisPage.tsx +45 -2
- package/src/client/theme/ui/SearchDialog/SearchDialog.tsx +1 -1
- package/src/client/theme/ui/Sidebar/Sidebar.tsx +44 -40
- package/src/client/theme/ui/Sidebar/sidebar.css +25 -58
- package/src/client/theme/ui/VersionSwitcher/VersionSwitcher.tsx +1 -1
- package/src/client/types.ts +50 -0
- package/src/node/cache.ts +360 -46
- package/src/node/config.ts +7 -0
- package/src/node/mdx.ts +83 -4
- package/src/node/plugin/index.ts +3 -0
- package/src/node/routes/cache.ts +5 -1
- package/src/node/routes/index.ts +17 -2
- package/src/node/ssg/index.ts +4 -0
- package/dist/Playground-OE2OE6B6.mjs +0 -7
- package/dist/chunk-PN4GCTYG.mjs +0 -67
- package/dist/chunk-X2TDGMTR.mjs +0 -64
- package/dist/chunk-X6BYQHVC.mjs +0 -12
- package/dist/node/cli/index.d.mts +0 -1
- package/dist/node/cli/index.d.ts +0 -1
- package/dist/node/cli/index.js +0 -199
- package/dist/node/cli/index.mjs +0 -154
- package/src/client/theme/styles/home.css +0 -60
|
@@ -70,7 +70,6 @@ export function OnThisPage({
|
|
|
70
70
|
|
|
71
71
|
if (visibleEntries.length > 0) {
|
|
72
72
|
// If we have visible entries, find the one closest to the top of the viewport
|
|
73
|
-
// But with a priority for ones that just entered from the top
|
|
74
73
|
const closest = visibleEntries.reduce((prev, curr) => {
|
|
75
74
|
return Math.abs(curr.boundingClientRect.top - 100) <
|
|
76
75
|
Math.abs(prev.boundingClientRect.top - 100)
|
|
@@ -98,15 +97,59 @@ export function OnThisPage({
|
|
|
98
97
|
// Initial observation
|
|
99
98
|
observeHeadings();
|
|
100
99
|
|
|
101
|
-
// Re-observe if content changes
|
|
100
|
+
// Re-observe if content changes
|
|
102
101
|
const timeoutId = setTimeout(observeHeadings, 1000);
|
|
103
102
|
|
|
103
|
+
// Scroll listener to detect bottom of page
|
|
104
|
+
const handleScroll = () => {
|
|
105
|
+
const scrollPosition = window.innerHeight + window.pageYOffset;
|
|
106
|
+
const bodyHeight = document.documentElement.scrollHeight;
|
|
107
|
+
|
|
108
|
+
// If we're within 50px of the bottom, activate the last heading
|
|
109
|
+
if (scrollPosition >= bodyHeight - 50) {
|
|
110
|
+
setActiveId(headings[headings.length - 1].id);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
window.addEventListener("scroll", handleScroll, { passive: true });
|
|
115
|
+
|
|
104
116
|
return () => {
|
|
105
117
|
observerRef.current?.disconnect();
|
|
106
118
|
clearTimeout(timeoutId);
|
|
119
|
+
window.removeEventListener("scroll", handleScroll);
|
|
107
120
|
};
|
|
108
121
|
}, [headings, location.pathname]);
|
|
109
122
|
|
|
123
|
+
// Autoscroll TOC list when activeId changes
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
if (!activeId || !listRef.current) return;
|
|
126
|
+
|
|
127
|
+
const activeLink = listRef.current.querySelector(
|
|
128
|
+
`a[href="#${activeId}"]`,
|
|
129
|
+
) as HTMLElement;
|
|
130
|
+
|
|
131
|
+
if (activeLink) {
|
|
132
|
+
const container = listRef.current.closest(
|
|
133
|
+
".boltdocs-on-this-page",
|
|
134
|
+
) as HTMLElement;
|
|
135
|
+
if (!container) return;
|
|
136
|
+
|
|
137
|
+
const linkRect = activeLink.getBoundingClientRect();
|
|
138
|
+
const containerRect = container.getBoundingClientRect();
|
|
139
|
+
|
|
140
|
+
const isVisible =
|
|
141
|
+
linkRect.top >= containerRect.top &&
|
|
142
|
+
linkRect.bottom <= containerRect.bottom;
|
|
143
|
+
|
|
144
|
+
if (!isVisible) {
|
|
145
|
+
activeLink.scrollIntoView({
|
|
146
|
+
behavior: "smooth",
|
|
147
|
+
block: "nearest",
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}, [activeId]);
|
|
152
|
+
|
|
110
153
|
const handleClick = useCallback(
|
|
111
154
|
(e: React.MouseEvent<HTMLAnchorElement>, id: string) => {
|
|
112
155
|
e.preventDefault();
|
|
@@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef } from "react";
|
|
|
2
2
|
import { createPortal } from "react-dom";
|
|
3
3
|
import { Link } from "../Link";
|
|
4
4
|
import { Search } from "lucide-react";
|
|
5
|
-
import { ComponentRoute } from "../../../
|
|
5
|
+
import { ComponentRoute } from "../../../types";
|
|
6
6
|
|
|
7
7
|
interface SearchResult {
|
|
8
8
|
title: string;
|
|
@@ -3,7 +3,7 @@ import { useLocation } from "react-router-dom";
|
|
|
3
3
|
import { Link } from "../Link";
|
|
4
4
|
import { BoltdocsConfig } from "../../../../node/config";
|
|
5
5
|
import { PoweredBy } from "../PoweredBy";
|
|
6
|
-
import { ChevronRight, ChevronLeft } from "lucide-react";
|
|
6
|
+
import { ChevronRight, ChevronLeft, PanelLeft } from "lucide-react";
|
|
7
7
|
|
|
8
8
|
interface RouteItem {
|
|
9
9
|
path: string;
|
|
@@ -76,11 +76,13 @@ function renderBadge(badgeRaw: RouteItem["badge"]) {
|
|
|
76
76
|
export function Sidebar({
|
|
77
77
|
routes,
|
|
78
78
|
config,
|
|
79
|
-
|
|
79
|
+
isCollapsed,
|
|
80
|
+
onToggle,
|
|
80
81
|
}: {
|
|
81
82
|
routes: RouteItem[];
|
|
82
83
|
config: BoltdocsConfig;
|
|
83
|
-
|
|
84
|
+
isCollapsed?: boolean;
|
|
85
|
+
onToggle?: () => void;
|
|
84
86
|
}) {
|
|
85
87
|
const location = useLocation();
|
|
86
88
|
|
|
@@ -106,50 +108,52 @@ export function Sidebar({
|
|
|
106
108
|
|
|
107
109
|
return (
|
|
108
110
|
<aside className="boltdocs-sidebar">
|
|
109
|
-
|
|
110
|
-
<
|
|
111
|
-
{ungrouped.map((route) => (
|
|
112
|
-
<li key={route.path}>
|
|
113
|
-
<Link
|
|
114
|
-
to={route.path === "" ? "/" : route.path}
|
|
115
|
-
className={`sidebar-link ${location.pathname === route.path ? "active" : ""}`}
|
|
116
|
-
aria-current={
|
|
117
|
-
location.pathname === route.path ? "page" : undefined
|
|
118
|
-
}
|
|
119
|
-
>
|
|
120
|
-
<div className="sidebar-link-content">
|
|
121
|
-
<span>{route.title}</span>
|
|
122
|
-
{renderBadge(route.badge)}
|
|
123
|
-
</div>
|
|
124
|
-
</Link>
|
|
125
|
-
</li>
|
|
126
|
-
))}
|
|
127
|
-
</ul>
|
|
128
|
-
|
|
129
|
-
{groups.map((group) => (
|
|
130
|
-
<SidebarGroupSection
|
|
131
|
-
key={group.slug}
|
|
132
|
-
group={group}
|
|
133
|
-
currentPath={location.pathname}
|
|
134
|
-
/>
|
|
135
|
-
))}
|
|
136
|
-
</nav>
|
|
137
|
-
|
|
138
|
-
{onCollapse && (
|
|
139
|
-
<div className="sidebar-footer">
|
|
111
|
+
{onToggle && (
|
|
112
|
+
<div className="sidebar-collapse">
|
|
140
113
|
<button
|
|
141
114
|
className="sidebar-collapse-btn"
|
|
142
|
-
onClick={
|
|
143
|
-
aria-label="Collapse Sidebar"
|
|
144
|
-
title="Collapse Sidebar"
|
|
115
|
+
onClick={onToggle}
|
|
116
|
+
aria-label={isCollapsed ? "Expand Sidebar" : "Collapse Sidebar"}
|
|
117
|
+
title={isCollapsed ? "Expand Sidebar" : "Collapse Sidebar"}
|
|
145
118
|
>
|
|
146
|
-
<
|
|
147
|
-
<span>Collapse Sidebar</span>
|
|
119
|
+
<PanelLeft size={18} />
|
|
148
120
|
</button>
|
|
149
121
|
</div>
|
|
150
122
|
)}
|
|
151
123
|
|
|
152
|
-
{
|
|
124
|
+
{!isCollapsed && (
|
|
125
|
+
<>
|
|
126
|
+
<nav aria-label="Main Navigation">
|
|
127
|
+
<ul className="sidebar-list">
|
|
128
|
+
{ungrouped.map((route) => (
|
|
129
|
+
<li key={route.path}>
|
|
130
|
+
<Link
|
|
131
|
+
to={route.path === "" ? "/" : route.path}
|
|
132
|
+
className={`sidebar-link ${location.pathname === route.path ? "active" : ""}`}
|
|
133
|
+
aria-current={
|
|
134
|
+
location.pathname === route.path ? "page" : undefined
|
|
135
|
+
}
|
|
136
|
+
>
|
|
137
|
+
<div className="sidebar-link-content">
|
|
138
|
+
<span>{route.title}</span>
|
|
139
|
+
{renderBadge(route.badge)}
|
|
140
|
+
</div>
|
|
141
|
+
</Link>
|
|
142
|
+
</li>
|
|
143
|
+
))}
|
|
144
|
+
</ul>
|
|
145
|
+
|
|
146
|
+
{groups.map((group) => (
|
|
147
|
+
<SidebarGroupSection
|
|
148
|
+
key={group.slug}
|
|
149
|
+
group={group}
|
|
150
|
+
currentPath={location.pathname}
|
|
151
|
+
/>
|
|
152
|
+
))}
|
|
153
|
+
</nav>
|
|
154
|
+
{config.themeConfig?.poweredBy !== false && <PoweredBy />}
|
|
155
|
+
</>
|
|
156
|
+
)}
|
|
153
157
|
</aside>
|
|
154
158
|
);
|
|
155
159
|
}
|
|
@@ -29,80 +29,47 @@
|
|
|
29
29
|
|
|
30
30
|
/* ─── Collapsible Sidebar ────────────────────────────────── */
|
|
31
31
|
.boltdocs-main-container.sidebar-collapsed .boltdocs-sidebar {
|
|
32
|
-
width:
|
|
33
|
-
padding
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
pointer-events: none;
|
|
32
|
+
width: 54px;
|
|
33
|
+
padding: 1rem 0;
|
|
34
|
+
border-right: 1px solid var(--ld-border-subtle);
|
|
35
|
+
opacity: 1;
|
|
36
|
+
pointer-events: auto;
|
|
38
37
|
overflow: hidden;
|
|
39
38
|
}
|
|
40
39
|
|
|
41
|
-
.sidebar-
|
|
42
|
-
|
|
43
|
-
bottom: 2rem;
|
|
44
|
-
left: 2rem;
|
|
45
|
-
width: 2.75rem;
|
|
46
|
-
height: 2.75rem;
|
|
47
|
-
border-radius: 50%;
|
|
48
|
-
background-color: var(--ld-surface);
|
|
49
|
-
border: 1px solid var(--ld-border-strong);
|
|
50
|
-
color: var(--ld-text-muted);
|
|
40
|
+
.sidebar-collapse {
|
|
41
|
+
width: 100%;
|
|
51
42
|
display: flex;
|
|
52
43
|
align-items: center;
|
|
53
|
-
justify-content:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
57
|
-
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
|
58
|
-
opacity: 0;
|
|
59
|
-
pointer-events: none;
|
|
60
|
-
transform: translateY(20px) scale(0.9);
|
|
44
|
+
justify-content: flex-end;
|
|
45
|
+
padding: 0 0.75rem 1rem;
|
|
46
|
+
transition: justify-content 0.3s ease;
|
|
61
47
|
}
|
|
62
48
|
|
|
63
|
-
.sidebar-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
transform: translateY(0px) scale(1.05);
|
|
67
|
-
border-color: var(--ld-color-primary);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
.sidebar-toggle-floating:active {
|
|
71
|
-
transform: translateY(0px) scale(0.95);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
.boltdocs-main-container.sidebar-collapsed .sidebar-toggle-floating {
|
|
75
|
-
opacity: 1;
|
|
76
|
-
pointer-events: auto;
|
|
77
|
-
transform: translateY(0) scale(1);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
.sidebar-footer {
|
|
81
|
-
margin-top: 2rem;
|
|
82
|
-
padding-top: 1rem;
|
|
83
|
-
border-top: 1px solid var(--ld-border-subtle);
|
|
49
|
+
.boltdocs-main-container.sidebar-collapsed .sidebar-collapse {
|
|
50
|
+
justify-content: center;
|
|
51
|
+
padding: 0 0 1rem;
|
|
84
52
|
}
|
|
85
53
|
|
|
86
54
|
.sidebar-collapse-btn {
|
|
55
|
+
color: var(--ld-text-muted);
|
|
56
|
+
border: none;
|
|
57
|
+
box-shadow: none;
|
|
58
|
+
background-color: transparent;
|
|
59
|
+
cursor: pointer;
|
|
87
60
|
display: flex;
|
|
88
61
|
align-items: center;
|
|
89
|
-
|
|
90
|
-
width:
|
|
91
|
-
|
|
92
|
-
background: none;
|
|
93
|
-
border: none;
|
|
62
|
+
justify-content: center;
|
|
63
|
+
width: 32px;
|
|
64
|
+
height: 32px;
|
|
94
65
|
border-radius: var(--ld-radius-md);
|
|
95
|
-
|
|
96
|
-
font-family: var(--ld-font-sans);
|
|
97
|
-
font-size: 0.8125rem;
|
|
98
|
-
font-weight: 500;
|
|
99
|
-
cursor: pointer;
|
|
100
|
-
transition: all 0.2s ease;
|
|
66
|
+
transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1);
|
|
101
67
|
}
|
|
102
68
|
|
|
103
69
|
.sidebar-collapse-btn:hover {
|
|
104
|
-
background-color: var(--ld-bg-
|
|
105
|
-
color: var(--ld-
|
|
70
|
+
background-color: var(--ld-bg-mute);
|
|
71
|
+
color: var(--ld-text-main);
|
|
72
|
+
transform: scale(1.05);
|
|
106
73
|
}
|
|
107
74
|
|
|
108
75
|
.boltdocs-sidebar::-webkit-scrollbar {
|
|
@@ -2,7 +2,7 @@ import { useState, useRef, useEffect } from "react";
|
|
|
2
2
|
import { Layers, ChevronDown } from "lucide-react";
|
|
3
3
|
import { useNavigate, useLocation } from "react-router-dom";
|
|
4
4
|
import { BoltdocsVersionsConfig } from "../../../../node/config";
|
|
5
|
-
import { ComponentRoute } from "../../../
|
|
5
|
+
import { ComponentRoute } from "../../../types";
|
|
6
6
|
|
|
7
7
|
function getBaseFilePath(
|
|
8
8
|
filePath: string,
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Metadata provided by the server for a specific route.
|
|
5
|
+
* Maps closely to the `RouteMeta` type in the Node environment.
|
|
6
|
+
*/
|
|
7
|
+
export interface ComponentRoute {
|
|
8
|
+
/** The final URL path */
|
|
9
|
+
path: string;
|
|
10
|
+
/** The absolute filesystem path of the source file */
|
|
11
|
+
componentPath: string;
|
|
12
|
+
/** The page title */
|
|
13
|
+
title: string;
|
|
14
|
+
/** Explicit order in the sidebar */
|
|
15
|
+
sidebarPosition?: number;
|
|
16
|
+
/** The relative path from the docs directory */
|
|
17
|
+
filePath: string;
|
|
18
|
+
/** The group directory name */
|
|
19
|
+
group?: string;
|
|
20
|
+
/** The display title of the group */
|
|
21
|
+
groupTitle?: string;
|
|
22
|
+
/** Explicit order of the group in the sidebar */
|
|
23
|
+
groupPosition?: number;
|
|
24
|
+
/** Extracted markdown headings for search indexing */
|
|
25
|
+
headings?: { level: number; text: string; id: string }[];
|
|
26
|
+
/** The locale this route belongs to, if i18n is configured */
|
|
27
|
+
locale?: string;
|
|
28
|
+
/** The version this route belongs to, if versioning is configured */
|
|
29
|
+
version?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Configuration options for initializing the Boltdocs client app.
|
|
34
|
+
*/
|
|
35
|
+
export interface CreateBoltdocsAppOptions {
|
|
36
|
+
/** CSS selector for the DOM element where the app should mount (e.g. '#root') */
|
|
37
|
+
target: string;
|
|
38
|
+
/** Initial routes generated by the Vite plugin (`virtual:boltdocs-routes`) */
|
|
39
|
+
routes: ComponentRoute[];
|
|
40
|
+
/** Site configuration (`virtual:boltdocs-config`) */
|
|
41
|
+
config: any;
|
|
42
|
+
/** Dynamic import mapping from `import.meta.glob` for the documentation pages */
|
|
43
|
+
modules: Record<string, () => Promise<any>>;
|
|
44
|
+
/** The `import.meta.hot` instance necessary for fast refresh/HMR updates */
|
|
45
|
+
hot?: any;
|
|
46
|
+
/** Optional custom React component to render when visiting the root path ('/') */
|
|
47
|
+
homePage?: React.ComponentType;
|
|
48
|
+
/** Optional custom MDX components provided by plugins */
|
|
49
|
+
components?: Record<string, React.ComponentType<any>>;
|
|
50
|
+
}
|