@usecross/docs 0.10.2 → 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.
@@ -0,0 +1,183 @@
1
+ import type { GriffeParameter, GriffeDocstringSection, GriffeDocstringElement, GriffeExpression } from '../../types'
2
+ import { CodeSpan } from './CodeSpan'
3
+
4
+ /**
5
+ * Render a type annotation expression to string
6
+ */
7
+ function renderExpression(expr: GriffeExpression | string | undefined): string {
8
+ if (!expr) return ''
9
+ if (typeof expr === 'string') return expr
10
+ if (expr.str) return expr.str
11
+ if (expr.canonical) return expr.canonical
12
+
13
+ const exprAny = expr as any
14
+
15
+ // Handle ExprName with member reference
16
+ if (expr.name && typeof expr.name === 'string') return expr.name
17
+
18
+ // Handle ExprBoolOp (like `config or StrawberryConfig()`)
19
+ if (exprAny.cls === 'ExprBoolOp' && exprAny.operator && Array.isArray(exprAny.values)) {
20
+ return exprAny.values.map((v: any) => renderExpression(v)).join(` ${exprAny.operator} `)
21
+ }
22
+
23
+ // Handle ExprBinOp (like `type | None`)
24
+ if (exprAny.cls === 'ExprBinOp' && exprAny.left && exprAny.right) {
25
+ const left = renderExpression(exprAny.left)
26
+ const right = renderExpression(exprAny.right)
27
+ const op = exprAny.operator || '|'
28
+ return `${left} ${op} ${right}`
29
+ }
30
+
31
+ // Handle ExprCall (like `StrawberryConfig()`)
32
+ if (exprAny.cls === 'ExprCall' && exprAny.function) {
33
+ const funcName = renderExpression(exprAny.function)
34
+ const args = Array.isArray(exprAny.arguments)
35
+ ? exprAny.arguments.map((a: any) => renderExpression(a)).join(', ')
36
+ : ''
37
+ return `${funcName}(${args})`
38
+ }
39
+
40
+ // Handle ExprAttribute (like contextlib.asynccontextmanager)
41
+ if (exprAny.cls === 'ExprAttribute' && Array.isArray(exprAny.values)) {
42
+ return exprAny.values.map((v: any) => renderExpression(v)).join('.')
43
+ }
44
+
45
+ // Handle ExprList and ExprTuple
46
+ if ('elements' in exprAny && Array.isArray(exprAny.elements)) {
47
+ const inner = exprAny.elements.map((el: any) => renderExpression(el)).join(', ')
48
+ return exprAny.cls === 'ExprTuple' ? `(${inner})` : `[${inner}]`
49
+ }
50
+
51
+ // Handle ExprDict
52
+ if (exprAny.cls === 'ExprDict' && Array.isArray(exprAny.keys) && Array.isArray(exprAny.values)) {
53
+ const pairs = exprAny.keys.map((k: any, i: number) =>
54
+ `${renderExpression(k)}: ${renderExpression(exprAny.values[i])}`
55
+ ).join(', ')
56
+ return `{${pairs}}`
57
+ }
58
+
59
+ // Handle ExprSubscript (like Dict[str, int])
60
+ if (exprAny.left && exprAny.slice) {
61
+ const left = renderExpression(exprAny.left)
62
+ const slice = renderExpression(exprAny.slice)
63
+ return `${left}[${slice}]`
64
+ }
65
+
66
+ // Handle slice expressions
67
+ if ('slice' in exprAny && exprAny.slice && !exprAny.left) {
68
+ return renderExpression(exprAny.slice)
69
+ }
70
+
71
+ // Fallback for unknown expressions
72
+ if (typeof expr === 'object') {
73
+ return JSON.stringify(expr)
74
+ }
75
+
76
+ return String(expr)
77
+ }
78
+
79
+ /**
80
+ * Get parameter description from docstring sections
81
+ */
82
+ function getParamDescription(
83
+ paramName: string,
84
+ docstringSections?: GriffeDocstringSection[]
85
+ ): string | undefined {
86
+ if (!docstringSections) return undefined
87
+
88
+ for (const section of docstringSections) {
89
+ if (section.kind === 'parameters' && Array.isArray(section.value)) {
90
+ const param = (section.value as GriffeDocstringElement[]).find(
91
+ (p) => p.name === paramName
92
+ )
93
+ if (param) return param.description
94
+ }
95
+ }
96
+ return undefined
97
+ }
98
+
99
+ interface ParameterTableProps {
100
+ parameters: GriffeParameter[]
101
+ /** Docstring sections for parameter descriptions */
102
+ docstringSections?: GriffeDocstringSection[]
103
+ /** Additional CSS class */
104
+ className?: string
105
+ }
106
+
107
+ /**
108
+ * Renders a two-column parameter list matching strawberry.rocks design.
109
+ * Left column: parameter name badge
110
+ * Right column: description, type, and default value
111
+ */
112
+ export function ParameterTable({ parameters, docstringSections, className = '' }: ParameterTableProps) {
113
+ if (!parameters || parameters.length === 0) return null
114
+
115
+ // Filter out 'self' parameter for cleaner display
116
+ const displayParams = parameters.filter(p => p.name !== 'self')
117
+
118
+ if (displayParams.length === 0) return null
119
+
120
+ return (
121
+ <ol className={`list-none p-0 ${className}`}>
122
+ {displayParams.map((param, index) => {
123
+ const description = getParamDescription(param.name, docstringSections)
124
+ const annotation = renderExpression(param.annotation)
125
+ const defaultValue = renderExpression(param.default)
126
+ const isLast = index === displayParams.length - 1
127
+
128
+ return (
129
+ <li
130
+ key={param.name}
131
+ className="contents"
132
+ >
133
+ <div className={`grid grid-cols-[max-content_1fr] items-baseline gap-x-8 gap-y-2 py-6 ${!isLast ? 'border-b border-gray-200 dark:border-gray-700' : ''}`}>
134
+ {/* Parameter name badge - left column */}
135
+ <div className="flex-shrink-0">
136
+ <CodeSpan>
137
+ {param.kind === 'var-positional' && '*'}
138
+ {param.kind === 'var-keyword' && '**'}
139
+ {param.name}:
140
+ </CodeSpan>
141
+ </div>
142
+
143
+ {/* Description and metadata - right column */}
144
+ <div className="space-y-3">
145
+ {/* Description */}
146
+ {description && (
147
+ <p className="text-gray-700 dark:text-gray-300 leading-relaxed">
148
+ {description}
149
+ </p>
150
+ )}
151
+
152
+ {/* Type and Default in definition list style */}
153
+ <dl className="grid grid-cols-[auto_1fr] gap-x-4 gap-y-2">
154
+ {annotation && (
155
+ <>
156
+ <dt className="font-semibold text-gray-500 dark:text-gray-400">
157
+ Type
158
+ </dt>
159
+ <dd className="m-0">
160
+ <CodeSpan>{annotation}</CodeSpan>
161
+ </dd>
162
+ </>
163
+ )}
164
+
165
+ {defaultValue && (
166
+ <>
167
+ <dt className="font-semibold text-gray-500 dark:text-gray-400">
168
+ Default
169
+ </dt>
170
+ <dd className="m-0">
171
+ <CodeSpan>{defaultValue}</CodeSpan>
172
+ </dd>
173
+ </>
174
+ )}
175
+ </dl>
176
+ </div>
177
+ </div>
178
+ </li>
179
+ )
180
+ })}
181
+ </ol>
182
+ )
183
+ }
@@ -0,0 +1,317 @@
1
+ import { useState } from 'react'
2
+ import type { GriffeFunction, GriffeParameter, GriffeExpression } from '../../types'
3
+
4
+ /**
5
+ * Render a type annotation expression to string
6
+ */
7
+ function renderExpression(expr: GriffeExpression | string | undefined): string {
8
+ if (!expr) return ''
9
+ if (typeof expr === 'string') return expr
10
+ if (expr.str) return expr.str
11
+ if (expr.canonical) return expr.canonical
12
+
13
+ const exprAny = expr as any
14
+
15
+ // Handle ExprName with member reference
16
+ if (expr.name && typeof expr.name === 'string') return expr.name
17
+
18
+ // Handle ExprBoolOp (like `config or StrawberryConfig()`)
19
+ if (exprAny.cls === 'ExprBoolOp' && exprAny.operator && Array.isArray(exprAny.values)) {
20
+ return exprAny.values.map((v: any) => renderExpression(v)).join(` ${exprAny.operator} `)
21
+ }
22
+
23
+ // Handle ExprBinOp (like `type | None`)
24
+ if (exprAny.cls === 'ExprBinOp' && exprAny.left && exprAny.right) {
25
+ const left = renderExpression(exprAny.left)
26
+ const right = renderExpression(exprAny.right)
27
+ const op = exprAny.operator || '|'
28
+ return `${left} ${op} ${right}`
29
+ }
30
+
31
+ // Handle ExprCall (like `StrawberryConfig()`)
32
+ if (exprAny.cls === 'ExprCall' && exprAny.function) {
33
+ const funcName = renderExpression(exprAny.function)
34
+ const args = Array.isArray(exprAny.arguments)
35
+ ? exprAny.arguments.map((a: any) => renderExpression(a)).join(', ')
36
+ : ''
37
+ return `${funcName}(${args})`
38
+ }
39
+
40
+ // Handle ExprAttribute (like contextlib.asynccontextmanager)
41
+ if (exprAny.cls === 'ExprAttribute' && Array.isArray(exprAny.values)) {
42
+ return exprAny.values.map((v: any) => renderExpression(v)).join('.')
43
+ }
44
+
45
+ // Handle ExprList and ExprTuple
46
+ if ('elements' in exprAny && Array.isArray(exprAny.elements)) {
47
+ const inner = exprAny.elements.map((el: any) => renderExpression(el)).join(', ')
48
+ return exprAny.cls === 'ExprTuple' ? `(${inner})` : `[${inner}]`
49
+ }
50
+
51
+ // Handle ExprDict
52
+ if (exprAny.cls === 'ExprDict' && Array.isArray(exprAny.keys) && Array.isArray(exprAny.values)) {
53
+ const pairs = exprAny.keys.map((k: any, i: number) =>
54
+ `${renderExpression(k)}: ${renderExpression(exprAny.values[i])}`
55
+ ).join(', ')
56
+ return `{${pairs}}`
57
+ }
58
+
59
+ // Handle ExprSubscript (like Dict[str, int])
60
+ if (exprAny.left && exprAny.slice) {
61
+ const left = renderExpression(exprAny.left)
62
+ const slice = renderExpression(exprAny.slice)
63
+ return `${left}[${slice}]`
64
+ }
65
+
66
+ // Handle slice expressions
67
+ if ('slice' in exprAny && exprAny.slice && !exprAny.left) {
68
+ return renderExpression(exprAny.slice)
69
+ }
70
+
71
+ // Fallback for unknown expressions
72
+ if (typeof expr === 'object') {
73
+ return JSON.stringify(expr)
74
+ }
75
+
76
+ return String(expr)
77
+ }
78
+
79
+ /**
80
+ * Render a parameter with its type annotation and default value
81
+ */
82
+ function renderParameter(param: GriffeParameter): string {
83
+ let result = ''
84
+
85
+ // Handle special parameter kinds
86
+ if (param.kind === 'var-positional') {
87
+ result = `*${param.name}`
88
+ } else if (param.kind === 'var-keyword') {
89
+ result = `**${param.name}`
90
+ } else {
91
+ result = param.name
92
+ }
93
+
94
+ // Add type annotation
95
+ if (param.annotation) {
96
+ const annotation = renderExpression(param.annotation)
97
+ if (annotation) {
98
+ result += `: ${annotation}`
99
+ }
100
+ }
101
+
102
+ // Add default value
103
+ if (param.default) {
104
+ result += ` = ${renderExpression(param.default)}`
105
+ }
106
+
107
+ return result
108
+ }
109
+
110
+ /**
111
+ * Copy icon component
112
+ */
113
+ function CopyIcon() {
114
+ return (
115
+ <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
116
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
117
+ </svg>
118
+ )
119
+ }
120
+
121
+ /**
122
+ * Check icon component
123
+ */
124
+ function CheckIcon() {
125
+ return (
126
+ <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
127
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
128
+ </svg>
129
+ )
130
+ }
131
+
132
+ interface SignatureProps {
133
+ fn: GriffeFunction
134
+ /** Show full path or just function name */
135
+ showPath?: boolean
136
+ /** Additional CSS class */
137
+ className?: string
138
+ }
139
+
140
+ /**
141
+ * Renders a Python function/method signature with syntax highlighting.
142
+ * Uses dark background style matching strawberry.rocks.
143
+ */
144
+ export function Signature({ fn, showPath = false, className = '' }: SignatureProps) {
145
+ const [copied, setCopied] = useState(false)
146
+ const name = showPath && fn.path ? fn.path : fn.name
147
+ const isAsync = fn.is_async
148
+
149
+ // Filter out 'self' for cleaner display
150
+ const displayParams = fn.parameters?.filter(p => p.name !== 'self') ?? []
151
+
152
+ // Render return type
153
+ const returnType = renderExpression(fn.returns)
154
+
155
+ // Build parameter string with proper separators for positional-only and keyword-only
156
+ const buildParamString = (params: GriffeParameter[]): string => {
157
+ const parts: string[] = []
158
+ const hasVarPositional = params.some(p => p.kind === 'var-positional')
159
+ let addedBareAsterisk = false
160
+
161
+ for (let i = 0; i < params.length; i++) {
162
+ const param = params[i]
163
+ const nextParam = params[i + 1]
164
+
165
+ // Add the parameter itself
166
+ parts.push(renderParameter(param))
167
+
168
+ // Add / after last positional-only parameter
169
+ if (param.kind === 'positional-only' && nextParam && nextParam.kind !== 'positional-only') {
170
+ parts.push('/')
171
+ }
172
+
173
+ // Add bare * before first keyword-only parameter (if no *args)
174
+ if (!hasVarPositional && !addedBareAsterisk && nextParam?.kind === 'keyword-only' && param.kind !== 'keyword-only') {
175
+ parts.push('*')
176
+ addedBareAsterisk = true
177
+ }
178
+ }
179
+
180
+ return parts.join(', ')
181
+ }
182
+
183
+ // Build the plain text signature for copying
184
+ const plainSignature = (() => {
185
+ const params = buildParamString(displayParams)
186
+ const prefix = isAsync ? 'async def ' : 'def '
187
+ return returnType
188
+ ? `${prefix}${name}(${params}) -> ${returnType}`
189
+ : `${prefix}${name}(${params})`
190
+ })()
191
+
192
+ const handleCopy = async () => {
193
+ await navigator.clipboard.writeText(plainSignature)
194
+ setCopied(true)
195
+ setTimeout(() => setCopied(false), 2000)
196
+ }
197
+
198
+ // Build list of parameter tokens (params + separators like / and *)
199
+ type ParamToken = { type: 'param'; param: GriffeParameter } | { type: 'separator'; value: '/' | '*' }
200
+ const buildParamTokens = (params: GriffeParameter[]): ParamToken[] => {
201
+ const tokens: ParamToken[] = []
202
+ const hasVarPositional = params.some(p => p.kind === 'var-positional')
203
+ let addedBareAsterisk = false
204
+
205
+ for (let i = 0; i < params.length; i++) {
206
+ const param = params[i]
207
+ const nextParam = params[i + 1]
208
+
209
+ tokens.push({ type: 'param', param })
210
+
211
+ // Add / after last positional-only parameter
212
+ if (param.kind === 'positional-only' && nextParam && nextParam.kind !== 'positional-only') {
213
+ tokens.push({ type: 'separator', value: '/' })
214
+ }
215
+
216
+ // Add bare * before first keyword-only parameter (if no *args)
217
+ if (!hasVarPositional && !addedBareAsterisk && nextParam?.kind === 'keyword-only' && param.kind !== 'keyword-only') {
218
+ tokens.push({ type: 'separator', value: '*' })
219
+ addedBareAsterisk = true
220
+ }
221
+ }
222
+
223
+ return tokens
224
+ }
225
+
226
+ const paramTokens = buildParamTokens(displayParams)
227
+
228
+ // Render a single parameter element
229
+ const renderParamElement = (param: GriffeParameter, multiline: boolean) => (
230
+ <>
231
+ {param.kind === 'var-positional' && <span className="text-gray-400">*</span>}
232
+ {param.kind === 'var-keyword' && <span className="text-gray-400">**</span>}
233
+ <span className="text-orange-300">{param.name}</span>
234
+ {param.annotation && (
235
+ <>
236
+ <span className="text-gray-400">: </span>
237
+ <span className="text-emerald-400">{renderExpression(param.annotation)}</span>
238
+ </>
239
+ )}
240
+ {param.default && (
241
+ <>
242
+ <span className="text-gray-400"> = </span>
243
+ <span className="text-blue-300">{renderExpression(param.default)}</span>
244
+ </>
245
+ )}
246
+ {multiline && <span className="text-gray-400">,</span>}
247
+ </>
248
+ )
249
+
250
+ // Determine if we need multi-line formatting
251
+ const needsMultiline = displayParams.length > 3
252
+
253
+ return (
254
+ <div className={`relative group ${className}`}>
255
+ {/* Dark code block like strawberry.rocks */}
256
+ <div className="font-mono text-sm bg-gray-900 dark:bg-gray-950 rounded-lg p-4 overflow-x-auto">
257
+ <code className="text-gray-100">
258
+ {isAsync && <span className="text-purple-400">async </span>}
259
+ <span className="text-blue-400">def</span>
260
+ {' '}
261
+ <span className="text-yellow-300">{name}</span>
262
+ <span className="text-gray-400">(</span>
263
+ {paramTokens.length > 0 && (
264
+ needsMultiline ? (
265
+ // Multi-line for many parameters
266
+ <>
267
+ {paramTokens.map((token, i) => (
268
+ token.type === 'param' ? (
269
+ <span key={token.param.name} className="block pl-4">
270
+ {renderParamElement(token.param, true)}
271
+ </span>
272
+ ) : (
273
+ <span key={`sep-${i}`} className="block pl-4">
274
+ <span className="text-gray-400">{token.value},</span>
275
+ </span>
276
+ )
277
+ ))}
278
+ </>
279
+ ) : (
280
+ // Single line for few parameters
281
+ paramTokens.map((token, i) => (
282
+ token.type === 'param' ? (
283
+ <span key={token.param.name}>
284
+ {i > 0 && <span className="text-gray-400">, </span>}
285
+ {renderParamElement(token.param, false)}
286
+ </span>
287
+ ) : (
288
+ <span key={`sep-${i}`}>
289
+ <span className="text-gray-400">, {token.value}</span>
290
+ </span>
291
+ )
292
+ ))
293
+ )
294
+ )}
295
+ <span className="text-gray-400">)</span>
296
+ {returnType && (
297
+ <>
298
+ <span className="text-gray-400"> -&gt; </span>
299
+ <span className="text-emerald-400">{returnType}</span>
300
+ </>
301
+ )}
302
+ <span className="text-gray-400">:</span>
303
+ <span className="block pl-2 text-gray-500">...</span>
304
+ </code>
305
+ </div>
306
+
307
+ {/* Copy button */}
308
+ <button
309
+ onClick={handleCopy}
310
+ className="absolute top-3 right-3 p-1.5 rounded bg-gray-700 hover:bg-gray-600 opacity-0 group-hover:opacity-100 transition-opacity text-gray-300 hover:text-white"
311
+ title="Copy to clipboard"
312
+ >
313
+ {copied ? <CheckIcon /> : <CopyIcon />}
314
+ </button>
315
+ </div>
316
+ )
317
+ }
@@ -0,0 +1,50 @@
1
+ // Re-export the shared TableOfContents component
2
+ export { TableOfContents } from '../TableOfContents'
3
+ export type { TOCItem as TocItem } from '../../types'
4
+
5
+ /**
6
+ * Generate TOC items from a class's members
7
+ * Filters out private members (except __init__) to match ClassDoc rendering
8
+ */
9
+ export function generateClassToc(cls: {
10
+ name: string
11
+ members?: Record<string, { kind: string; name: string }>
12
+ }): { id: string; title: string; level: number }[] {
13
+ const items: { id: string; title: string; level: number }[] = []
14
+
15
+ // Add class name as top item
16
+ items.push({ id: cls.name, title: cls.name, level: 1 })
17
+
18
+ if (!cls.members) return items
19
+
20
+ const members = Object.values(cls.members)
21
+
22
+ // Filter methods: __init__ is special, skip other private/dunder methods
23
+ const methods = members.filter(m => m.kind === 'function')
24
+ const initMethod = methods.find(m => m.name === '__init__')
25
+ const publicMethods = methods
26
+ .filter(m => m.name !== '__init__' && !m.name.startsWith('_'))
27
+ .sort((a, b) => a.name.localeCompare(b.name))
28
+
29
+ // Filter attributes: skip private ones
30
+ const publicAttributes = members
31
+ .filter(m => m.kind === 'attribute' && !m.name.startsWith('_'))
32
+ .sort((a, b) => a.name.localeCompare(b.name))
33
+
34
+ // Add constructor section if exists
35
+ if (initMethod) {
36
+ items.push({ id: 'constructor', title: 'Constructor', level: 2 })
37
+ }
38
+
39
+ // Add methods section header if there are public methods
40
+ if (publicMethods.length > 0) {
41
+ items.push({ id: 'methods', title: 'Methods', level: 2 })
42
+ }
43
+
44
+ // Add attributes section header if there are public attributes
45
+ if (publicAttributes.length > 0) {
46
+ items.push({ id: 'attributes', title: 'Attributes', level: 2 })
47
+ }
48
+
49
+ return items
50
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * API Documentation Components
3
+ *
4
+ * Components for rendering Python API documentation generated by Griffe.
5
+ */
6
+
7
+ export { APIPage } from './APIPage'
8
+ export { APILayout } from './APILayout'
9
+ export { ModuleDoc } from './ModuleDoc'
10
+ export { ClassDoc } from './ClassDoc'
11
+ export { FunctionDoc } from './FunctionDoc'
12
+ export { Signature } from './Signature'
13
+ export { Docstring } from './Docstring'
14
+ export { ParameterTable } from './ParameterTable'
15
+ export { CodeSpan } from './CodeSpan'
16
+ export { TableOfContents, generateClassToc, type TocItem } from './TableOfContents'
17
+ export { Breadcrumb, generateBreadcrumb } from './Breadcrumb'
@@ -1,6 +1,6 @@
1
1
  export { CodeBlock, InlineCode } from './CodeBlock'
2
2
  export { DocSetSelector } from './DocSetSelector'
3
- export { DocsLayout } from './DocsLayout'
3
+ export { DocsLayout, MobileMenuButton } from './DocsLayout'
4
4
  export { DocsPage } from './DocsPage'
5
5
  export { EmojiConfetti } from './EmojiConfetti'
6
6
  export { HomePage } from './HomePage'
@@ -9,3 +9,15 @@ export { Sidebar } from './Sidebar'
9
9
  export { TableOfContents } from './TableOfContents'
10
10
  export { ThemeProvider, useTheme, themeInitScript } from './ThemeProvider'
11
11
  export { ThemeToggle } from './ThemeToggle'
12
+
13
+ // API Documentation Components
14
+ export {
15
+ APIPage,
16
+ APILayout,
17
+ ModuleDoc,
18
+ ClassDoc,
19
+ FunctionDoc,
20
+ Signature,
21
+ Docstring,
22
+ ParameterTable,
23
+ } from './api'
package/src/index.ts CHANGED
@@ -8,12 +8,22 @@ export {
8
8
  HomePage,
9
9
  InlineCode,
10
10
  Markdown,
11
+ MobileMenuButton,
11
12
  Sidebar,
12
13
  TableOfContents,
13
14
  ThemeProvider,
14
15
  ThemeToggle,
15
16
  useTheme,
16
17
  themeInitScript,
18
+ // API Documentation Components
19
+ APIPage,
20
+ APILayout,
21
+ ModuleDoc,
22
+ ClassDoc,
23
+ FunctionDoc,
24
+ Signature,
25
+ Docstring,
26
+ ParameterTable,
17
27
  } from './components'
18
28
 
19
29
  // HomePage sub-components (for compound component pattern)
@@ -47,6 +57,28 @@ export type {
47
57
  SidebarProps,
48
58
  TableOfContentsProps,
49
59
  TOCItem,
60
+ // API Documentation Types
61
+ GriffeKind,
62
+ GriffeDocstringSectionKind,
63
+ GriffeExpression,
64
+ GriffeParameter,
65
+ GriffeDocstringElement,
66
+ GriffeDocstringSection,
67
+ GriffeDocstring,
68
+ GriffeDecorator,
69
+ GriffeObjectBase,
70
+ GriffeFunction,
71
+ GriffeAttribute,
72
+ GriffeClass,
73
+ GriffeModule,
74
+ GriffeMember,
75
+ APIPageProps,
76
+ ModuleDocProps,
77
+ ClassDocProps,
78
+ FunctionDocProps,
79
+ SignatureProps,
80
+ DocstringProps,
81
+ ParameterTableProps,
50
82
  } from './types'
51
83
 
52
84
  export type { Theme, ResolvedTheme } from './components/ThemeProvider'