@wix/zero-config-implementation 1.5.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/README.md +72 -0
- package/dist/component-loader.d.ts +42 -0
- package/dist/component-renderer.d.ts +31 -0
- package/dist/converters/data-item-builder.d.ts +15 -0
- package/dist/converters/index.d.ts +1 -0
- package/dist/converters/to-editor-component.d.ts +3 -0
- package/dist/converters/utils.d.ts +16 -0
- package/dist/errors.d.ts +230 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +51978 -0
- package/dist/information-extractors/css/index.d.ts +3 -0
- package/dist/information-extractors/css/parse.d.ts +7 -0
- package/dist/information-extractors/css/selector-matcher.d.ts +3 -0
- package/dist/information-extractors/css/types.d.ts +49 -0
- package/dist/information-extractors/react/extractors/core/index.d.ts +6 -0
- package/dist/information-extractors/react/extractors/core/runner.d.ts +19 -0
- package/dist/information-extractors/react/extractors/core/store.d.ts +17 -0
- package/dist/information-extractors/react/extractors/core/tree-builder.d.ts +15 -0
- package/dist/information-extractors/react/extractors/core/types.d.ts +40 -0
- package/dist/information-extractors/react/extractors/css-properties.d.ts +20 -0
- package/dist/information-extractors/react/extractors/index.d.ts +11 -0
- package/dist/information-extractors/react/extractors/prop-tracker.d.ts +24 -0
- package/dist/information-extractors/react/index.d.ts +9 -0
- package/dist/information-extractors/react/types.d.ts +51 -0
- package/dist/information-extractors/react/utils/mock-generator.d.ts +9 -0
- package/dist/information-extractors/react/utils/prop-spy.d.ts +10 -0
- package/dist/information-extractors/ts/components.d.ts +9 -0
- package/dist/information-extractors/ts/css-imports.d.ts +2 -0
- package/dist/information-extractors/ts/index.d.ts +3 -0
- package/dist/information-extractors/ts/types.d.ts +47 -0
- package/dist/information-extractors/ts/utils/semantic-type-resolver.d.ts +3 -0
- package/dist/jsx-runtime-interceptor.d.ts +42 -0
- package/dist/jsx-runtime-interceptor.js +63 -0
- package/dist/jsx-runtime-loader.d.ts +23 -0
- package/dist/jsx-runtime-loader.js +7 -0
- package/dist/manifest-pipeline.d.ts +33 -0
- package/dist/schema.d.ts +167 -0
- package/dist/ts-compiler.d.ts +13 -0
- package/package.json +81 -0
- package/src/component-loader.test.ts +277 -0
- package/src/component-loader.ts +256 -0
- package/src/component-renderer.ts +192 -0
- package/src/converters/data-item-builder.ts +354 -0
- package/src/converters/index.ts +1 -0
- package/src/converters/to-editor-component.ts +167 -0
- package/src/converters/utils.ts +21 -0
- package/src/errors.ts +103 -0
- package/src/index.ts +223 -0
- package/src/information-extractors/css/README.md +3 -0
- package/src/information-extractors/css/index.ts +3 -0
- package/src/information-extractors/css/parse.ts +450 -0
- package/src/information-extractors/css/selector-matcher.ts +88 -0
- package/src/information-extractors/css/types.ts +56 -0
- package/src/information-extractors/react/extractors/core/index.ts +6 -0
- package/src/information-extractors/react/extractors/core/runner.ts +89 -0
- package/src/information-extractors/react/extractors/core/store.ts +36 -0
- package/src/information-extractors/react/extractors/core/tree-builder.ts +273 -0
- package/src/information-extractors/react/extractors/core/types.ts +48 -0
- package/src/information-extractors/react/extractors/css-properties.ts +214 -0
- package/src/information-extractors/react/extractors/index.ts +27 -0
- package/src/information-extractors/react/extractors/prop-tracker.ts +132 -0
- package/src/information-extractors/react/index.ts +53 -0
- package/src/information-extractors/react/types.ts +70 -0
- package/src/information-extractors/react/utils/mock-generator.ts +331 -0
- package/src/information-extractors/react/utils/prop-spy.ts +168 -0
- package/src/information-extractors/ts/components.ts +300 -0
- package/src/information-extractors/ts/css-imports.ts +26 -0
- package/src/information-extractors/ts/index.ts +3 -0
- package/src/information-extractors/ts/types.ts +56 -0
- package/src/information-extractors/ts/utils/semantic-type-resolver.ts +377 -0
- package/src/jsx-runtime-interceptor.ts +146 -0
- package/src/jsx-runtime-loader.ts +38 -0
- package/src/manifest-pipeline.ts +362 -0
- package/src/schema.ts +174 -0
- package/src/ts-compiler.ts +41 -0
- package/tsconfig.json +17 -0
- package/typedoc.json +18 -0
- package/vite.config.ts +45 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import { type ComponentDoc, type PropItem, withCompilerOptions } from 'react-docgen-typescript'
|
|
2
|
+
import ts from 'typescript'
|
|
3
|
+
import type { ComponentInfo, DefaultValue, PropInfo } from './types'
|
|
4
|
+
import { resolveType } from './utils/semantic-type-resolver'
|
|
5
|
+
|
|
6
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
7
|
+
// Shared parser options
|
|
8
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
9
|
+
|
|
10
|
+
const sharedPropFilter = (prop: PropItem) => {
|
|
11
|
+
// Exclude props inherited from node_modules (e.g. HTMLAttributes)
|
|
12
|
+
if (prop.declarations && prop.declarations.length > 0) {
|
|
13
|
+
return !prop.declarations.every((d) => d.fileName.includes('node_modules'))
|
|
14
|
+
}
|
|
15
|
+
return true
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const sharedParserOptions = {
|
|
19
|
+
shouldRemoveUndefinedFromOptional: true,
|
|
20
|
+
shouldIncludePropTagMap: true,
|
|
21
|
+
skipChildrenPropWithoutDoc: true,
|
|
22
|
+
propFilter: sharedPropFilter,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
26
|
+
// Main API
|
|
27
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
28
|
+
|
|
29
|
+
export function extractAllComponentInfo(program: ts.Program, filePath: string): ComponentInfo[] {
|
|
30
|
+
const checker = program.getTypeChecker()
|
|
31
|
+
const options = program.getCompilerOptions()
|
|
32
|
+
|
|
33
|
+
const parser = withCompilerOptions(options, sharedParserOptions)
|
|
34
|
+
|
|
35
|
+
const docs = parser.parseWithProgramProvider([filePath], () => program)
|
|
36
|
+
|
|
37
|
+
return docs.map((doc) => convertComponentDoc(doc, program, checker))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Extracts component info for only the default-exported component in a file.
|
|
42
|
+
* Returns `undefined` if the file has no default export or if the default export
|
|
43
|
+
* is not a recognized React component.
|
|
44
|
+
*/
|
|
45
|
+
export function extractDefaultComponentInfo(program: ts.Program, filePath: string): ComponentInfo | undefined {
|
|
46
|
+
const defaultName = findDefaultExportName(program, filePath)
|
|
47
|
+
if (!defaultName) return undefined
|
|
48
|
+
|
|
49
|
+
const all = extractAllComponentInfo(program, filePath)
|
|
50
|
+
return all.find((c) => c.componentName === defaultName)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
54
|
+
// Default export resolution
|
|
55
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Resolves the name of the default-exported symbol in a file using the
|
|
59
|
+
* TypeScript type checker.
|
|
60
|
+
*
|
|
61
|
+
* Returns `undefined` for anonymous default exports (e.g. `export default () => ...`)
|
|
62
|
+
* where no stable name can be determined.
|
|
63
|
+
*/
|
|
64
|
+
function findDefaultExportName(program: ts.Program, filePath: string): string | undefined {
|
|
65
|
+
const checker = program.getTypeChecker()
|
|
66
|
+
const sourceFile = program.getSourceFile(filePath)
|
|
67
|
+
if (!sourceFile) return undefined
|
|
68
|
+
|
|
69
|
+
const moduleSymbol = checker.getSymbolAtLocation(sourceFile)
|
|
70
|
+
if (!moduleSymbol) return undefined
|
|
71
|
+
|
|
72
|
+
const defaultSymbol = checker.getExportsOfModule(moduleSymbol).find((s) => s.getName() === 'default')
|
|
73
|
+
if (!defaultSymbol) return undefined
|
|
74
|
+
|
|
75
|
+
// For `export default Foo` the symbol is an alias — resolve it to get 'Foo'
|
|
76
|
+
if (defaultSymbol.getFlags() & ts.SymbolFlags.Alias) {
|
|
77
|
+
const aliased = checker.getAliasedSymbol(defaultSymbol)
|
|
78
|
+
const name = aliased.getName()
|
|
79
|
+
// 'default' means the alias resolved back to an anonymous default export
|
|
80
|
+
return name !== 'default' ? name : undefined
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return undefined
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
87
|
+
// ComponentDoc → ComponentInfo conversion
|
|
88
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
89
|
+
|
|
90
|
+
function convertComponentDoc(doc: ComponentDoc, program: ts.Program, checker: ts.TypeChecker): ComponentInfo {
|
|
91
|
+
const propsType = findPropsType(doc.displayName, doc.filePath, program, checker)
|
|
92
|
+
const props: Record<string, PropInfo> = {}
|
|
93
|
+
|
|
94
|
+
for (const [propName, propItem] of Object.entries(doc.props)) {
|
|
95
|
+
// Skip props marked with @ignore or @private
|
|
96
|
+
const tags = propItem.tags as Record<string, string> | undefined
|
|
97
|
+
if (tags?.ignore !== undefined || tags?.private !== undefined) {
|
|
98
|
+
continue
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Look up the ts.Symbol from the props type for deep resolution
|
|
102
|
+
const propSymbol = propsType?.getProperty(propName)
|
|
103
|
+
const propType = propSymbol ? checker.getTypeOfSymbol(propSymbol) : undefined
|
|
104
|
+
|
|
105
|
+
// Resolve the type deeply
|
|
106
|
+
let declaredTypeInfo: DeclaredTypeInfo | undefined
|
|
107
|
+
if (propSymbol) {
|
|
108
|
+
const decl = propSymbol.getDeclarations()?.[0]
|
|
109
|
+
if (decl) {
|
|
110
|
+
declaredTypeInfo = getDeclaredTypeInfo(propSymbol, decl.getSourceFile(), checker)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const typeString = declaredTypeInfo?.name ?? propItem.type.name
|
|
115
|
+
const resolvedType = propType
|
|
116
|
+
? resolveType(propType, checker, 0, typeString, declaredTypeInfo?.symbol)
|
|
117
|
+
: { kind: 'primitive' as const, value: propItem.type.name }
|
|
118
|
+
|
|
119
|
+
// Convert default value
|
|
120
|
+
let defaultValue: DefaultValue | undefined
|
|
121
|
+
if (propItem.defaultValue != null) {
|
|
122
|
+
defaultValue = convertDefaultValue(propItem.defaultValue)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// If no runtime default, check @default JSDoc tag
|
|
126
|
+
if (!defaultValue && tags?.default) {
|
|
127
|
+
defaultValue = parseDefaultValueFromString(tags.default)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
props[propName] = {
|
|
131
|
+
name: propName,
|
|
132
|
+
type: typeString,
|
|
133
|
+
required: propItem.required,
|
|
134
|
+
defaultValue,
|
|
135
|
+
resolvedType,
|
|
136
|
+
description: propItem.description || undefined,
|
|
137
|
+
deprecated: tags?.deprecated !== undefined ? true : undefined,
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return { componentName: doc.displayName, props }
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
145
|
+
// Find the props ts.Type for a component (needed for resolveType)
|
|
146
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
147
|
+
|
|
148
|
+
function findPropsType(
|
|
149
|
+
componentName: string,
|
|
150
|
+
filePath: string,
|
|
151
|
+
program: ts.Program,
|
|
152
|
+
checker: ts.TypeChecker,
|
|
153
|
+
): ts.Type | undefined {
|
|
154
|
+
const sourceFile = program.getSourceFile(filePath)
|
|
155
|
+
if (!sourceFile) return undefined
|
|
156
|
+
|
|
157
|
+
const moduleSymbol = checker.getSymbolAtLocation(sourceFile)
|
|
158
|
+
if (!moduleSymbol) return undefined
|
|
159
|
+
|
|
160
|
+
const exports = checker.getExportsOfModule(moduleSymbol)
|
|
161
|
+
const componentSymbol = exports.find((s) => s.getName() === componentName)
|
|
162
|
+
if (!componentSymbol) return undefined
|
|
163
|
+
|
|
164
|
+
const componentType = checker.getTypeOfSymbol(componentSymbol)
|
|
165
|
+
|
|
166
|
+
// Function component: call signatures → first parameter is props
|
|
167
|
+
const callSigs = componentType.getCallSignatures()
|
|
168
|
+
if (callSigs.length > 0) {
|
|
169
|
+
const params = callSigs[0].getParameters()
|
|
170
|
+
if (params.length > 0) {
|
|
171
|
+
return checker.getTypeOfSymbol(params[0])
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Class component: construct signatures → first type argument is props
|
|
176
|
+
const constructSigs = componentType.getConstructSignatures()
|
|
177
|
+
if (constructSigs.length > 0) {
|
|
178
|
+
const params = constructSigs[0].getParameters()
|
|
179
|
+
if (params.length > 0) {
|
|
180
|
+
const propsParam = checker.getTypeOfSymbol(params[0])
|
|
181
|
+
return propsParam
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// memo / forwardRef: check for the underlying call signature
|
|
186
|
+
// The type of memo(...) or forwardRef(...) wraps the inner component
|
|
187
|
+
const properties = componentType.getProperties()
|
|
188
|
+
for (const prop of properties) {
|
|
189
|
+
if (prop.getName() === 'type' || prop.getName() === 'render') {
|
|
190
|
+
const innerType = checker.getTypeOfSymbol(prop)
|
|
191
|
+
const innerSigs = innerType.getCallSignatures()
|
|
192
|
+
if (innerSigs.length > 0) {
|
|
193
|
+
const params = innerSigs[0].getParameters()
|
|
194
|
+
if (params.length > 0) {
|
|
195
|
+
return checker.getTypeOfSymbol(params[0])
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return undefined
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
205
|
+
// Default value conversion
|
|
206
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
207
|
+
|
|
208
|
+
function convertDefaultValue(rdtDefault: { value: unknown } | null): DefaultValue | undefined {
|
|
209
|
+
if (!rdtDefault || rdtDefault.value == null) return undefined
|
|
210
|
+
|
|
211
|
+
const val = rdtDefault.value
|
|
212
|
+
|
|
213
|
+
// Already a primitive — react-docgen-typescript sometimes returns non-string values
|
|
214
|
+
if (typeof val === 'boolean') return { kind: 'boolean', value: val }
|
|
215
|
+
if (typeof val === 'number') return { kind: 'number', value: val }
|
|
216
|
+
if (typeof val !== 'string') return { kind: 'unresolved', value: String(val) }
|
|
217
|
+
|
|
218
|
+
// react-docgen-typescript strips quotes from string literal defaults,
|
|
219
|
+
// so 'ltr' becomes "ltr". Try parsing as a well-known literal first
|
|
220
|
+
// (true/false/null/number), otherwise treat as a string value.
|
|
221
|
+
return parseDefaultValueFromString(val, /* fallbackToString */ true)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Parses a string value (typically from JSDoc @default or react-docgen-typescript) into a DefaultValue.
|
|
226
|
+
* Attempts to parse as JSON-like literals, falls back to unresolved (or string if fallbackToString is true).
|
|
227
|
+
*
|
|
228
|
+
* @param fallbackToString — when true, unquoted non-literal values become `{ kind: 'string' }`
|
|
229
|
+
* instead of `{ kind: 'unresolved' }`. Used for react-docgen-typescript defaults which are
|
|
230
|
+
* always literals but arrive without surrounding quotes.
|
|
231
|
+
*/
|
|
232
|
+
function parseDefaultValueFromString(text: string, fallbackToString = false): DefaultValue {
|
|
233
|
+
const trimmed = text.trim()
|
|
234
|
+
|
|
235
|
+
// Boolean literals
|
|
236
|
+
if (trimmed === 'true') {
|
|
237
|
+
return { kind: 'boolean', value: true }
|
|
238
|
+
}
|
|
239
|
+
if (trimmed === 'false') {
|
|
240
|
+
return { kind: 'boolean', value: false }
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Null literal
|
|
244
|
+
if (trimmed === 'null') {
|
|
245
|
+
return { kind: 'null', value: null }
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Number literals (including negative)
|
|
249
|
+
const num = Number(trimmed)
|
|
250
|
+
if (!Number.isNaN(num) && trimmed !== '') {
|
|
251
|
+
return { kind: 'number', value: num }
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// String literals: 'hello' or "hello"
|
|
255
|
+
if ((trimmed.startsWith("'") && trimmed.endsWith("'")) || (trimmed.startsWith('"') && trimmed.endsWith('"'))) {
|
|
256
|
+
return { kind: 'string', value: trimmed.slice(1, -1) }
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// react-docgen-typescript strips quotes from string defaults, so treat as string
|
|
260
|
+
if (fallbackToString) {
|
|
261
|
+
return { kind: 'string', value: trimmed }
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Everything else is unresolved (e.g. JSDoc @default with a reference)
|
|
265
|
+
return { kind: 'unresolved', value: trimmed }
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
269
|
+
// Helpers
|
|
270
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
271
|
+
|
|
272
|
+
interface DeclaredTypeInfo {
|
|
273
|
+
name: string
|
|
274
|
+
symbol?: ts.Symbol
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function getDeclaredTypeInfo(
|
|
278
|
+
prop: ts.Symbol,
|
|
279
|
+
sourceFile: ts.SourceFile,
|
|
280
|
+
checker: ts.TypeChecker,
|
|
281
|
+
): DeclaredTypeInfo | undefined {
|
|
282
|
+
const declaration = prop.getDeclarations()?.[0]
|
|
283
|
+
if (!declaration) return undefined
|
|
284
|
+
|
|
285
|
+
if (
|
|
286
|
+
(ts.isPropertySignature(declaration) || ts.isPropertyDeclaration(declaration) || ts.isParameter(declaration)) &&
|
|
287
|
+
declaration.type &&
|
|
288
|
+
ts.isTypeReferenceNode(declaration.type)
|
|
289
|
+
) {
|
|
290
|
+
const typeName = declaration.type.typeName
|
|
291
|
+
const identifier = ts.isIdentifier(typeName) ? typeName : typeName.right
|
|
292
|
+
|
|
293
|
+
return {
|
|
294
|
+
name: identifier.getText(sourceFile),
|
|
295
|
+
symbol: checker.getSymbolAtLocation(identifier),
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return undefined
|
|
300
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as path from 'node:path'
|
|
2
|
+
import ts, { type Program } from 'typescript'
|
|
3
|
+
|
|
4
|
+
export function extractCssImports(program: Program): string[] {
|
|
5
|
+
const cssFiles = new Set<string>()
|
|
6
|
+
|
|
7
|
+
for (const sourceFile of program.getSourceFiles()) {
|
|
8
|
+
// Skip external libraries
|
|
9
|
+
if (sourceFile.isDeclarationFile || sourceFile.fileName.includes('node_modules')) continue
|
|
10
|
+
|
|
11
|
+
ts.forEachChild(sourceFile, (node) => {
|
|
12
|
+
// Look for: import './style.css' or import x from './style.css'
|
|
13
|
+
if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {
|
|
14
|
+
const importPath = node.moduleSpecifier.text
|
|
15
|
+
|
|
16
|
+
if (importPath.endsWith('.css')) {
|
|
17
|
+
// Resolve relative path to an absolute disk path
|
|
18
|
+
const fullPath = path.resolve(path.dirname(sourceFile.fileName), importPath)
|
|
19
|
+
cssFiles.add(fullPath)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return Array.from(cssFiles)
|
|
26
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API to extract component props with full TypeScript type resolution
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type ResolvedKind =
|
|
6
|
+
| 'primitive'
|
|
7
|
+
| 'semantic'
|
|
8
|
+
| 'array'
|
|
9
|
+
| 'object'
|
|
10
|
+
| 'union'
|
|
11
|
+
| 'intersection'
|
|
12
|
+
| 'enum'
|
|
13
|
+
| 'literal'
|
|
14
|
+
| 'function'
|
|
15
|
+
|
|
16
|
+
export interface ResolvedType {
|
|
17
|
+
kind: ResolvedKind
|
|
18
|
+
value?: unknown
|
|
19
|
+
/** For semantic types, the package the symbol came from */
|
|
20
|
+
source?: string
|
|
21
|
+
properties?: Record<string, PropInfo>
|
|
22
|
+
elementType?: ResolvedType
|
|
23
|
+
types?: ResolvedType[] // For unions and intersections
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Resolved default value with its type.
|
|
28
|
+
* For literals (string, number, boolean, null), the value is the actual JavaScript value.
|
|
29
|
+
* For unresolvable values (references, expressions), we store the raw source text.
|
|
30
|
+
*/
|
|
31
|
+
export type DefaultValue =
|
|
32
|
+
| { kind: 'string'; value: string }
|
|
33
|
+
| { kind: 'number'; value: number }
|
|
34
|
+
| { kind: 'boolean'; value: boolean }
|
|
35
|
+
| { kind: 'null'; value: null }
|
|
36
|
+
| { kind: 'unresolved'; value: string } // For references like MY_CONST or complex expressions
|
|
37
|
+
|
|
38
|
+
export interface PropInfo {
|
|
39
|
+
name: string
|
|
40
|
+
// The unresolved type. For example "string", "User".
|
|
41
|
+
type: string
|
|
42
|
+
required: boolean
|
|
43
|
+
// The resolved default value of the prop
|
|
44
|
+
defaultValue?: DefaultValue
|
|
45
|
+
// Describes the resolved type of the prop, recursively down to the primitive type.
|
|
46
|
+
resolvedType: ResolvedType
|
|
47
|
+
// Description extracted from JSDoc comment
|
|
48
|
+
description?: string
|
|
49
|
+
// Whether the prop is marked as deprecated via @deprecated JSDoc tag
|
|
50
|
+
deprecated?: boolean
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface ComponentInfo {
|
|
54
|
+
componentName: string
|
|
55
|
+
props: Record<string, PropInfo>
|
|
56
|
+
}
|