@usecross/docs 0.11.0 → 0.12.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/index.d.ts +158 -5
- package/dist/index.js +1260 -31
- package/dist/index.js.map +1 -1
- package/dist/ssr.d.ts +1 -1
- package/dist/types-_anC1UJu.d.ts +320 -0
- package/package.json +1 -1
- package/src/components/Sidebar.tsx +171 -28
- package/src/components/TableOfContents.tsx +1 -1
- package/src/components/api/APILayout.tsx +231 -0
- package/src/components/api/APIPage.tsx +216 -0
- package/src/components/api/Breadcrumb.tsx +98 -0
- package/src/components/api/ClassDoc.tsx +257 -0
- package/src/components/api/CodeSpan.tsx +53 -0
- package/src/components/api/Docstring.tsx +269 -0
- package/src/components/api/FunctionDoc.tsx +130 -0
- package/src/components/api/ModuleDoc.tsx +298 -0
- package/src/components/api/ParameterTable.tsx +183 -0
- package/src/components/api/Signature.tsx +317 -0
- package/src/components/api/TableOfContents.tsx +50 -0
- package/src/components/api/index.ts +17 -0
- package/src/components/index.ts +12 -0
- package/src/index.ts +31 -0
- package/src/types.ts +218 -2
- package/dist/types-Qbhh2Ihz.d.ts +0 -136
package/dist/ssr.d.ts
CHANGED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Cross-Docs TypeScript type definitions
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** Single navigation item */
|
|
8
|
+
interface NavItem {
|
|
9
|
+
title: string;
|
|
10
|
+
href: string;
|
|
11
|
+
}
|
|
12
|
+
/** Navigation section containing multiple items */
|
|
13
|
+
interface NavSection {
|
|
14
|
+
title: string;
|
|
15
|
+
items: NavItem[];
|
|
16
|
+
}
|
|
17
|
+
/** Documentation set metadata (for multi-docs mode) */
|
|
18
|
+
interface DocSetMeta {
|
|
19
|
+
name: string;
|
|
20
|
+
slug: string;
|
|
21
|
+
description: string;
|
|
22
|
+
/** Emoji or short text icon (e.g., "🍓") */
|
|
23
|
+
icon?: string;
|
|
24
|
+
/** URL to icon image */
|
|
25
|
+
iconUrl?: string;
|
|
26
|
+
prefix: string;
|
|
27
|
+
}
|
|
28
|
+
/** Shared props passed to all pages via Inertia */
|
|
29
|
+
interface SharedProps {
|
|
30
|
+
nav: NavSection[];
|
|
31
|
+
currentPath: string;
|
|
32
|
+
/** Logo image URL (from Python backend) */
|
|
33
|
+
logoUrl?: string;
|
|
34
|
+
/** Logo image URL for dark/inverted contexts (from Python backend) */
|
|
35
|
+
logoInvertedUrl?: string;
|
|
36
|
+
/** Footer logo image URL (from Python backend) */
|
|
37
|
+
footerLogoUrl?: string;
|
|
38
|
+
/** Footer logo image URL for dark mode (from Python backend) */
|
|
39
|
+
footerLogoInvertedUrl?: string;
|
|
40
|
+
/** GitHub repository URL (from Python backend) */
|
|
41
|
+
githubUrl?: string;
|
|
42
|
+
/** Additional navigation links (from Python backend) */
|
|
43
|
+
navLinks?: Array<{
|
|
44
|
+
label: string;
|
|
45
|
+
href: string;
|
|
46
|
+
}>;
|
|
47
|
+
/** Available documentation sets (multi-docs mode) */
|
|
48
|
+
docSets?: DocSetMeta[];
|
|
49
|
+
/** Current documentation set slug (multi-docs mode) */
|
|
50
|
+
currentDocSet?: string;
|
|
51
|
+
}
|
|
52
|
+
/** Table of contents item */
|
|
53
|
+
interface TOCItem {
|
|
54
|
+
id: string;
|
|
55
|
+
/** Display text (use either text or title) */
|
|
56
|
+
text?: string;
|
|
57
|
+
/** Display title (use either text or title) */
|
|
58
|
+
title?: string;
|
|
59
|
+
level: number;
|
|
60
|
+
}
|
|
61
|
+
/** Document content structure */
|
|
62
|
+
interface DocContent {
|
|
63
|
+
title: string;
|
|
64
|
+
description: string;
|
|
65
|
+
body: string;
|
|
66
|
+
toc?: TOCItem[];
|
|
67
|
+
}
|
|
68
|
+
/** Props for DocsLayout component */
|
|
69
|
+
interface DocsLayoutProps {
|
|
70
|
+
children: ReactNode;
|
|
71
|
+
title: string;
|
|
72
|
+
description?: string;
|
|
73
|
+
/** Custom logo component (React node) */
|
|
74
|
+
logo?: ReactNode;
|
|
75
|
+
/** Custom logo for dark/inverted contexts (React node) */
|
|
76
|
+
logoInverted?: ReactNode;
|
|
77
|
+
/** Logo image URL (alternative to logo prop, can be passed from backend) */
|
|
78
|
+
logoUrl?: string;
|
|
79
|
+
/** Logo image URL for dark/inverted contexts */
|
|
80
|
+
logoInvertedUrl?: string;
|
|
81
|
+
/** GitHub repository URL (shows GitHub icon in nav) */
|
|
82
|
+
githubUrl?: string;
|
|
83
|
+
/** Additional navigation links */
|
|
84
|
+
navLinks?: Array<{
|
|
85
|
+
label: string;
|
|
86
|
+
href: string;
|
|
87
|
+
}>;
|
|
88
|
+
/** Custom header component (replaces entire header). Can be a ReactNode or a function that receives mobile menu props. */
|
|
89
|
+
header?: ReactNode | ((props: {
|
|
90
|
+
mobileMenuOpen: boolean;
|
|
91
|
+
toggleMobileMenu: () => void;
|
|
92
|
+
}) => ReactNode);
|
|
93
|
+
/** Header height in pixels. Used to calculate content offset. Defaults to 64 (h-16). */
|
|
94
|
+
headerHeight?: number;
|
|
95
|
+
/** Custom footer component */
|
|
96
|
+
footer?: ReactNode;
|
|
97
|
+
/** Table of contents items for the current page */
|
|
98
|
+
toc?: TOCItem[];
|
|
99
|
+
}
|
|
100
|
+
/** Props for TableOfContents component */
|
|
101
|
+
interface TableOfContentsProps {
|
|
102
|
+
items: TOCItem[];
|
|
103
|
+
className?: string;
|
|
104
|
+
style?: React.CSSProperties;
|
|
105
|
+
}
|
|
106
|
+
/** Props for Sidebar component */
|
|
107
|
+
interface SidebarProps {
|
|
108
|
+
nav: NavSection[];
|
|
109
|
+
currentPath: string;
|
|
110
|
+
className?: string;
|
|
111
|
+
/** Available documentation sets (multi-docs mode) */
|
|
112
|
+
docSets?: DocSetMeta[];
|
|
113
|
+
/** Current documentation set slug (multi-docs mode) */
|
|
114
|
+
currentDocSet?: string;
|
|
115
|
+
}
|
|
116
|
+
/** Props for Markdown component */
|
|
117
|
+
interface MarkdownProps {
|
|
118
|
+
content: string;
|
|
119
|
+
/** Override default markdown components */
|
|
120
|
+
components?: Record<string, React.ComponentType<any>>;
|
|
121
|
+
}
|
|
122
|
+
/** Props for CodeBlock component */
|
|
123
|
+
interface CodeBlockProps {
|
|
124
|
+
code: string;
|
|
125
|
+
language?: string;
|
|
126
|
+
filename?: string;
|
|
127
|
+
showLineNumbers?: boolean;
|
|
128
|
+
theme?: string;
|
|
129
|
+
className?: string;
|
|
130
|
+
}
|
|
131
|
+
/** Configuration for createDocsApp */
|
|
132
|
+
interface DocsAppConfig {
|
|
133
|
+
pages: Record<string, React.ComponentType<any>>;
|
|
134
|
+
title?: (pageTitle: string) => string;
|
|
135
|
+
/** Custom components to use in markdown (e.g., Alert, Card, etc.) */
|
|
136
|
+
components?: Record<string, React.ComponentType<any>>;
|
|
137
|
+
}
|
|
138
|
+
/** Griffe object kinds */
|
|
139
|
+
type GriffeKind = 'module' | 'class' | 'function' | 'attribute';
|
|
140
|
+
/** Griffe docstring section kinds */
|
|
141
|
+
type GriffeDocstringSectionKind = 'text' | 'parameters' | 'returns' | 'yields' | 'receives' | 'raises' | 'warns' | 'examples' | 'attributes' | 'other' | 'deprecated' | 'admonition';
|
|
142
|
+
/** Griffe expression (type annotation) */
|
|
143
|
+
interface GriffeExpression {
|
|
144
|
+
/** String representation of the expression */
|
|
145
|
+
str?: string;
|
|
146
|
+
/** Canonical string representation */
|
|
147
|
+
canonical?: string;
|
|
148
|
+
/** For name expressions */
|
|
149
|
+
name?: string;
|
|
150
|
+
/** For subscript expressions (e.g., List[int]) */
|
|
151
|
+
slice?: GriffeExpression;
|
|
152
|
+
/** For compound expressions */
|
|
153
|
+
left?: GriffeExpression;
|
|
154
|
+
right?: GriffeExpression;
|
|
155
|
+
}
|
|
156
|
+
/** Griffe parameter */
|
|
157
|
+
interface GriffeParameter {
|
|
158
|
+
name: string;
|
|
159
|
+
kind: 'positional-only' | 'positional-or-keyword' | 'var-positional' | 'keyword-only' | 'var-keyword';
|
|
160
|
+
annotation?: GriffeExpression | string;
|
|
161
|
+
default?: string;
|
|
162
|
+
}
|
|
163
|
+
/** Griffe docstring section element (for parameters, returns, etc.) */
|
|
164
|
+
interface GriffeDocstringElement {
|
|
165
|
+
name?: string;
|
|
166
|
+
annotation?: GriffeExpression | string;
|
|
167
|
+
description?: string;
|
|
168
|
+
value?: string;
|
|
169
|
+
}
|
|
170
|
+
/** Griffe docstring section */
|
|
171
|
+
interface GriffeDocstringSection {
|
|
172
|
+
kind: GriffeDocstringSectionKind;
|
|
173
|
+
value?: string | GriffeDocstringElement[];
|
|
174
|
+
title?: string;
|
|
175
|
+
}
|
|
176
|
+
/** Griffe parsed docstring */
|
|
177
|
+
interface GriffeDocstring {
|
|
178
|
+
value: string;
|
|
179
|
+
parsed?: GriffeDocstringSection[];
|
|
180
|
+
}
|
|
181
|
+
/** Griffe decorator */
|
|
182
|
+
interface GriffeDecorator {
|
|
183
|
+
value: string;
|
|
184
|
+
lineno?: number;
|
|
185
|
+
}
|
|
186
|
+
/** Base Griffe object with common properties */
|
|
187
|
+
interface GriffeObjectBase {
|
|
188
|
+
kind: GriffeKind;
|
|
189
|
+
name: string;
|
|
190
|
+
path?: string;
|
|
191
|
+
filepath?: string;
|
|
192
|
+
/** Relative file path (set by cross-docs) */
|
|
193
|
+
relative_filepath?: string;
|
|
194
|
+
/** Relative file path within the package (set by Griffe) */
|
|
195
|
+
relative_package_filepath?: string;
|
|
196
|
+
lineno?: number;
|
|
197
|
+
endlineno?: number;
|
|
198
|
+
docstring?: GriffeDocstring;
|
|
199
|
+
labels?: string[];
|
|
200
|
+
}
|
|
201
|
+
/** Griffe function/method */
|
|
202
|
+
interface GriffeFunction extends GriffeObjectBase {
|
|
203
|
+
kind: 'function';
|
|
204
|
+
parameters?: GriffeParameter[];
|
|
205
|
+
returns?: GriffeExpression | string;
|
|
206
|
+
decorators?: GriffeDecorator[];
|
|
207
|
+
/** Whether this is an async function */
|
|
208
|
+
is_async?: boolean;
|
|
209
|
+
}
|
|
210
|
+
/** Griffe attribute */
|
|
211
|
+
interface GriffeAttribute extends GriffeObjectBase {
|
|
212
|
+
kind: 'attribute';
|
|
213
|
+
annotation?: GriffeExpression | string;
|
|
214
|
+
value?: string;
|
|
215
|
+
}
|
|
216
|
+
/** Griffe class */
|
|
217
|
+
interface GriffeClass extends GriffeObjectBase {
|
|
218
|
+
kind: 'class';
|
|
219
|
+
bases?: Array<GriffeExpression | string>;
|
|
220
|
+
decorators?: GriffeDecorator[];
|
|
221
|
+
members?: Record<string, GriffeMember>;
|
|
222
|
+
}
|
|
223
|
+
/** Griffe module */
|
|
224
|
+
interface GriffeModule extends GriffeObjectBase {
|
|
225
|
+
kind: 'module';
|
|
226
|
+
members?: Record<string, GriffeMember>;
|
|
227
|
+
/** Generator metadata added by cross-docs */
|
|
228
|
+
_generator?: string;
|
|
229
|
+
_plugin?: string;
|
|
230
|
+
_version?: string;
|
|
231
|
+
}
|
|
232
|
+
/** Griffe alias (re-export) */
|
|
233
|
+
interface GriffeAlias {
|
|
234
|
+
kind: 'alias';
|
|
235
|
+
name: string;
|
|
236
|
+
path?: string;
|
|
237
|
+
/** The target path this alias points to */
|
|
238
|
+
target_path: string;
|
|
239
|
+
lineno?: number;
|
|
240
|
+
endlineno?: number;
|
|
241
|
+
}
|
|
242
|
+
/** Union of all Griffe member types */
|
|
243
|
+
type GriffeMember = GriffeModule | GriffeClass | GriffeFunction | GriffeAttribute | GriffeAlias;
|
|
244
|
+
/** Props for API documentation pages */
|
|
245
|
+
interface APIPageProps {
|
|
246
|
+
/** Full API data (the entire module tree) */
|
|
247
|
+
apiData: GriffeModule;
|
|
248
|
+
/** Current item being viewed (module, class, or function) */
|
|
249
|
+
currentItem?: GriffeMember;
|
|
250
|
+
/** Current URL path */
|
|
251
|
+
currentPath: string;
|
|
252
|
+
/** Current module name */
|
|
253
|
+
currentModule: string;
|
|
254
|
+
/** Navigation structure for API sidebar */
|
|
255
|
+
apiNav: NavSection[];
|
|
256
|
+
/** URL prefix for API links (e.g., /docs/api-reference) */
|
|
257
|
+
prefix: string;
|
|
258
|
+
/** Logo URL */
|
|
259
|
+
logoUrl?: string;
|
|
260
|
+
/** Logo URL for dark mode */
|
|
261
|
+
logoInvertedUrl?: string;
|
|
262
|
+
/** Footer logo URL */
|
|
263
|
+
footerLogoUrl?: string;
|
|
264
|
+
/** Footer logo URL for dark mode */
|
|
265
|
+
footerLogoInvertedUrl?: string;
|
|
266
|
+
/** GitHub URL */
|
|
267
|
+
githubUrl?: string;
|
|
268
|
+
/** Navigation links */
|
|
269
|
+
navLinks?: Array<{
|
|
270
|
+
label: string;
|
|
271
|
+
href: string;
|
|
272
|
+
}>;
|
|
273
|
+
/** Custom header component (replaces entire header). Can be a ReactNode or a function that receives mobile menu props. */
|
|
274
|
+
header?: React.ReactNode | ((props: {
|
|
275
|
+
mobileMenuOpen: boolean;
|
|
276
|
+
toggleMobileMenu: () => void;
|
|
277
|
+
}) => React.ReactNode);
|
|
278
|
+
/** Header height in pixels. Used to calculate content offset. Defaults to 64 (h-16). */
|
|
279
|
+
headerHeight?: number;
|
|
280
|
+
/** Custom footer component */
|
|
281
|
+
footer?: React.ReactNode;
|
|
282
|
+
}
|
|
283
|
+
/** Props for ModuleDoc component */
|
|
284
|
+
interface ModuleDocProps {
|
|
285
|
+
module: GriffeModule;
|
|
286
|
+
/** URL prefix for links */
|
|
287
|
+
prefix?: string;
|
|
288
|
+
}
|
|
289
|
+
/** Props for ClassDoc component */
|
|
290
|
+
interface ClassDocProps {
|
|
291
|
+
cls: GriffeClass;
|
|
292
|
+
/** URL prefix for links */
|
|
293
|
+
prefix?: string;
|
|
294
|
+
}
|
|
295
|
+
/** Props for FunctionDoc component */
|
|
296
|
+
interface FunctionDocProps {
|
|
297
|
+
fn: GriffeFunction;
|
|
298
|
+
/** Whether this is a method (inside a class) */
|
|
299
|
+
isMethod?: boolean;
|
|
300
|
+
}
|
|
301
|
+
/** Props for Signature component */
|
|
302
|
+
interface SignatureProps {
|
|
303
|
+
fn: GriffeFunction;
|
|
304
|
+
/** Show full path or just name */
|
|
305
|
+
showPath?: boolean;
|
|
306
|
+
}
|
|
307
|
+
/** Props for Docstring component */
|
|
308
|
+
interface DocstringProps {
|
|
309
|
+
docstring: GriffeDocstring;
|
|
310
|
+
/** Show raw text instead of parsed sections */
|
|
311
|
+
raw?: boolean;
|
|
312
|
+
}
|
|
313
|
+
/** Props for ParameterTable component */
|
|
314
|
+
interface ParameterTableProps {
|
|
315
|
+
parameters: GriffeParameter[];
|
|
316
|
+
/** Docstring sections for parameter descriptions */
|
|
317
|
+
docstringSections?: GriffeDocstringSection[];
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export type { APIPageProps as A, CodeBlockProps as C, DocSetMeta as D, FunctionDocProps as F, GriffeModule as G, MarkdownProps as M, NavSection as N, ParameterTableProps as P, SidebarProps as S, TableOfContentsProps as T, DocsLayoutProps as a, DocContent as b, GriffeClass as c, GriffeFunction as d, GriffeDocstring as e, GriffeParameter as f, GriffeDocstringSection as g, DocsAppConfig as h, NavItem as i, SharedProps as j, TOCItem as k, GriffeKind as l, GriffeDocstringSectionKind as m, GriffeExpression as n, GriffeDocstringElement as o, GriffeDecorator as p, GriffeObjectBase as q, GriffeAttribute as r, GriffeMember as s, ModuleDocProps as t, ClassDocProps as u, SignatureProps as v, DocstringProps as w };
|
package/package.json
CHANGED
|
@@ -1,13 +1,151 @@
|
|
|
1
|
+
import { useState } from 'react'
|
|
1
2
|
import { Link } from '@inertiajs/react'
|
|
2
3
|
import { cn } from '../lib/utils'
|
|
3
4
|
import { DocSetSelector } from './DocSetSelector'
|
|
4
|
-
import type { SidebarProps } from '../types'
|
|
5
|
+
import type { SidebarProps, NavSection } from '../types'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Chevron icon for collapsible sections
|
|
9
|
+
*/
|
|
10
|
+
function ChevronIcon({ expanded, className }: { expanded: boolean; className?: string }) {
|
|
11
|
+
return (
|
|
12
|
+
<svg
|
|
13
|
+
className={cn('w-4 h-4 transition-transform duration-200', expanded && 'rotate-90', className)}
|
|
14
|
+
fill="none"
|
|
15
|
+
viewBox="0 0 24 24"
|
|
16
|
+
stroke="currentColor"
|
|
17
|
+
>
|
|
18
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
|
19
|
+
</svg>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Collapsible navigation section
|
|
25
|
+
*/
|
|
26
|
+
function CollapsibleSection({
|
|
27
|
+
section,
|
|
28
|
+
currentPath,
|
|
29
|
+
defaultExpanded = true,
|
|
30
|
+
compact = false,
|
|
31
|
+
}: {
|
|
32
|
+
section: NavSection
|
|
33
|
+
currentPath: string
|
|
34
|
+
defaultExpanded?: boolean
|
|
35
|
+
compact?: boolean
|
|
36
|
+
}) {
|
|
37
|
+
// Check if current path is in this section
|
|
38
|
+
const isActive = section.items.some(
|
|
39
|
+
(item) => currentPath === item.href || currentPath + '/' === item.href
|
|
40
|
+
)
|
|
41
|
+
const [expanded, setExpanded] = useState(defaultExpanded || isActive)
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<div>
|
|
45
|
+
<button
|
|
46
|
+
onClick={() => setExpanded(!expanded)}
|
|
47
|
+
className="w-full flex items-center justify-between mb-2 group"
|
|
48
|
+
>
|
|
49
|
+
<h3 className={cn(
|
|
50
|
+
'text-sm font-mono uppercase tracking-widest text-gray-500 dark:text-gray-400',
|
|
51
|
+
'group-hover:text-gray-700 dark:group-hover:text-gray-300 transition-colors'
|
|
52
|
+
)}>
|
|
53
|
+
{section.title}
|
|
54
|
+
</h3>
|
|
55
|
+
<ChevronIcon expanded={expanded} className="text-gray-400 dark:text-gray-500" />
|
|
56
|
+
</button>
|
|
57
|
+
{expanded && (
|
|
58
|
+
<ul className={cn(
|
|
59
|
+
'border-l-2 border-gray-200 dark:border-gray-700',
|
|
60
|
+
compact ? 'space-y-0.5' : 'space-y-1.5'
|
|
61
|
+
)}>
|
|
62
|
+
{section.items.map((item) => (
|
|
63
|
+
<li key={item.href}>
|
|
64
|
+
<Link
|
|
65
|
+
href={item.href}
|
|
66
|
+
className={cn(
|
|
67
|
+
'block border-l-2 py-1 pl-4 leading-snug transition-colors -ml-0.5',
|
|
68
|
+
compact ? 'text-sm' : 'text-[15px]',
|
|
69
|
+
currentPath === item.href || currentPath + '/' === item.href
|
|
70
|
+
? 'border-primary-500 text-gray-900 dark:text-white font-semibold'
|
|
71
|
+
: 'border-transparent text-gray-600 dark:text-gray-400 hover:border-primary-300 dark:hover:border-primary-400 hover:text-gray-900 dark:hover:text-white'
|
|
72
|
+
)}
|
|
73
|
+
>
|
|
74
|
+
{item.title}
|
|
75
|
+
</Link>
|
|
76
|
+
</li>
|
|
77
|
+
))}
|
|
78
|
+
</ul>
|
|
79
|
+
)}
|
|
80
|
+
</div>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Static navigation section (non-collapsible)
|
|
86
|
+
*/
|
|
87
|
+
function StaticSection({
|
|
88
|
+
section,
|
|
89
|
+
currentPath,
|
|
90
|
+
compact = false,
|
|
91
|
+
}: {
|
|
92
|
+
section: NavSection
|
|
93
|
+
currentPath: string
|
|
94
|
+
compact?: boolean
|
|
95
|
+
}) {
|
|
96
|
+
return (
|
|
97
|
+
<div>
|
|
98
|
+
<h3 className="mb-3 text-sm font-mono uppercase tracking-widest text-gray-500 dark:text-gray-400">
|
|
99
|
+
{section.title}
|
|
100
|
+
</h3>
|
|
101
|
+
<ul className={cn(
|
|
102
|
+
'border-l-2 border-gray-200 dark:border-gray-700',
|
|
103
|
+
compact ? 'space-y-0.5' : 'space-y-1.5'
|
|
104
|
+
)}>
|
|
105
|
+
{section.items.map((item) => (
|
|
106
|
+
<li key={item.href}>
|
|
107
|
+
<Link
|
|
108
|
+
href={item.href}
|
|
109
|
+
className={cn(
|
|
110
|
+
'block border-l-2 py-1 pl-4 leading-snug transition-colors -ml-0.5',
|
|
111
|
+
compact ? 'text-sm' : 'text-[15px]',
|
|
112
|
+
currentPath === item.href || currentPath + '/' === item.href
|
|
113
|
+
? 'border-primary-500 text-gray-900 dark:text-white font-semibold'
|
|
114
|
+
: 'border-transparent text-gray-600 dark:text-gray-400 hover:border-primary-300 dark:hover:border-primary-400 hover:text-gray-900 dark:hover:text-white'
|
|
115
|
+
)}
|
|
116
|
+
>
|
|
117
|
+
{item.title}
|
|
118
|
+
</Link>
|
|
119
|
+
</li>
|
|
120
|
+
))}
|
|
121
|
+
</ul>
|
|
122
|
+
</div>
|
|
123
|
+
)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export interface ExtendedSidebarProps extends SidebarProps {
|
|
127
|
+
/** Use compact styling (smaller text) */
|
|
128
|
+
compact?: boolean
|
|
129
|
+
/** Make sections collapsible */
|
|
130
|
+
collapsible?: boolean
|
|
131
|
+
/** Collapse sections with more than N items by default */
|
|
132
|
+
collapseThreshold?: number
|
|
133
|
+
}
|
|
5
134
|
|
|
6
135
|
/**
|
|
7
136
|
* Documentation sidebar with section-based navigation.
|
|
8
|
-
*
|
|
137
|
+
* Supports both docs and API navigation styles.
|
|
9
138
|
*/
|
|
10
|
-
export function Sidebar({
|
|
139
|
+
export function Sidebar({
|
|
140
|
+
nav,
|
|
141
|
+
currentPath,
|
|
142
|
+
className,
|
|
143
|
+
docSets,
|
|
144
|
+
currentDocSet,
|
|
145
|
+
compact = false,
|
|
146
|
+
collapsible = false,
|
|
147
|
+
collapseThreshold = 10,
|
|
148
|
+
}: ExtendedSidebarProps) {
|
|
11
149
|
return (
|
|
12
150
|
<nav className={cn('space-y-6', className)}>
|
|
13
151
|
{/* Doc Set Selector - only shown in multi-docs mode */}
|
|
@@ -16,31 +154,36 @@ export function Sidebar({ nav, currentPath, className, docSets, currentDocSet }:
|
|
|
16
154
|
)}
|
|
17
155
|
|
|
18
156
|
{/* Navigation Sections */}
|
|
19
|
-
<div className=
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
157
|
+
<div className={compact ? 'space-y-4' : 'space-y-6'}>
|
|
158
|
+
{nav.map((section) => {
|
|
159
|
+
// Determine if this section should be collapsible
|
|
160
|
+
const shouldCollapse = collapsible && section.items.length > collapseThreshold
|
|
161
|
+
// Check if current path is in this section
|
|
162
|
+
const isActive = section.items.some(
|
|
163
|
+
(item) => currentPath === item.href || currentPath + '/' === item.href
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
if (shouldCollapse) {
|
|
167
|
+
return (
|
|
168
|
+
<CollapsibleSection
|
|
169
|
+
key={section.title}
|
|
170
|
+
section={section}
|
|
171
|
+
currentPath={currentPath}
|
|
172
|
+
defaultExpanded={isActive}
|
|
173
|
+
compact={compact}
|
|
174
|
+
/>
|
|
175
|
+
)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return (
|
|
179
|
+
<StaticSection
|
|
180
|
+
key={section.title}
|
|
181
|
+
section={section}
|
|
182
|
+
currentPath={currentPath}
|
|
183
|
+
compact={compact}
|
|
184
|
+
/>
|
|
185
|
+
)
|
|
186
|
+
})}
|
|
44
187
|
</div>
|
|
45
188
|
</nav>
|
|
46
189
|
)
|
|
@@ -169,7 +169,7 @@ export function TableOfContents({ items, className = '', ...props }: TableOfCont
|
|
|
169
169
|
: 'border-transparent text-gray-600 dark:text-gray-300 hover:border-primary-300 dark:hover:border-primary-400 hover:text-gray-900 dark:hover:text-white'
|
|
170
170
|
}`}
|
|
171
171
|
>
|
|
172
|
-
{item.text}
|
|
172
|
+
{item.text || item.title}
|
|
173
173
|
</a>
|
|
174
174
|
</li>
|
|
175
175
|
)
|