@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/ssr.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { c as DocsAppConfig } from './types-Qbhh2Ihz.js';
1
+ import { h as DocsAppConfig } from './types-_anC1UJu.js';
2
2
  import 'react';
3
3
 
4
4
  /**
@@ -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,6 +1,6 @@
1
1
  {
2
2
  "name": "@usecross/docs",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Documentation framework built on Cross-Inertia",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -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
- * In multi-docs mode, includes a dropdown selector at the top.
137
+ * Supports both docs and API navigation styles.
9
138
  */
10
- export function Sidebar({ nav, currentPath, className, docSets, currentDocSet }: SidebarProps) {
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="space-y-8">
20
- {nav.map((section) => (
21
- <div key={section.title}>
22
- <h3 className="mb-3 text-sm font-mono uppercase tracking-widest text-gray-500 dark:text-gray-400">
23
- {section.title}
24
- </h3>
25
- <ul className="space-y-1.5 border-l-2 border-gray-200 dark:border-gray-700">
26
- {section.items.map((item) => (
27
- <li key={item.href}>
28
- <Link
29
- href={item.href}
30
- className={cn(
31
- 'block border-l-2 py-1 pl-4 text-[17px] leading-snug transition-colors -ml-0.5',
32
- currentPath === item.href
33
- ? 'border-primary-500 text-gray-900 dark:text-white font-bold'
34
- : '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'
35
- )}
36
- >
37
- {item.title}
38
- </Link>
39
- </li>
40
- ))}
41
- </ul>
42
- </div>
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
  )