@storybook/react 10.5.0-alpha.3 → 10.5.0-alpha.5

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/preset.js CHANGED
@@ -1,10 +1,10 @@
1
- import CJS_COMPAT_NODE_URL_4vwrh8n2k1w from 'node:url';
2
- import CJS_COMPAT_NODE_PATH_4vwrh8n2k1w from 'node:path';
3
- import CJS_COMPAT_NODE_MODULE_4vwrh8n2k1w from "node:module";
1
+ import CJS_COMPAT_NODE_URL_ncp5j0auwhe from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_ncp5j0auwhe from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_ncp5j0auwhe from "node:module";
4
4
 
5
- var __filename = CJS_COMPAT_NODE_URL_4vwrh8n2k1w.fileURLToPath(import.meta.url);
6
- var __dirname = CJS_COMPAT_NODE_PATH_4vwrh8n2k1w.dirname(__filename);
7
- var require = CJS_COMPAT_NODE_MODULE_4vwrh8n2k1w.createRequire(import.meta.url);
5
+ var __filename = CJS_COMPAT_NODE_URL_ncp5j0auwhe.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_ncp5j0auwhe.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_ncp5j0auwhe.createRequire(import.meta.url);
8
8
 
9
9
  // ------------------------------------------------------------
10
10
  // end of CJS compatibility banner, injected by Storybook's esbuild configuration
@@ -13858,7 +13858,7 @@ var defaultFunctionValue = inlineFunction, formatFunction = (function(fn, option
13858
13858
  var usedValue = hasValue ? value : defaultValue, useBooleanShorthandSyntax = options.useBooleanShorthandSyntax, tabStop = options.tabStop, formattedPropValue = formatPropValue(usedValue, inline, lvl, options), attributeFormattedInline = " ", attributeFormattedMultiline = `
13859
13859
  `.concat(spacer(lvl + 1, tabStop)), isMultilineAttribute = formattedPropValue.includes(`
13860
13860
  `);
13861
- return useBooleanShorthandSyntax && formattedPropValue === "{false}" && !hasDefaultValue ? (attributeFormattedInline = "", attributeFormattedMultiline = "") : useBooleanShorthandSyntax && formattedPropValue === "{true}" ? (attributeFormattedInline += "".concat(name), attributeFormattedMultiline += "".concat(name)) : (attributeFormattedInline += "".concat(name, "=").concat(formattedPropValue), attributeFormattedMultiline += "".concat(name, "=").concat(formattedPropValue)), {
13861
+ return useBooleanShorthandSyntax && formattedPropValue === "{true}" ? (attributeFormattedInline += "".concat(name), attributeFormattedMultiline += "".concat(name)) : (attributeFormattedInline += "".concat(name, "=").concat(formattedPropValue), attributeFormattedMultiline += "".concat(name, "=").concat(formattedPropValue)), {
13862
13862
  attributeFormattedInline,
13863
13863
  attributeFormattedMultiline,
13864
13864
  isMultilineAttribute
@@ -15314,2323 +15314,2381 @@ var extractArgTypesFromDocgenTypescript = async ({
15314
15314
  };
15315
15315
 
15316
15316
  // src/componentManifest/generator.ts
15317
- import { recast as recast2 } from "storybook/internal/babel";
15318
- import { Tag } from "storybook/internal/core-server";
15319
- import { storyNameFromExport } from "storybook/internal/csf";
15320
- import { extractDescription, loadCsf } from "storybook/internal/csf-tools";
15321
- import { logger as logger8 } from "storybook/internal/node-logger";
15322
-
15323
- // src/componentManifest/componentMeta/ComponentMetaManager.ts
15324
- import { logger as logger5 } from "storybook/internal/node-logger";
15325
- import { existsSync as existsSync3, watch } from "fs";
15326
- import * as path3 from "path";
15317
+ import {
15318
+ getStoryImportPathFromEntry,
15319
+ selectComponentEntriesByComponentId
15320
+ } from "storybook/internal/common";
15327
15321
 
15328
- // src/componentManifest/componentMeta/ComponentMetaProject.ts
15329
- var import_language_core = __toESM(require_language_core(), 1), import_typescript = __toESM(require_typescript(), 1);
15330
- import * as path2 from "path";
15322
+ // src/componentManifest/buildReactComponentDocgen.ts
15323
+ import { getComponentIdFromEntry } from "storybook/internal/common";
15324
+ import { extractDescription as extractDescription2 } from "storybook/internal/csf-tools";
15331
15325
 
15332
- // src/componentManifest/componentMeta/componentMetaExtractor.ts
15333
- var LARGE_SOURCE_THRESHOLD = 30, MAX_UNWRAP_DEPTH = 5, MAX_SERIALIZATION_DEPTH = 5;
15334
- function isLiteralType(type) {
15335
- return type.isStringLiteral() || type.isNumberLiteral();
15336
- }
15337
- function isUnionType(type) {
15338
- return type.isUnion();
15339
- }
15340
- function isWrappedExpression(typescript, expression) {
15341
- return typescript.isParenthesizedExpression(expression) || typescript.isAsExpression(expression) || typescript.isNonNullExpression(expression) || (typescript.isSatisfiesExpression?.(expression) ?? !1);
15342
- }
15343
- function resolveAliasedSymbol(typescript, checker, symbol) {
15344
- return symbol.flags & typescript.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
15345
- }
15346
- function getSymbolContextNode(symbol) {
15347
- return symbol.valueDeclaration ?? symbol.getDeclarations()?.[0];
15348
- }
15349
- function resolveComponentSymbolFromNode(typescript, checker, node) {
15350
- if (!node)
15351
- return;
15352
- let symbol = checker.getSymbolAtLocation(node);
15353
- return symbol ? resolveComponentSymbol(typescript, checker, symbol, node) : void 0;
15326
+ // src/componentManifest/extractComponentDescription.ts
15327
+ function extractComponentDescription(metaJsDoc, docgenDescription, docgenJsDocTags) {
15328
+ let jsdocComment = metaJsDoc || docgenDescription, extracted = jsdocComment ? extractJSDocInfo(jsdocComment) : void 0, tags = docgenJsDocTags ?? extracted?.tags ?? {}, description = extracted?.description;
15329
+ return {
15330
+ description: ((tags?.describe?.[0] || tags?.desc?.[0]) ?? description)?.trim(),
15331
+ summary: tags.summary?.[0],
15332
+ jsDocTags: tags
15333
+ };
15354
15334
  }
15355
- function resolveComponentSymbol(typescript, checker, symbol, contextNode, depth = 0) {
15356
- let resolved = resolveAliasedSymbol(typescript, checker, symbol);
15357
- if (depth > MAX_UNWRAP_DEPTH)
15358
- return resolved;
15359
- let declarationForPromotion = getSymbolContextNode(resolved);
15360
- if (declarationForPromotion && (typescript.isArrowFunction(declarationForPromotion) || typescript.isFunctionExpression(declarationForPromotion)) && declarationForPromotion.parent && typescript.isVariableDeclaration(declarationForPromotion.parent) && typescript.isIdentifier(declarationForPromotion.parent.name)) {
15361
- let variableSymbol = checker.getSymbolAtLocation(declarationForPromotion.parent.name);
15362
- variableSymbol && (resolved = resolveAliasedSymbol(typescript, checker, variableSymbol));
15363
- }
15364
- let declaration = getSymbolContextNode(resolved);
15365
- if (declaration) {
15366
- if (typescript.isShorthandPropertyAssignment(declaration)) {
15367
- let valueSymbol = checker.getShorthandAssignmentValueSymbol(declaration);
15368
- if (valueSymbol)
15369
- return resolveComponentSymbol(
15370
- typescript,
15371
- checker,
15372
- valueSymbol,
15373
- declaration.name,
15374
- depth + 1
15375
- );
15376
- }
15377
- if (typescript.isPropertyAssignment(declaration)) {
15378
- let next = resolveComponentSymbolFromNode(typescript, checker, declaration.initializer);
15379
- if (next)
15380
- return next;
15381
- }
15382
- if (typescript.isBinaryExpression(declaration) && declaration.operatorToken.kind === typescript.SyntaxKind.EqualsToken) {
15383
- let next = resolveComponentSymbolFromNode(typescript, checker, declaration.right);
15384
- if (next)
15385
- return next;
15386
- }
15387
- }
15388
- let typeSymbol = (!!(resolved.flags & typescript.SymbolFlags.Property) || declaration !== void 0 && (typescript.isPropertyAssignment(declaration) || typescript.isShorthandPropertyAssignment(declaration) || typescript.isPropertySignature(declaration) || typescript.isPropertyDeclaration(declaration) || typescript.isBinaryExpression(declaration) && declaration.operatorToken.kind === typescript.SyntaxKind.EqualsToken)) && checker.getTypeOfSymbolAtLocation(resolved, contextNode).getSymbol?.();
15389
- if (typeSymbol) {
15390
- let resolvedTypeSymbol = resolveAliasedSymbol(typescript, checker, typeSymbol), typeDeclaration = getSymbolContextNode(resolvedTypeSymbol);
15391
- if (resolvedTypeSymbol !== resolved && typeDeclaration)
15392
- return resolveComponentSymbol(
15393
- typescript,
15394
- checker,
15395
- resolvedTypeSymbol,
15396
- typeDeclaration,
15397
- depth + 1
15398
- );
15335
+
15336
+ // src/componentManifest/getComponentImports.ts
15337
+ import { dirname as dirname6 } from "node:path";
15338
+ import { babelParse as babelParse2, recast, types as t2 } from "storybook/internal/babel";
15339
+ import { logger as logger6 } from "storybook/internal/node-logger";
15340
+
15341
+ // src/componentManifest/reactDocgenTypescript.ts
15342
+ import { dirname as dirname5 } from "node:path";
15343
+ import { logger as logger5 } from "storybook/internal/node-logger";
15344
+ var typeScriptPromise, reactDocgenTypescriptPromise, loadTypeScript = () => typeScriptPromise ??= import("typescript"), loadReactDocgenTypescript = () => reactDocgenTypescriptPromise ??= import("react-docgen-typescript"), LARGE_NON_USER_SOURCE_THRESHOLD = 30, getPropSource = (prop) => prop.parent?.fileName ?? prop.declarations?.[0]?.fileName, getLargeNonUserPropSources = (props) => {
15345
+ let countBySource = /* @__PURE__ */ new Map();
15346
+ for (let prop of Object.values(props)) {
15347
+ let source = getPropSource(prop);
15348
+ (source?.includes("node_modules") || source?.endsWith(".d.ts")) && countBySource.set(source, (countBySource.get(source) ?? 0) + 1);
15399
15349
  }
15400
- return resolved;
15401
- }
15402
- function resolvePropsFromStoryFile(typescript, checker, storySourceFile, componentRef) {
15403
- let importSpecifier = componentRef.importId, importName = componentRef.importName, memberAccess = componentRef.member;
15404
- if (!importSpecifier)
15405
- return;
15406
- let importSymbol;
15407
- for (let stmt of storySourceFile.statements) {
15408
- if (!typescript.isImportDeclaration(stmt))
15409
- continue;
15410
- let moduleSpec = stmt.moduleSpecifier;
15411
- if (!typescript.isStringLiteral(moduleSpec) || moduleSpec.text !== importSpecifier)
15350
+ let largeNonUserSources = /* @__PURE__ */ new Set();
15351
+ for (let [source, count] of countBySource)
15352
+ count > LARGE_NON_USER_SOURCE_THRESHOLD && largeNonUserSources.add(source);
15353
+ return largeNonUserSources;
15354
+ };
15355
+ function findDisplayNameAssignment(typescript, sourceFile, identifierName) {
15356
+ for (let statement of sourceFile.statements) {
15357
+ if (!typescript.isExpressionStatement(statement))
15412
15358
  continue;
15413
- let clause = stmt.importClause;
15414
- if (clause) {
15415
- if (importName === "default") {
15416
- if (clause.name && (importSymbol = checker.getSymbolAtLocation(clause.name)), !importSymbol && clause.namedBindings && typescript.isNamedImports(clause.namedBindings)) {
15417
- for (let spec of clause.namedBindings.elements)
15418
- if ((spec.propertyName ?? spec.name).text === "default") {
15419
- importSymbol = checker.getSymbolAtLocation(spec.name);
15420
- break;
15421
- }
15422
- }
15423
- } else if (clause.namedBindings && typescript.isNamedImports(clause.namedBindings)) {
15424
- for (let spec of clause.namedBindings.elements)
15425
- if ((spec.propertyName ?? spec.name).text === importName) {
15426
- importSymbol = checker.getSymbolAtLocation(spec.name);
15427
- break;
15428
- }
15429
- }
15430
- if (!importSymbol && memberAccess && clause.namedBindings && typescript.isNamespaceImport(clause.namedBindings) && (importSymbol = checker.getSymbolAtLocation(clause.namedBindings.name)), importSymbol)
15431
- break;
15432
- }
15433
- }
15434
- if (!importSymbol)
15435
- return;
15436
- let result;
15437
- function extractPropsFromJsx(node) {
15438
- let sig = checker.getResolvedSignature(node);
15439
- if (!sig)
15440
- return;
15441
- let params = sig.getParameters();
15442
- return params.length === 0 ? checker.getTypeFromTypeNode(typescript.factory.createTypeLiteralNode([])) : checker.getTypeOfSymbolAtLocation(params[0], node);
15443
- }
15444
- function visit(node) {
15445
- if (!result) {
15446
- if (typescript.isJsxSelfClosingElement(node) || typescript.isJsxOpeningElement(node)) {
15447
- let tagName = node.tagName;
15448
- if (memberAccess) {
15449
- if (typescript.isPropertyAccessExpression(tagName) && tagName.name.text === memberAccess) {
15450
- let leftSym = checker.getSymbolAtLocation(tagName.expression);
15451
- if (leftSym && importSymbol && leftSym === importSymbol) {
15452
- let propsType = extractPropsFromJsx(node);
15453
- if (propsType) {
15454
- let memberSymbol = checker.getSymbolAtLocation(tagName.name) ?? checker.getTypeAtLocation(tagName.expression).getProperty(tagName.name.text) ?? resolveComponentSymbolFromNode(typescript, checker, tagName);
15455
- result = {
15456
- componentRef,
15457
- propsType,
15458
- symbol: memberSymbol ? resolveComponentSymbol(typescript, checker, memberSymbol, tagName.name) : resolveAliasedSymbol(typescript, checker, importSymbol)
15459
- };
15460
- return;
15461
- }
15462
- }
15463
- }
15464
- } else if (typescript.isIdentifier(tagName)) {
15465
- let sym = checker.getSymbolAtLocation(tagName);
15466
- if (sym && importSymbol && sym === importSymbol) {
15467
- let propsType = extractPropsFromJsx(node);
15468
- if (propsType) {
15469
- result = {
15470
- componentRef,
15471
- propsType,
15472
- symbol: resolveAliasedSymbol(typescript, checker, sym)
15473
- };
15474
- return;
15475
- }
15476
- }
15477
- }
15478
- }
15479
- typescript.forEachChild(node, visit);
15480
- }
15481
- }
15482
- return visit(storySourceFile), result;
15483
- }
15484
- function resolvePropsFromComponentType(typescript, checker, componentType) {
15485
- let callSigs = componentType.getCallSignatures();
15486
- if (callSigs.length > 0) {
15487
- let sig = callSigs[0];
15488
- if (sig.parameters.length === 0)
15489
- return checker.getVoidType();
15490
- let propsType = checker.getTypeOfSymbol(sig.parameters[0]);
15491
- if (!(propsType.flags & typescript.TypeFlags.Any))
15492
- return propsType;
15493
- }
15494
- let ctorSigs = componentType.getConstructSignatures();
15495
- for (let sig of ctorSigs) {
15496
- let propsSym = sig.getReturnType().getProperty("props");
15497
- if (propsSym) {
15498
- let propsType = checker.getTypeOfSymbol(propsSym);
15499
- if (!(propsType.flags & typescript.TypeFlags.Any))
15500
- return propsType;
15501
- }
15359
+ let expr = statement.expression;
15360
+ if (typescript.isBinaryExpression(expr) && expr.operatorToken.kind === typescript.SyntaxKind.EqualsToken && typescript.isPropertyAccessExpression(expr.left) && expr.left.name.text === "displayName" && typescript.isIdentifier(expr.left.expression) && expr.left.expression.text === identifierName && typescript.isStringLiteral(expr.right))
15361
+ return expr.right.text;
15502
15362
  }
15503
15363
  }
15504
- function getPropSourceFile(prop) {
15505
- let declarations = prop.getDeclarations();
15506
- if (declarations?.length) {
15507
- for (let decl of declarations) {
15508
- let fileName = decl.getSourceFile().fileName;
15509
- if (!fileName.includes("node_modules") && !fileName.endsWith(".d.ts"))
15510
- return fileName;
15364
+ function getExportNameMap(typescript, checker, sourceFile) {
15365
+ let moduleSymbol = checker.getSymbolAtLocation(sourceFile);
15366
+ if (!moduleSymbol)
15367
+ return /* @__PURE__ */ new Map();
15368
+ let result = /* @__PURE__ */ new Map(), fileName = sourceFile.fileName.replace(/.*\//, "").replace(/\.[^.]+$/, "");
15369
+ for (let exportSymbol of checker.getExportsOfModule(moduleSymbol)) {
15370
+ let resolved = exportSymbol.flags & typescript.SymbolFlags.Alias ? checker.getAliasedSymbol(exportSymbol) : exportSymbol, declaration = resolved.valueDeclaration ?? resolved.getDeclarations()?.[0];
15371
+ if (!declaration)
15372
+ continue;
15373
+ let type = checker.getTypeOfSymbolAtLocation(resolved, declaration), isStateless = type.getCallSignatures().some((sig) => {
15374
+ let params = sig.getParameters();
15375
+ return params.length === 1 || params.length > 0 && params[0].getName() === "props";
15376
+ }), isStateful = type.getConstructSignatures().some(
15377
+ (sig) => sig.getReturnType().getProperty("props") !== void 0
15378
+ );
15379
+ if (isStateless || isStateful) {
15380
+ let exportName = exportSymbol.getName(), resolvedName = resolved.getName();
15381
+ result.set(resolvedName, exportName), exportName === "default" && result.set(fileName, "default");
15382
+ let displayNameValue = findDisplayNameAssignment(typescript, sourceFile, resolvedName);
15383
+ displayNameValue && result.set(displayNameValue, exportName);
15511
15384
  }
15512
- return declarations[0].getSourceFile().fileName;
15513
15385
  }
15386
+ return result;
15514
15387
  }
15515
- function getParentType(typescript, prop) {
15516
- let declarations = prop.getDeclarations();
15517
- if (!declarations?.length)
15518
- return;
15519
- let node = declarations[0].parent;
15520
- for (; node; ) {
15521
- if (typescript.isInterfaceDeclaration(node) || typescript.isTypeAliasDeclaration(node))
15522
- return {
15523
- name: node.name.getText(),
15524
- fileName: node.getSourceFile().fileName
15525
- };
15526
- node = node.parent;
15527
- }
15388
+ var cachedCompilerOptions, cachedFileNames, previousProgram, parser, cachedParserOptionsKey;
15389
+ function invalidateParser() {
15390
+ parser = void 0, cachedCompilerOptions = void 0, cachedFileNames = void 0, cachedParserOptionsKey = void 0;
15528
15391
  }
15529
- function getAllDeclarationParents(typescript, prop) {
15530
- let declarations = prop.getDeclarations();
15531
- if (!declarations?.length)
15532
- return;
15533
- let parents = [];
15534
- for (let declaration of declarations) {
15535
- let { parent } = declaration;
15536
- parent && (typescript.isInterfaceDeclaration(parent) || typescript.isTypeAliasDeclaration(parent) ? parents.push({
15537
- name: parent.name.getText(),
15538
- fileName: parent.getSourceFile().fileName
15539
- }) : typescript.isTypeLiteralNode(parent) && parents.push({
15540
- name: "TypeLiteral",
15541
- fileName: parent.getSourceFile().fileName
15542
- }));
15392
+ async function getParser5(userOptions) {
15393
+ let [typescript, reactDocgenTypescript] = await Promise.all([
15394
+ loadTypeScript(),
15395
+ loadReactDocgenTypescript()
15396
+ ]), optionsKey = JSON.stringify(userOptions ?? {});
15397
+ if (parser && cachedParserOptionsKey !== optionsKey && (parser = void 0), !parser) {
15398
+ let configPath = findTsconfigPath(process.cwd());
15399
+ if (cachedCompilerOptions = { noErrorTruncation: !0, strict: !0 }, configPath) {
15400
+ let { config } = typescript.readConfigFile(configPath, typescript.sys.readFile), parsed = typescript.parseJsonConfigFileContent(
15401
+ config,
15402
+ typescript.sys,
15403
+ dirname5(configPath)
15404
+ );
15405
+ cachedCompilerOptions = { ...parsed.options, noErrorTruncation: !0 }, cachedFileNames = parsed.fileNames;
15406
+ } else
15407
+ logger5.warn(
15408
+ "No tsconfig.json (or tsconfig.base.json / tsconfig.app.json) found. TypeScript component props will not be documented by react-docgen-typescript. Create a tsconfig.json in your project root to enable automatic controls."
15409
+ );
15410
+ let program = typescript.createProgram(
15411
+ cachedFileNames ?? [],
15412
+ cachedCompilerOptions,
15413
+ void 0,
15414
+ previousProgram
15415
+ );
15416
+ previousProgram = program;
15417
+ let parserOptions = {
15418
+ shouldExtractLiteralValuesFromEnum: !0,
15419
+ shouldRemoveUndefinedFromOptional: !0,
15420
+ ...userOptions,
15421
+ // Always force savePropValueAsString so default values are in a consistent format
15422
+ savePropValueAsString: !0
15423
+ };
15424
+ parser = {
15425
+ program,
15426
+ fileParser: reactDocgenTypescript.withCompilerOptions(cachedCompilerOptions, parserOptions)
15427
+ }, cachedParserOptionsKey = optionsKey;
15543
15428
  }
15544
- return parents.length > 0 ? parents : void 0;
15429
+ return { ...parser, typescript };
15545
15430
  }
15546
- function serializeType(typescript, checker, type, isRequired, depth = 0) {
15547
- if (depth > MAX_SERIALIZATION_DEPTH)
15548
- return { name: checker.typeToString(type) };
15549
- if (type.isUnion()) {
15550
- let nonUndefinedTypes = type.types.filter(
15551
- (t6) => !(t6.getFlags() & typescript.TypeFlags.Undefined)
15552
- ), literalMembers = nonUndefinedTypes.filter(isLiteralType);
15553
- if (literalMembers.length > 0 && literalMembers.length === nonUndefinedTypes.length)
15431
+ function matchComponentDoc(docs, {
15432
+ importName,
15433
+ localImportName,
15434
+ componentName
15435
+ }) {
15436
+ if (docs.length !== 0)
15437
+ return docs.length === 1 ? docs[0] : docs.find(
15438
+ (doc) => doc.exportName === importName || doc.exportName === localImportName || doc.displayName === importName || doc.displayName === localImportName || doc.displayName === componentName
15439
+ );
15440
+ }
15441
+ function getReactDocgenTypescriptError(path5, {
15442
+ importName,
15443
+ localImportName,
15444
+ componentName
15445
+ }, docs) {
15446
+ return docs.length === 0 ? {
15447
+ name: "react-docgen-typescript found no component docs",
15448
+ message: [
15449
+ `File: ${path5}`,
15450
+ "react-docgen-typescript did not return any component docs for this file."
15451
+ ].join(`
15452
+ `)
15453
+ } : {
15454
+ name: "react-docgen-typescript could not match component docs",
15455
+ message: [
15456
+ `File: ${path5}`,
15457
+ "react-docgen-typescript returned component docs for this file, but none matched the story's component import.",
15458
+ `Looked for: componentName=${componentName}, localImportName=${localImportName ?? "<none>"}, importName=${importName ?? "<none>"}.`
15459
+ ].join(`
15460
+ `)
15461
+ };
15462
+ }
15463
+ var parseWithReactDocgenTypescript = asyncCache(
15464
+ async (filePath, userOptions) => {
15465
+ let { program, fileParser, typescript } = await getParser5(userOptions), checker = program.getTypeChecker(), sourceFile = program.getSourceFile(filePath), docs = fileParser.parseWithProgramProvider(filePath, () => program), exportNameMap = sourceFile ? getExportNameMap(typescript, checker, sourceFile) : /* @__PURE__ */ new Map();
15466
+ return docs.map((doc) => {
15467
+ let largeNonUserSources = getLargeNonUserPropSources(doc.props);
15554
15468
  return {
15555
- name: "enum",
15556
- raw: literalMembers.map((m) => checker.typeToString(m)).join(" | "),
15557
- value: literalMembers.map((m) => ({
15558
- value: JSON.stringify(m.value)
15559
- }))
15469
+ ...doc,
15470
+ // Use name-based lookup: displayName is the resolved symbol name, so look it up in the
15471
+ // export map to get the public export name. Falls back to displayName when not aliased.
15472
+ exportName: exportNameMap.get(doc.displayName) ?? doc.displayName,
15473
+ // Filter out bulk props from non-user sources (React built-ins, DOM, CSS-in-JS system props)
15474
+ props: Object.fromEntries(
15475
+ Object.entries(doc.props).filter(([, prop]) => {
15476
+ let source = getPropSource(prop);
15477
+ return !source || !largeNonUserSources.has(source);
15478
+ })
15479
+ )
15560
15480
  };
15561
- if (!isRequired && nonUndefinedTypes.length === 1 && nonUndefinedTypes.length < type.types.length)
15562
- return { name: checker.typeToString(nonUndefinedTypes[0]) };
15563
- }
15564
- let constraint = type.getConstraint?.();
15565
- return constraint && constraint !== type ? serializeType(typescript, checker, constraint, isRequired, depth + 1) : { name: checker.typeToString(type) };
15566
- }
15567
- function unwrapToFunction(typescript, node, depth = 0, checker) {
15568
- if (!(depth > MAX_UNWRAP_DEPTH)) {
15569
- if (typescript.isArrowFunction(node) || typescript.isFunctionExpression(node) || typescript.isFunctionDeclaration(node))
15570
- return node;
15571
- if (typescript.isCallExpression(node))
15572
- for (let arg of node.arguments) {
15573
- let fn = unwrapToFunction(typescript, arg, depth + 1, checker);
15574
- if (fn)
15575
- return fn;
15481
+ });
15482
+ },
15483
+ { name: "parseWithReactDocgenTypescript" }
15484
+ );
15485
+
15486
+ // src/componentManifest/getComponentImports.ts
15487
+ var baseIdentifier = (component) => component.split(".")[0] ?? component, isTypeSpecifier = (s) => t2.isImportSpecifier(s) && s.importKind === "type", importedName = (im) => t2.isIdentifier(im) ? im.name : im.value, addUniqueBy = (arr, item, eq2) => {
15488
+ arr.find(eq2) || arr.push(item);
15489
+ }, getComponents = async ({
15490
+ csf,
15491
+ storyFilePath,
15492
+ typescriptOptions = {},
15493
+ docgenEngine,
15494
+ additionalComponentNames = []
15495
+ }) => {
15496
+ let { reactDocgenTypescriptOptions } = typescriptOptions, program = csf._file.path, componentSet = /* @__PURE__ */ new Set(), componentDepth = /* @__PURE__ */ new Map(), localToImport = /* @__PURE__ */ new Map(), jsxDepth = 0;
15497
+ program.traverse({
15498
+ JSXElement: {
15499
+ enter() {
15500
+ jsxDepth++;
15501
+ },
15502
+ exit() {
15503
+ jsxDepth--;
15576
15504
  }
15577
- if (typescript.isParenthesizedExpression(node) || typescript.isAsExpression(node))
15578
- return unwrapToFunction(typescript, node.expression, depth + 1, checker);
15579
- if (typescript.isIdentifier(node) && checker) {
15580
- let symbol = checker.getSymbolAtLocation(node);
15581
- if (symbol) {
15582
- let decl = (symbol.flags & typescript.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol).valueDeclaration;
15583
- if (decl && typescript.isVariableDeclaration(decl) && decl.initializer)
15584
- return unwrapToFunction(typescript, decl.initializer, depth + 1, checker);
15585
- if (decl && typescript.isFunctionDeclaration(decl))
15586
- return decl;
15505
+ },
15506
+ JSXOpeningElement(p) {
15507
+ let n = p.node.name, name;
15508
+ if (t2.isJSXIdentifier(n))
15509
+ name = n.name, name && /[A-Z]/.test(name.charAt(0)) && componentSet.add(name);
15510
+ else if (t2.isJSXMemberExpression(n)) {
15511
+ let jsxNameToString = (nm) => t2.isJSXIdentifier(nm) ? nm.name : `${jsxNameToString(nm.object)}.${jsxNameToString(nm.property)}`;
15512
+ name = jsxNameToString(n), componentSet.add(name);
15513
+ }
15514
+ if (name) {
15515
+ let depth = jsxDepth - 1, existing = componentDepth.get(name);
15516
+ (existing === void 0 || depth < existing) && componentDepth.set(name, depth);
15587
15517
  }
15588
15518
  }
15519
+ });
15520
+ let metaComp = csf._meta?.component;
15521
+ metaComp && componentSet.add(metaComp);
15522
+ for (let componentName of additionalComponentNames)
15523
+ componentSet.add(componentName);
15524
+ let components = Array.from(componentSet).sort((a, b) => a.localeCompare(b)), body = program.get("body");
15525
+ for (let stmt of body) {
15526
+ if (!stmt.isImportDeclaration())
15527
+ continue;
15528
+ let decl = stmt.node;
15529
+ if (decl.importKind === "type")
15530
+ continue;
15531
+ let specifiers = decl.specifiers ?? [];
15532
+ if (specifiers.length !== 0)
15533
+ for (let s of specifiers) {
15534
+ if (!("local" in s) || !s.local || isTypeSpecifier(s))
15535
+ continue;
15536
+ let importId = decl.source.value;
15537
+ if (t2.isImportDefaultSpecifier(s))
15538
+ localToImport.set(s.local.name, { importId, importName: "default" });
15539
+ else if (t2.isImportNamespaceSpecifier(s))
15540
+ localToImport.set(s.local.name, { importId, importName: "*" });
15541
+ else if (t2.isImportSpecifier(s)) {
15542
+ let imported = importedName(s.imported);
15543
+ localToImport.set(s.local.name, { importId, importName: imported });
15544
+ }
15545
+ }
15589
15546
  }
15590
- }
15591
- function resolveLiteralValue(typescript, checker, node, depth = 0) {
15592
- if (depth > MAX_UNWRAP_DEPTH || typescript.isStringLiteral(node) || typescript.isNumericLiteral(node) || typescript.isNoSubstitutionTemplateLiteral(node) || node.kind === typescript.SyntaxKind.TrueKeyword || node.kind === typescript.SyntaxKind.FalseKeyword || node.kind === typescript.SyntaxKind.NullKeyword)
15593
- return node.getText();
15594
- if (typescript.isIdentifier(node)) {
15595
- if (node.text === "undefined")
15596
- return "undefined";
15597
- let symbol = checker.getSymbolAtLocation(node);
15598
- if (!symbol)
15599
- return node.getText();
15600
- let decl = (symbol.flags & typescript.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol).valueDeclaration;
15601
- return decl && typescript.isVariableDeclaration(decl) && decl.initializer || decl && typescript.isEnumMember(decl) && decl.initializer || decl && typescript.isBindingElement(decl) && decl.initializer ? resolveLiteralValue(typescript, checker, decl.initializer, depth + 1) : node.getText();
15602
- }
15603
- if (typescript.isPropertyAccessExpression(node)) {
15604
- let symbol = checker.getSymbolAtLocation(node);
15605
- if (symbol) {
15606
- let decl = symbol.valueDeclaration;
15607
- if (decl && typescript.isEnumMember(decl) && decl.initializer || decl && typescript.isPropertyAssignment(decl) && decl.initializer || decl && typescript.isVariableDeclaration(decl) && decl.initializer)
15608
- return resolveLiteralValue(typescript, checker, decl.initializer, depth + 1);
15609
- }
15610
- return node.getText();
15611
- }
15612
- return node.getText();
15613
- }
15614
- function collectBindingDefaults(typescript, pattern, defaults, checker) {
15615
- for (let element of pattern.elements)
15616
- if (element.initializer) {
15617
- let propName = element.propertyName ? element.propertyName.getText() : element.name.getText();
15618
- defaults.set(
15619
- propName,
15620
- checker ? resolveLiteralValue(typescript, checker, element.initializer) : element.initializer.getText()
15621
- );
15622
- }
15623
- }
15624
- function unwrapExpression(typescript, expression) {
15625
- let current2 = expression;
15626
- for (; isWrappedExpression(typescript, current2); )
15627
- current2 = current2.expression;
15628
- return current2;
15629
- }
15630
- function isPropsIdentifier(typescript, node, paramName, checker) {
15631
- if (!typescript.isIdentifier(node))
15632
- return !1;
15633
- if (!checker)
15634
- return node.text === paramName.text;
15635
- let symbol = checker.getSymbolAtLocation(node), paramSymbol = checker.getSymbolAtLocation(paramName);
15636
- return symbol !== void 0 && symbol === paramSymbol;
15637
- }
15638
- function isPropsDerivedInitializer(typescript, initializer, paramName, checker) {
15639
- let expr = unwrapExpression(typescript, initializer);
15640
- return isPropsIdentifier(typescript, expr, paramName, checker) ? !0 : typescript.isAwaitExpression(expr) ? isPropsDerivedInitializer(typescript, expr.expression, paramName, checker) : typescript.isBinaryExpression(expr) && [
15641
- typescript.SyntaxKind.BarBarToken,
15642
- typescript.SyntaxKind.QuestionQuestionToken,
15643
- typescript.SyntaxKind.AmpersandAmpersandToken
15644
- ].includes(expr.operatorToken.kind) ? isPropsDerivedInitializer(typescript, expr.left, paramName, checker) || isPropsDerivedInitializer(typescript, expr.right, paramName, checker) : typescript.isConditionalExpression(expr) ? isPropsDerivedInitializer(typescript, expr.whenTrue, paramName, checker) || isPropsDerivedInitializer(typescript, expr.whenFalse, paramName, checker) : typescript.isCallExpression(expr) || typescript.isNewExpression(expr) ? expr.arguments?.some(
15645
- (arg) => isPropsDerivedInitializer(typescript, arg, paramName, checker)
15646
- ) ?? !1 : !1;
15647
- }
15648
- function extractDestructuringDefaults(typescript, resolved, checker) {
15649
- let defaults = /* @__PURE__ */ new Map(), decl = resolved.valueDeclaration;
15650
- if (!decl)
15651
- return defaults;
15652
- let fn;
15653
- if (typescript.isFunctionDeclaration(decl)) {
15654
- if (fn = decl, !fn.body) {
15655
- let allDecls = resolved.getDeclarations?.() ?? [];
15656
- for (let d of allDecls)
15657
- if (typescript.isFunctionDeclaration(d) && d.body) {
15658
- fn = d;
15659
- break;
15547
+ let isLocallyDefinedWithoutImport = (base2) => {
15548
+ let binding = program.scope.getBinding(base2);
15549
+ return binding ? !!!(binding.path.isImportSpecifier?.() || binding.path.isImportDefaultSpecifier?.() || binding.path.isImportNamespaceSpecifier?.()) : !1;
15550
+ }, filteredComponents = components.filter(
15551
+ (c) => !isLocallyDefinedWithoutImport(baseIdentifier(c))
15552
+ );
15553
+ return (await Promise.all(
15554
+ filteredComponents.map(async (c) => {
15555
+ let depth = componentDepth.get(c), dot = c.indexOf("."), component = dot !== -1 ? (() => {
15556
+ let ns = c.slice(0, dot), mem = c.slice(dot + 1), direct = localToImport.get(ns);
15557
+ return direct ? direct.importName === "*" ? {
15558
+ componentName: c,
15559
+ localImportName: ns,
15560
+ importId: direct.importId,
15561
+ importName: mem,
15562
+ namespace: ns,
15563
+ member: mem,
15564
+ jsxDepth: depth
15565
+ } : {
15566
+ componentName: c,
15567
+ localImportName: ns,
15568
+ importId: direct.importId,
15569
+ importName: direct.importName,
15570
+ member: mem,
15571
+ jsxDepth: depth
15572
+ } : { componentName: c, member: mem, jsxDepth: depth };
15573
+ })() : (() => {
15574
+ let direct = localToImport.get(c);
15575
+ return direct ? {
15576
+ componentName: c,
15577
+ localImportName: c,
15578
+ importId: direct.importId,
15579
+ importName: direct.importName,
15580
+ jsxDepth: depth
15581
+ } : { componentName: c, jsxDepth: depth };
15582
+ })(), path5, isPackage = !1;
15583
+ try {
15584
+ component.importId && storyFilePath && (path5 = cachedResolveImport(matchPath(component.importId, dirname6(storyFilePath)), {
15585
+ basedir: dirname6(storyFilePath)
15586
+ }));
15587
+ } catch (e) {
15588
+ logger6.debug(e);
15589
+ }
15590
+ try {
15591
+ component.importId && !component.importId.startsWith(".") && storyFilePath && (cachedResolveImport(component.importId, { basedir: dirname6(storyFilePath) }), isPackage = !0);
15592
+ } catch {
15593
+ }
15594
+ let componentWithPackage = { ...component, isPackage };
15595
+ if (path5) {
15596
+ if (docgenEngine === "react-docgen-typescript") {
15597
+ let reactDocgenTypescript, reactDocgenTypescriptError;
15598
+ try {
15599
+ let docs = await parseWithReactDocgenTypescript(path5, reactDocgenTypescriptOptions);
15600
+ reactDocgenTypescript = matchComponentDoc(docs, component), reactDocgenTypescript || (reactDocgenTypescriptError = getReactDocgenTypescriptError(path5, component, docs));
15601
+ } catch (e) {
15602
+ let message = e instanceof Error ? e.message : String(e);
15603
+ logger6.debug(`react-docgen-typescript failed for ${path5}: ${message}`), reactDocgenTypescriptError = {
15604
+ name: "react-docgen-typescript parse error",
15605
+ message: `File: ${path5}
15606
+ ${message}`
15607
+ };
15608
+ }
15609
+ let importOverride = reactDocgenTypescript ? getImportTag(reactDocgenTypescript) : void 0;
15610
+ return {
15611
+ ...componentWithPackage,
15612
+ path: path5,
15613
+ ...reactDocgenTypescript ? { reactDocgenTypescript } : {},
15614
+ ...reactDocgenTypescriptError ? { reactDocgenTypescriptError } : {},
15615
+ importOverride
15616
+ };
15660
15617
  }
15661
- }
15662
- } else typescript.isVariableDeclaration(decl) && decl.initializer ? fn = unwrapToFunction(typescript, decl.initializer, 0, checker) : typescript.isExportAssignment(decl) && decl.expression && (fn = unwrapToFunction(typescript, decl.expression, 0, checker));
15663
- if (!fn)
15664
- return defaults;
15665
- let firstParam = fn.parameters[0];
15666
- if (!firstParam)
15667
- return defaults;
15668
- if (typescript.isObjectBindingPattern(firstParam.name))
15669
- return collectBindingDefaults(typescript, firstParam.name, defaults, checker), defaults;
15670
- let propsParamName = typescript.isIdentifier(firstParam.name) ? firstParam.name : void 0;
15671
- if (fn.body && propsParamName) {
15672
- let body = typescript.isBlock(fn.body) ? fn.body : void 0;
15673
- if (body) {
15674
- for (let stmt of body.statements)
15675
- if (typescript.isVariableStatement(stmt))
15676
- for (let varDecl of stmt.declarationList.declarations)
15677
- typescript.isObjectBindingPattern(varDecl.name) && varDecl.initializer && isPropsDerivedInitializer(typescript, varDecl.initializer, propsParamName, checker) && collectBindingDefaults(typescript, varDecl.name, defaults, checker);
15678
- }
15679
- }
15680
- return defaults;
15681
- }
15682
- function collectObjectLiteralDefaults(typescript, checker, obj, defaults) {
15683
- for (let prop of obj.properties)
15684
- if (typescript.isPropertyAssignment(prop) && prop.name) {
15685
- let name = prop.name.getText();
15686
- defaults.set(name, resolveLiteralValue(typescript, checker, prop.initializer));
15687
- } else if (typescript.isShorthandPropertyAssignment(prop)) {
15688
- let name = prop.name.getText(), symbol = checker.getShorthandAssignmentValueSymbol(prop);
15689
- symbol?.valueDeclaration && typescript.isVariableDeclaration(symbol.valueDeclaration) && symbol.valueDeclaration.initializer ? defaults.set(
15690
- name,
15691
- resolveLiteralValue(typescript, checker, symbol.valueDeclaration.initializer)
15692
- ) : defaults.set(name, name);
15693
- }
15694
- }
15695
- function extractStaticDefaultProps(typescript, checker, resolved) {
15696
- let defaults = /* @__PURE__ */ new Map(), decl = resolved.valueDeclaration ?? resolved.getDeclarations()?.[0];
15697
- if (!decl)
15698
- return defaults;
15699
- let componentSourceFile = decl.getSourceFile();
15700
- for (let stmt of componentSourceFile.statements) {
15701
- if (typescript.isClassDeclaration(stmt) && stmt.name) {
15702
- if (checker.getSymbolAtLocation(stmt.name) !== resolved)
15618
+ if (docgenEngine === "react-docgen") {
15619
+ let reactDocgen = getReactDocgen(path5, componentWithPackage);
15620
+ return {
15621
+ ...componentWithPackage,
15622
+ path: path5,
15623
+ reactDocgen,
15624
+ importOverride: reactDocgen.type === "success" ? getImportTag(reactDocgen.data) : void 0
15625
+ };
15626
+ }
15627
+ if (docgenEngine === "react-component-meta")
15628
+ return {
15629
+ ...componentWithPackage,
15630
+ path: path5
15631
+ };
15632
+ }
15633
+ return componentWithPackage;
15634
+ })
15635
+ )).sort((a, b) => a.componentName.localeCompare(b.componentName));
15636
+ }, getImports = ({
15637
+ components,
15638
+ packageName
15639
+ }) => {
15640
+ let withSource = components.filter((c) => !!c.importId).map((c, idx) => {
15641
+ let importId = c.importId, overrideSource = (() => {
15642
+ if (c.importOverride)
15643
+ try {
15644
+ let src = babelParse2(c.importOverride).program.body.find((n) => t2.isImportDeclaration(n))?.source?.value;
15645
+ return typeof src == "string" ? src : void 0;
15646
+ } catch {
15647
+ return;
15648
+ }
15649
+ })(), rewritten = overrideSource !== void 0 ? overrideSource : (
15650
+ // only rewrite to the package name it the import id is not already a valid package
15651
+ // tsconfig paths such as ~/components/Button and components/Button are not seen as packages
15652
+ packageName && !c.isPackage ? packageName : importId
15653
+ );
15654
+ return { c, src: t2.stringLiteral(rewritten), key: rewritten, ord: idx };
15655
+ }), orderOfSource = {};
15656
+ for (let w of withSource)
15657
+ orderOfSource[w.key] === void 0 && (orderOfSource[w.key] = w.ord);
15658
+ let buckets = /* @__PURE__ */ new Map(), ensureBucket = (key, src) => {
15659
+ let prev = buckets.get(key);
15660
+ if (prev)
15661
+ return prev;
15662
+ let b = {
15663
+ source: src,
15664
+ defaults: [],
15665
+ namespaces: [],
15666
+ named: [],
15667
+ order: orderOfSource[key] ?? 0
15668
+ };
15669
+ return buckets.set(key, b), b;
15670
+ };
15671
+ for (let { c, src, key } of withSource) {
15672
+ let b = ensureBucket(key, src), rewritten = src.value !== c.importId, overrideSpec = (() => {
15673
+ if (c.importOverride)
15674
+ try {
15675
+ let decl = babelParse2(c.importOverride).program.body.find((n) => t2.isImportDeclaration(n));
15676
+ if (!decl)
15677
+ return;
15678
+ let spec = (decl.specifiers ?? []).find((s) => !isTypeSpecifier(s));
15679
+ return spec ? t2.isImportNamespaceSpecifier(spec) ? { kind: "namespace", local: spec.local.name } : t2.isImportDefaultSpecifier(spec) ? { kind: "default" } : t2.isImportSpecifier(spec) ? { kind: "named", imported: t2.isIdentifier(spec.imported) ? spec.imported.name : spec.imported.value } : void 0 : void 0;
15680
+ } catch {
15681
+ return;
15682
+ }
15683
+ })();
15684
+ if (overrideSpec) {
15685
+ if (overrideSpec.kind === "namespace") {
15686
+ let ns = t2.identifier(overrideSpec.local);
15687
+ addUniqueBy(b.namespaces, ns, (n) => n.name === ns.name);
15703
15688
  continue;
15704
- for (let member of stmt.members) {
15705
- if (!typescript.isPropertyDeclaration(member) || !member.name || member.name.getText() !== "defaultProps" || !member.initializer)
15689
+ }
15690
+ if (!c.localImportName)
15691
+ continue;
15692
+ if (overrideSpec.kind === "default") {
15693
+ let id = t2.identifier(c.localImportName);
15694
+ addUniqueBy(b.defaults, id, (d) => d.name === id.name);
15695
+ continue;
15696
+ }
15697
+ if (overrideSpec.kind === "named") {
15698
+ let local = t2.identifier(c.localImportName), imported = t2.identifier(overrideSpec.imported);
15699
+ addUniqueBy(
15700
+ b.named,
15701
+ t2.importSpecifier(local, imported),
15702
+ (n) => n.local.name === local.name && importedName(n.imported) === imported.name
15703
+ );
15704
+ continue;
15705
+ }
15706
+ }
15707
+ if (c.namespace) {
15708
+ if (rewritten) {
15709
+ if (!c.importName)
15706
15710
  continue;
15707
- let initializer = member.initializer;
15708
- if (typescript.isIdentifier(initializer)) {
15709
- let symDecl = checker.getSymbolAtLocation(initializer)?.valueDeclaration;
15710
- symDecl && typescript.isVariableDeclaration(symDecl) && symDecl.initializer && (initializer = symDecl.initializer);
15711
- }
15712
- typescript.isObjectLiteralExpression(initializer) && collectObjectLiteralDefaults(typescript, checker, initializer, defaults);
15711
+ let member = c.importName, id = t2.identifier(member);
15712
+ addUniqueBy(
15713
+ b.named,
15714
+ t2.importSpecifier(id, id),
15715
+ (n) => n.local.name === member && importedName(n.imported) === member
15716
+ );
15717
+ } else {
15718
+ let ns = t2.identifier(c.namespace);
15719
+ addUniqueBy(b.namespaces, ns, (n) => n.name === ns.name);
15713
15720
  }
15721
+ continue;
15714
15722
  }
15715
- if (typescript.isExpressionStatement(stmt) && typescript.isBinaryExpression(stmt.expression) && stmt.expression.operatorToken.kind === typescript.SyntaxKind.EqualsToken) {
15716
- let left = stmt.expression.left;
15717
- if (!typescript.isPropertyAccessExpression(left) || left.name.text !== "defaultProps")
15718
- continue;
15719
- let targetSymbol = checker.getSymbolAtLocation(left.expression);
15720
- if (!targetSymbol || (targetSymbol.flags & typescript.SymbolFlags.Alias ? checker.getAliasedSymbol(targetSymbol) : targetSymbol) !== resolved)
15723
+ if (c.importName === "default") {
15724
+ if (!c.localImportName)
15721
15725
  continue;
15722
- let right = stmt.expression.right;
15723
- if (typescript.isIdentifier(right)) {
15724
- let symDecl = checker.getSymbolAtLocation(right)?.valueDeclaration;
15725
- symDecl && typescript.isVariableDeclaration(symDecl) && symDecl.initializer && (right = symDecl.initializer);
15726
+ if (rewritten) {
15727
+ let id = t2.identifier(c.localImportName);
15728
+ addUniqueBy(
15729
+ b.named,
15730
+ t2.importSpecifier(id, id),
15731
+ (n) => n.local.name === id.name && importedName(n.imported) === id.name
15732
+ );
15733
+ } else {
15734
+ let id = t2.identifier(c.localImportName);
15735
+ addUniqueBy(b.defaults, id, (d) => d.name === id.name);
15726
15736
  }
15727
- typescript.isObjectLiteralExpression(right) && collectObjectLiteralDefaults(typescript, checker, right, defaults);
15737
+ continue;
15738
+ }
15739
+ if (c.importName) {
15740
+ if (!c.localImportName)
15741
+ continue;
15742
+ let local = t2.identifier(c.localImportName), imported = t2.identifier(c.importName);
15743
+ addUniqueBy(
15744
+ b.named,
15745
+ t2.importSpecifier(local, imported),
15746
+ (n) => n.local.name === local.name && importedName(n.imported) === imported.name
15747
+ );
15748
+ continue;
15728
15749
  }
15729
15750
  }
15730
- return defaults;
15731
- }
15732
- function getJSDocDefault(typescript, prop, checker) {
15733
- let tags = prop.getJsDocTags(checker);
15734
- for (let tag of tags)
15735
- if (tag.name === "default" || tag.name === "defaultValue")
15736
- return typescript.displayPartsToString(tag.text) || void 0;
15737
- }
15738
- function extractPropItem(typescript, checker, prop, contextNode, defaultsMap) {
15739
- let isRequired = !!!(prop.flags & typescript.SymbolFlags.Optional), propType = checker.getTypeOfSymbolAtLocation(prop, contextNode), type = serializeType(typescript, checker, propType, isRequired), description = typescript.displayPartsToString(prop.getDocumentationComment(checker)), parent = getParentType(typescript, prop), declarations = getAllDeclarationParents(typescript, prop), propName = prop.getName(), destructuringDefault = defaultsMap?.get(propName), jsDocDefault = getJSDocDefault(typescript, prop, checker), defaultStr = destructuringDefault ?? jsDocDefault;
15740
- return {
15741
- name: propName,
15742
- required: isRequired,
15743
- type,
15744
- description,
15745
- defaultValue: defaultStr !== void 0 ? { value: defaultStr } : null,
15746
- parent,
15747
- declarations
15748
- };
15749
- }
15750
- function getBulkSourceExclusions(properties) {
15751
- let propSourceCache = /* @__PURE__ */ new Map(), getSource = (prop) => {
15752
- let cached2 = propSourceCache.get(prop);
15753
- return cached2 === void 0 && !propSourceCache.has(prop) && (cached2 = getPropSourceFile(prop), propSourceCache.set(prop, cached2)), cached2;
15754
- }, sourceCount = /* @__PURE__ */ new Map();
15755
- for (let prop of properties) {
15756
- let source = getSource(prop);
15757
- source && (source.includes("node_modules") || source.endsWith(".d.ts")) && sourceCount.set(source, (sourceCount.get(source) ?? 0) + 1);
15751
+ let merged = [], printDecl = (specs, src) => {
15752
+ let node = t2.importDeclaration(specs, src), code = recast.print(node, {}).code;
15753
+ merged.push(code);
15754
+ }, sortedBuckets = Array.from(buckets.values()).sort((a, b) => a.order - b.order);
15755
+ for (let bucket of sortedBuckets) {
15756
+ let { source, defaults, namespaces, named } = bucket;
15757
+ if (!(defaults.length === 0 && namespaces.length === 0 && named.length === 0))
15758
+ if (namespaces.length > 0) {
15759
+ let firstSpecs = [];
15760
+ defaults[0] && firstSpecs.push(t2.importDefaultSpecifier(defaults[0])), firstSpecs.push(t2.importNamespaceSpecifier(namespaces[0])), printDecl(firstSpecs, source), named.length > 0 && printDecl(named, source);
15761
+ for (let d of defaults.slice(1))
15762
+ printDecl([t2.importDefaultSpecifier(d)], source);
15763
+ for (let ns of namespaces.slice(1))
15764
+ printDecl([t2.importNamespaceSpecifier(ns)], source);
15765
+ } else {
15766
+ if (defaults.length > 0 || named.length > 0) {
15767
+ let specs = [];
15768
+ defaults[0] && specs.push(t2.importDefaultSpecifier(defaults[0])), specs.push(...named), printDecl(specs, source);
15769
+ }
15770
+ for (let d of defaults.slice(1))
15771
+ printDecl([t2.importDefaultSpecifier(d)], source);
15772
+ }
15758
15773
  }
15759
- let bulkSources = new Set(
15760
- [...sourceCount.entries()].filter(([, count]) => count > LARGE_SOURCE_THRESHOLD).map(([source]) => source)
15761
- ), excluded = /* @__PURE__ */ new Set();
15762
- for (let prop of properties) {
15763
- let source = getSource(prop);
15764
- source && bulkSources.has(source) && excluded.add(prop.getName());
15774
+ return merged;
15775
+ };
15776
+
15777
+ // src/componentManifest/resolveComponents.ts
15778
+ import { recast as recast2 } from "storybook/internal/babel";
15779
+ import { storyNameFromExport } from "storybook/internal/csf";
15780
+ import { extractDescription, loadCsf } from "storybook/internal/csf-tools";
15781
+
15782
+ // src/componentManifest/generateCodeSnippet.ts
15783
+ import { types as t3 } from "storybook/internal/babel";
15784
+ function getCodeSnippet(csf, storyName, componentName) {
15785
+ let storyDeclaration = csf._storyDeclarationPath[storyName], metaObj = csf._metaNode;
15786
+ if (!storyDeclaration) {
15787
+ let message = "Expected story to be a function or variable declaration";
15788
+ throw csf._storyPaths[storyName]?.buildCodeFrameError(message) ?? message;
15765
15789
  }
15766
- return excluded;
15767
- }
15768
- function computeDisplayName({
15769
- exportSymbol,
15770
- resolvedSymbol
15771
- }) {
15772
- let resolvedName = resolvedSymbol.getName();
15773
- if (!exportSymbol)
15774
- return resolvedName && resolvedName !== "default" && resolvedName !== "__function" ? resolvedName : void 0;
15775
- let exportName = exportSymbol.getName();
15776
- return exportName === "default" ? resolvedName && resolvedName !== "default" && resolvedName !== "__function" ? resolvedName : void 0 : exportName;
15790
+ let storyPath;
15791
+ if (storyDeclaration.isFunctionDeclaration())
15792
+ storyPath = storyDeclaration;
15793
+ else if (storyDeclaration.isVariableDeclarator()) {
15794
+ let init = storyDeclaration.get("init");
15795
+ invariant(
15796
+ init.isExpression(),
15797
+ () => storyDeclaration.buildCodeFrameError("Expected story initializer to be an expression").message
15798
+ ), storyPath = init;
15799
+ } else
15800
+ throw storyDeclaration.buildCodeFrameError(
15801
+ "Expected story to be a function or variable declaration"
15802
+ );
15803
+ let normalizedPath = storyPath;
15804
+ if (storyPath.isCallExpression()) {
15805
+ let callee = storyPath.get("callee");
15806
+ if (callee.isMemberExpression()) {
15807
+ let obj = callee.get("object"), prop = callee.get("property"), isBind = prop.isIdentifier() && prop.node.name === "bind" || t3.isStringLiteral(prop.node) && prop.node.value === "bind";
15808
+ if (obj.isIdentifier() && isBind) {
15809
+ let resolved = resolveIdentifierInit(storyDeclaration, obj);
15810
+ resolved && (normalizedPath = resolved);
15811
+ }
15812
+ }
15813
+ if (storyPath === normalizedPath) {
15814
+ let args = storyPath.get("arguments");
15815
+ if (args.length !== 0) {
15816
+ invariant(
15817
+ args.length === 1,
15818
+ () => storyPath.buildCodeFrameError("Could not evaluate story expression").message
15819
+ );
15820
+ let storyArg = args[0];
15821
+ invariant(
15822
+ storyArg.isExpression(),
15823
+ () => storyPath.buildCodeFrameError("Could not evaluate story expression").message
15824
+ ), normalizedPath = storyArg;
15825
+ }
15826
+ }
15827
+ }
15828
+ normalizedPath = normalizedPath.isTSSatisfiesExpression() || normalizedPath.isTSAsExpression() ? normalizedPath.get("expression") : normalizedPath;
15829
+ let storyFn;
15830
+ if (normalizedPath.isArrowFunctionExpression() || normalizedPath.isFunctionExpression() || normalizedPath.isFunctionDeclaration())
15831
+ storyFn = normalizedPath;
15832
+ else if (!normalizedPath.isObjectExpression() && !(normalizedPath.isCallExpression() && Array.isArray(normalizedPath.node.arguments) && normalizedPath.node.arguments.length === 0))
15833
+ throw normalizedPath.buildCodeFrameError(
15834
+ "Expected story to be csf factory, function or an object expression"
15835
+ );
15836
+ let storyProps = normalizedPath.isObjectExpression() ? normalizedPath.get("properties").filter((p) => p.isObjectProperty()) : [], metaPath = pathForNode(csf._file.path, metaObj), metaProps = metaPath?.isObjectExpression() ? metaPath.get("properties").filter((p) => p.isObjectProperty()) : [], getRenderPath = (object) => {
15837
+ let renderPath = object.find((p) => keyOf(p.node) === "render")?.get("value");
15838
+ if (!renderPath)
15839
+ return { kind: "missing" };
15840
+ if (renderPath.isIdentifier()) {
15841
+ let resolved = resolveIdentifierInit(storyDeclaration, renderPath);
15842
+ return resolved && (resolved.isArrowFunctionExpression() || resolved.isFunctionExpression() || resolved.isFunctionDeclaration()) ? { kind: "resolved", path: resolved } : { kind: "unresolved" };
15843
+ }
15844
+ if (!(renderPath.isArrowFunctionExpression() || renderPath.isFunctionExpression()))
15845
+ throw renderPath.buildCodeFrameError(
15846
+ "Expected render to be an arrow function or function expression"
15847
+ );
15848
+ return { kind: "resolved", path: renderPath };
15849
+ }, metaRender = getRenderPath(metaProps), storyRender = getRenderPath(storyProps);
15850
+ storyFn || (storyFn = storyRender.kind === "resolved" ? storyRender.path : storyRender.kind === "missing" && metaRender.kind === "resolved" ? metaRender.path : void 0);
15851
+ let metaArgs = metaArgsRecord(metaObj ?? null), storyArgsPath = storyProps.filter((p) => keyOf(p.node) === "args").map((p) => p.get("value")).find((v) => v.isObjectExpression()), storyArgs = argsRecordFromObjectPath(storyArgsPath), storyAssignedArgsPath = storyArgsAssignmentPath(csf._file.path, storyName), storyAssignedArgs = argsRecordFromObjectPath(storyAssignedArgsPath), merged = { ...metaArgs, ...storyArgs, ...storyAssignedArgs }, entries = Object.entries(merged).filter(([k]) => k !== "children"), validEntries = entries.filter(([k, v]) => isValidJsxAttrName(k) && v != null), invalidEntries = entries.filter(([k, v]) => !isValidJsxAttrName(k) && v != null), injectedAttrs = validEntries.map(([k, v]) => toAttr(k, v)).filter((a) => a != null);
15852
+ if (storyFn) {
15853
+ let fn = storyFn.node;
15854
+ if (t3.isArrowFunctionExpression(fn) && (t3.isJSXElement(fn.body) || t3.isJSXFragment(fn.body))) {
15855
+ let spreadRes = transformArgsSpreadsInJsx(fn.body, merged), inlineRes = inlineArgsInJsx(spreadRes.node, merged);
15856
+ if (spreadRes.changed || inlineRes.changed) {
15857
+ let newFn = t3.arrowFunctionExpression([], inlineRes.node, fn.async);
15858
+ return t3.variableDeclaration("const", [
15859
+ t3.variableDeclarator(t3.identifier(storyName), newFn)
15860
+ ]);
15861
+ }
15862
+ }
15863
+ let stmts = t3.isFunctionDeclaration(fn) || t3.isArrowFunctionExpression(fn) && t3.isBlockStatement(fn.body) || t3.isFunctionExpression(fn) && t3.isBlockStatement(fn.body) ? fn.body.body : void 0;
15864
+ if (stmts) {
15865
+ let changed = !1, newBody = stmts.map((stmt) => {
15866
+ if (t3.isReturnStatement(stmt) && stmt.argument && (t3.isJSXElement(stmt.argument) || t3.isJSXFragment(stmt.argument))) {
15867
+ let spreadRes = transformArgsSpreadsInJsx(stmt.argument, merged), inlineRes = inlineArgsInJsx(spreadRes.node, merged);
15868
+ if (spreadRes.changed || inlineRes.changed)
15869
+ return changed = !0, t3.returnStatement(inlineRes.node);
15870
+ }
15871
+ return stmt;
15872
+ });
15873
+ if (changed)
15874
+ return t3.isFunctionDeclaration(fn) ? t3.functionDeclaration(
15875
+ t3.identifier(storyName),
15876
+ [],
15877
+ t3.blockStatement(newBody),
15878
+ fn.generator,
15879
+ fn.async
15880
+ ) : t3.variableDeclaration("const", [
15881
+ t3.variableDeclarator(
15882
+ t3.identifier(storyName),
15883
+ t3.arrowFunctionExpression([], t3.blockStatement(newBody), fn.async)
15884
+ )
15885
+ ]);
15886
+ }
15887
+ return t3.isFunctionDeclaration(fn) ? t3.functionDeclaration(t3.identifier(storyName), fn.params, fn.body, fn.generator, fn.async) : t3.variableDeclaration("const", [t3.variableDeclarator(t3.identifier(storyName), fn)]);
15888
+ }
15889
+ invariant(componentName, "Could not generate snippet without component name.");
15890
+ let invalidSpread = buildInvalidSpread(invalidEntries), name = t3.jsxIdentifier(componentName), openingElAttrs = invalidSpread ? [...injectedAttrs, invalidSpread] : injectedAttrs, children = toJsxChildren(merged.children), selfClosing = children.length === 0, arrow = t3.arrowFunctionExpression(
15891
+ [],
15892
+ t3.jsxElement(
15893
+ t3.jsxOpeningElement(name, openingElAttrs, selfClosing),
15894
+ selfClosing ? null : t3.jsxClosingElement(name),
15895
+ children,
15896
+ selfClosing
15897
+ )
15898
+ );
15899
+ return t3.variableDeclaration("const", [t3.variableDeclarator(t3.identifier(storyName), arrow)]);
15777
15900
  }
15778
- function extractComponentJsDocTags(typescript, checker, symbol) {
15779
- let tags = symbol.getJsDocTags(checker);
15780
- if (tags.length === 0)
15781
- return;
15782
- let groupedTags = groupBy(tags, (tag) => tag.name);
15783
- return Object.fromEntries(
15784
- Object.entries(groupedTags).map(([name, grouped]) => [
15785
- name,
15786
- (grouped ?? []).map((tag) => typescript.displayPartsToString(tag.text ?? []).trim())
15787
- ])
15901
+ function buildInvalidSpread(entries) {
15902
+ if (entries.length === 0)
15903
+ return null;
15904
+ let objectProps = entries.map(
15905
+ ([k, v]) => t3.objectProperty(t3.stringLiteral(k), t3.isExpression(v) ? v : t3.identifier("undefined"))
15788
15906
  );
15907
+ return t3.jsxSpreadAttribute(t3.objectExpression(objectProps));
15789
15908
  }
15790
- function serializeComponentDoc(typescript, checker, {
15791
- sourceFile,
15792
- resolvedComponent,
15793
- defaultsSourcePath
15794
- }) {
15795
- let { componentRef, propsType, symbol } = resolvedComponent, exportName = componentRef.importName;
15796
- if (!exportName)
15797
- return;
15798
- let displayNameOverride = componentRef.componentName, isMemberSelection = !!componentRef.member, filePath = componentRef.path ?? sourceFile.fileName, resolved = resolveAliasedSymbol(typescript, checker, symbol), contextNode = resolved.valueDeclaration ?? resolved.getDeclarations()?.[0];
15799
- if (!contextNode)
15800
- return;
15801
- let moduleSymbol = checker.getSymbolAtLocation(sourceFile), exportSymbol = moduleSymbol ? checker.getExportsOfModule(moduleSymbol).find((candidate) => candidate.getName() === exportName) : void 0, allProperties, unionForceOptional;
15802
- if (isUnionType(propsType)) {
15803
- let seen = /* @__PURE__ */ new Map(), forceOptional = /* @__PURE__ */ new Set(), unionMembers = propsType.types, allMemberPropSets = [];
15804
- for (let member of unionMembers) {
15805
- let memberPropNames = /* @__PURE__ */ new Set();
15806
- for (let prop of member.getApparentProperties()) {
15807
- let name = prop.getName();
15808
- memberPropNames.add(name);
15809
- let propType = checker.getTypeOfSymbolAtLocation(prop, contextNode), isOptional = !!(prop.flags & typescript.SymbolFlags.Optional), isDegraded = !!(propType.getFlags() & typescript.TypeFlags.Never) || !!(propType.getFlags() & typescript.TypeFlags.Undefined);
15810
- (isOptional || isDegraded) && forceOptional.add(name);
15811
- let existing = seen.get(name);
15812
- if (!existing)
15813
- seen.set(name, prop);
15814
- else if (!isDegraded) {
15815
- let existingType = checker.getTypeOfSymbolAtLocation(existing, contextNode);
15816
- (!!(existingType.getFlags() & typescript.TypeFlags.Never) || !!(existingType.getFlags() & typescript.TypeFlags.Undefined)) && seen.set(name, prop);
15817
- }
15909
+ var keyOf = (p) => t3.isIdentifier(p.key) ? p.key.name : t3.isStringLiteral(p.key) ? p.key.value : null, isValidJsxAttrName = (n) => /^[A-Za-z_][A-Za-z0-9_:-]*$/.test(n), argsRecordFromObjectPath = (objPath) => objPath ? Object.fromEntries(
15910
+ objPath.get("properties").filter((p) => p.isObjectProperty()).map((p) => [keyOf(p.node), p.get("value").node]).filter((e) => !!e[0])
15911
+ ) : {};
15912
+ function storyArgsAssignmentPath(program, storyName) {
15913
+ let found = null;
15914
+ return program.traverse({
15915
+ AssignmentExpression(p) {
15916
+ let left = p.get("left"), right = p.get("right");
15917
+ if (left.isMemberExpression()) {
15918
+ let obj = left.get("object"), prop = left.get("property"), isStoryIdent = obj.isIdentifier() && obj.node.name === storyName, isArgsProp = prop.isIdentifier() && prop.node.name === "args" && !left.node.computed || t3.isStringLiteral(prop.node) && left.node.computed && prop.node.value === "args";
15919
+ isStoryIdent && isArgsProp && right.isObjectExpression() && (found = right);
15818
15920
  }
15819
- allMemberPropSets.push(memberPropNames);
15820
15921
  }
15821
- for (let name of seen.keys())
15822
- allMemberPropSets.every((s) => s.has(name)) || forceOptional.add(name);
15823
- allProperties = Array.from(seen.values()), unionForceOptional = forceOptional;
15824
- } else
15825
- allProperties = propsType.getApparentProperties();
15826
- let excluded = getBulkSourceExclusions(allProperties), defaultsMap = extractDestructuringDefaults(typescript, resolved, checker);
15827
- if (defaultsMap.size === 0 && defaultsSourcePath) {
15828
- let fallbackDefaults = extractDefaultsFromSourceFile(typescript, defaultsSourcePath, {
15829
- exportName,
15830
- localName: resolved.getName(),
15831
- preferLocalName: isMemberSelection
15832
- });
15833
- for (let [key, value] of fallbackDefaults)
15834
- defaultsMap.set(key, value);
15922
+ }), found;
15923
+ }
15924
+ var argsRecordFromObjectNode = (obj) => obj ? Object.fromEntries(
15925
+ obj.properties.filter((p) => t3.isObjectProperty(p)).map((p) => [keyOf(p), p.value]).filter((e) => !!e[0])
15926
+ ) : {}, metaArgsRecord = (meta) => {
15927
+ if (!meta)
15928
+ return {};
15929
+ let argsProp = meta.properties.find(
15930
+ (p) => t3.isObjectProperty(p) && keyOf(p) === "args"
15931
+ );
15932
+ return argsProp && t3.isObjectExpression(argsProp.value) ? argsRecordFromObjectNode(argsProp.value) : {};
15933
+ }, toAttr = (key, value) => t3.isBooleanLiteral(value) ? value.value ? t3.jsxAttribute(t3.jsxIdentifier(key), null) : t3.jsxAttribute(t3.jsxIdentifier(key), t3.jsxExpressionContainer(value)) : t3.isStringLiteral(value) ? t3.jsxAttribute(t3.jsxIdentifier(key), t3.stringLiteral(value.value)) : t3.isExpression(value) ? t3.jsxAttribute(t3.jsxIdentifier(key), t3.jsxExpressionContainer(value)) : null, toJsxChildren = (node) => node ? t3.isStringLiteral(node) ? [t3.jsxText(node.value)] : t3.isJSXElement(node) || t3.isJSXFragment(node) ? [node] : t3.isExpression(node) ? [t3.jsxExpressionContainer(node)] : [] : [];
15934
+ function getArgsMemberKey(expr) {
15935
+ if (t3.isMemberExpression(expr) && t3.isIdentifier(expr.object) && expr.object.name === "args") {
15936
+ if (t3.isIdentifier(expr.property) && !expr.computed)
15937
+ return expr.property.name;
15938
+ if (t3.isStringLiteral(expr.property) && expr.computed)
15939
+ return expr.property.value;
15835
15940
  }
15836
- let staticDefaults = extractStaticDefaultProps(typescript, checker, resolved);
15837
- for (let [key, value] of staticDefaults)
15838
- defaultsMap.has(key) || defaultsMap.set(key, value);
15839
- let props = {};
15840
- for (let prop of allProperties) {
15841
- if (excluded.has(prop.getName()))
15842
- continue;
15843
- let item = extractPropItem(typescript, checker, prop, contextNode, defaultsMap);
15844
- unionForceOptional?.has(prop.getName()) && (item.required = !1), props[prop.getName()] = item;
15941
+ if (t3.isOptionalMemberExpression?.(expr) && t3.isIdentifier(expr.object) && expr.object.name === "args") {
15942
+ let prop = expr.property;
15943
+ if (t3.isIdentifier(prop) && !expr.computed)
15944
+ return prop.name;
15945
+ if (t3.isStringLiteral(prop) && expr.computed)
15946
+ return prop.value;
15845
15947
  }
15846
- let displayName = (isMemberSelection ? displayNameOverride : void 0) ?? computeDisplayName({
15847
- exportSymbol,
15848
- resolvedSymbol: resolved
15849
- }) ?? displayNameOverride, description = typescript.displayPartsToString(resolved.getDocumentationComment(checker)), selectedJsDocTags = extractComponentJsDocTags(typescript, checker, resolved), exportResolved = exportSymbol && exportSymbol !== resolved ? resolveAliasedSymbol(typescript, checker, exportSymbol) : void 0, exportJsDocTags = exportResolved ? extractComponentJsDocTags(typescript, checker, exportResolved) : void 0, jsDocTags = selectedJsDocTags?.import || !exportJsDocTags?.import ? selectedJsDocTags : {
15850
- ...selectedJsDocTags ?? {},
15851
- import: exportJsDocTags.import
15852
- };
15853
- return {
15854
- displayName,
15855
- exportName,
15856
- filePath,
15857
- description,
15858
- jsDocTags,
15859
- props
15860
- };
15948
+ return null;
15861
15949
  }
15862
- function extractDefaultsFromSourceFile(typescript, filePath, {
15863
- exportName,
15864
- localName,
15865
- preferLocalName = !1
15866
- }) {
15867
- let defaults = /* @__PURE__ */ new Map(), content = typescript.sys.readFile(filePath);
15868
- if (!content)
15869
- return defaults;
15870
- let sf = typescript.createSourceFile(
15871
- filePath,
15872
- content,
15873
- typescript.ScriptTarget.Latest,
15874
- /* setParentNodes */
15875
- !0
15876
- ), varMap = /* @__PURE__ */ new Map();
15877
- for (let stmt of sf.statements) {
15878
- if (typescript.isVariableStatement(stmt))
15879
- for (let decl of stmt.declarationList.declarations)
15880
- typescript.isIdentifier(decl.name) && decl.initializer && varMap.set(decl.name.text, decl.initializer);
15881
- typescript.isFunctionDeclaration(stmt) && stmt.name && varMap.set(stmt.name.text, stmt);
15950
+ function inlineArgsInJsx(node, merged) {
15951
+ let changed = !1;
15952
+ if (t3.isJSXElement(node)) {
15953
+ let opening = node.openingElement, newAttrs = opening.attributes.flatMap((a) => {
15954
+ if (!t3.isJSXAttribute(a))
15955
+ return [a];
15956
+ let name = t3.isJSXIdentifier(a.name) ? a.name.name : null;
15957
+ if (!(name && a.value && t3.isJSXExpressionContainer(a.value)))
15958
+ return [a];
15959
+ let key = getArgsMemberKey(a.value.expression);
15960
+ if (!(key && key in merged))
15961
+ return [a];
15962
+ let repl = toAttr(name, merged[key]);
15963
+ return changed = !0, repl ? [repl] : [];
15964
+ }), newChildren = node.children.flatMap((c) => {
15965
+ if (t3.isJSXElement(c) || t3.isJSXFragment(c)) {
15966
+ let res = inlineArgsInJsx(c, merged);
15967
+ return changed ||= res.changed, [res.node];
15968
+ }
15969
+ return t3.isJSXExpressionContainer(c) && getArgsMemberKey(c.expression) === "children" && merged.children ? (changed = !0, toJsxChildren(merged.children)) : [c];
15970
+ }), selfClosing = opening.selfClosing && newChildren.length === 0;
15971
+ return {
15972
+ node: t3.jsxElement(
15973
+ t3.jsxOpeningElement(opening.name, newAttrs, selfClosing),
15974
+ selfClosing ? null : node.closingElement ?? t3.jsxClosingElement(opening.name),
15975
+ newChildren,
15976
+ selfClosing
15977
+ ),
15978
+ changed
15979
+ };
15882
15980
  }
15883
- let fn = preferLocalName ? findLocalFunction(typescript, sf, localName, varMap) ?? findExportedFunction(typescript, sf, exportName, varMap) : findExportedFunction(typescript, sf, exportName, varMap) ?? findLocalFunction(typescript, sf, localName, varMap);
15884
- if (!fn)
15885
- return defaults;
15886
- let firstParam = fn.parameters[0];
15887
- if (!firstParam)
15888
- return defaults;
15889
- if (typescript.isObjectBindingPattern(firstParam.name))
15890
- collectBindingDefaults(typescript, firstParam.name, defaults);
15891
- else if (fn.body) {
15892
- let propsParamName = typescript.isIdentifier(firstParam.name) ? firstParam.name : void 0, body = typescript.isBlock(fn.body) ? fn.body : void 0;
15893
- if (body && propsParamName) {
15894
- for (let stmt of body.statements)
15895
- if (typescript.isVariableStatement(stmt))
15896
- for (let varDecl of stmt.declarationList.declarations)
15897
- typescript.isObjectBindingPattern(varDecl.name) && varDecl.initializer && isPropsDerivedInitializer(typescript, varDecl.initializer, propsParamName) && collectBindingDefaults(typescript, varDecl.name, defaults);
15981
+ let fragChildren = node.children.flatMap((c) => {
15982
+ if (t3.isJSXElement(c) || t3.isJSXFragment(c)) {
15983
+ let res = inlineArgsInJsx(c, merged);
15984
+ return changed ||= res.changed, [res.node];
15898
15985
  }
15899
- }
15900
- return defaults;
15986
+ return t3.isJSXExpressionContainer(c) && getArgsMemberKey(c.expression) === "children" && "children" in merged ? (changed = !0, toJsxChildren(merged.children)) : [c];
15987
+ });
15988
+ return { node: t3.jsxFragment(node.openingFragment, node.closingFragment, fragChildren), changed };
15901
15989
  }
15902
- function findLocalFunction(typescript, sf, localName, varMap) {
15903
- if (!localName)
15904
- return;
15905
- let targetExpr = varMap.get(localName);
15906
- if (targetExpr)
15907
- return unwrapToFunctionAST(typescript, targetExpr, varMap, 0);
15990
+ function transformArgsSpreadsInJsx(node, merged) {
15991
+ let changed = !1, makeInjectedPieces = (existing) => {
15992
+ let entries = Object.entries(merged).filter(([k, v]) => v != null && k !== "children"), validEntries = entries.filter(([k]) => isValidJsxAttrName(k)), invalidEntries = entries.filter(([k]) => !isValidJsxAttrName(k)), injectedAttrs = validEntries.map(([k, v]) => toAttr(k, v)).filter((a) => !!a).filter((a) => t3.isJSXIdentifier(a.name) && !existing.has(a.name.name)), invalidSpread = buildInvalidSpread(invalidEntries.filter(([k]) => !existing.has(k)));
15993
+ return invalidSpread ? [...injectedAttrs, invalidSpread] : injectedAttrs;
15994
+ };
15995
+ if (t3.isJSXElement(node)) {
15996
+ let opening = node.openingElement, attrs = opening.attributes, isArgsSpread = (a) => t3.isJSXSpreadAttribute(a) && t3.isIdentifier(a.argument) && a.argument.name === "args", sawArgsSpread = attrs.some(isArgsSpread), firstIdx = attrs.findIndex(isArgsSpread), nonArgsAttrs = attrs.filter((a) => !isArgsSpread(a)), insertionIndex = sawArgsSpread ? attrs.slice(0, firstIdx).filter((a) => !isArgsSpread(a)).length : 0, newAttrs = sawArgsSpread ? (() => {
15997
+ let existing = new Set(
15998
+ nonArgsAttrs.filter((a) => t3.isJSXAttribute(a)).flatMap((a) => t3.isJSXIdentifier(a.name) ? [a.name.name] : [])
15999
+ ), pieces = makeInjectedPieces(existing);
16000
+ return changed = !0, [
16001
+ ...nonArgsAttrs.slice(0, insertionIndex),
16002
+ ...pieces,
16003
+ ...nonArgsAttrs.slice(insertionIndex)
16004
+ ];
16005
+ })() : nonArgsAttrs, newChildren = node.children.flatMap((c) => {
16006
+ if (t3.isJSXElement(c) || t3.isJSXFragment(c)) {
16007
+ let res = transformArgsSpreadsInJsx(c, merged);
16008
+ return changed ||= res.changed, [res.node];
16009
+ }
16010
+ return [c];
16011
+ }), children = sawArgsSpread && newChildren.length === 0 && merged.children ? (changed = !0, toJsxChildren(merged.children)) : newChildren, selfClosing = children.length === 0;
16012
+ return {
16013
+ node: t3.jsxElement(
16014
+ t3.jsxOpeningElement(opening.name, newAttrs, selfClosing),
16015
+ selfClosing ? null : node.closingElement ?? t3.jsxClosingElement(opening.name),
16016
+ children,
16017
+ selfClosing
16018
+ ),
16019
+ changed
16020
+ };
16021
+ }
16022
+ let fragChildren = node.children.flatMap((c) => {
16023
+ if (t3.isJSXElement(c) || t3.isJSXFragment(c)) {
16024
+ let res = transformArgsSpreadsInJsx(c, merged);
16025
+ return changed ||= res.changed, [res.node];
16026
+ }
16027
+ return [c];
16028
+ });
16029
+ return { node: t3.jsxFragment(node.openingFragment, node.closingFragment, fragChildren), changed };
15908
16030
  }
15909
- function findExportedFunction(typescript, sf, exportName, varMap) {
15910
- let targetExpr;
15911
- for (let stmt of sf.statements) {
15912
- if (exportName === "default" && typescript.isExportAssignment(stmt) && !stmt.isExportEquals) {
15913
- targetExpr = stmt.expression;
15914
- break;
16031
+ function resolveIdentifierInit(storyPath, identifier) {
16032
+ let programPath = storyPath.findParent((p) => p.isProgram());
16033
+ if (!programPath)
16034
+ return null;
16035
+ for (let stmt of programPath.get("body")) {
16036
+ if (stmt.isFunctionDeclaration() && stmt.node.id?.name === identifier.node.name)
16037
+ return stmt;
16038
+ if (stmt.isExportNamedDeclaration()) {
16039
+ let decl = stmt.get("declaration");
16040
+ if (decl.isFunctionDeclaration() && decl.node.id?.name === identifier.node.name)
16041
+ return decl;
15915
16042
  }
15916
- if (typescript.isVariableStatement(stmt) && hasExportModifier(typescript, stmt)) {
15917
- for (let decl of stmt.declarationList.declarations)
15918
- if (typescript.isIdentifier(decl.name) && decl.name.text === exportName && decl.initializer) {
15919
- targetExpr = decl.initializer;
15920
- break;
15921
- }
15922
- if (targetExpr)
15923
- break;
16043
+ }
16044
+ let match = programPath.get("body").flatMap((stmt) => {
16045
+ if (stmt.isVariableDeclaration())
16046
+ return stmt.get("declarations");
16047
+ if (stmt.isExportNamedDeclaration()) {
16048
+ let decl = stmt.get("declaration");
16049
+ if (decl && decl.isVariableDeclaration())
16050
+ return decl.get("declarations");
15924
16051
  }
15925
- if (typescript.isFunctionDeclaration(stmt) && hasExportModifier(typescript, stmt) && stmt.name?.text === exportName)
15926
- return findFunctionImpl(typescript, sf, stmt.name.text) ?? stmt;
15927
- if (typescript.isExportDeclaration(stmt) && stmt.exportClause && typescript.isNamedExports(stmt.exportClause)) {
15928
- for (let spec of stmt.exportClause.elements) {
15929
- let exported = spec.name.text, local = spec.propertyName ? spec.propertyName.text : spec.name.text;
15930
- if (exported === exportName) {
15931
- targetExpr = varMap.get(local);
15932
- break;
15933
- }
15934
- }
15935
- if (targetExpr)
15936
- break;
16052
+ return [];
16053
+ }).find((d) => {
16054
+ let id = d.get("id");
16055
+ return id.isIdentifier() && id.node.name === identifier.node.name;
16056
+ });
16057
+ if (!match)
16058
+ return null;
16059
+ let init = match.get("init");
16060
+ return init && init.isExpression() ? init : null;
16061
+ }
16062
+ function pathForNode(program, target) {
16063
+ if (!target)
16064
+ return;
16065
+ let found;
16066
+ return program.traverse({
16067
+ enter(p) {
16068
+ p.node && p.node === target && (found = p, p.stop());
15937
16069
  }
16070
+ }), found;
16071
+ }
16072
+
16073
+ // src/componentManifest/subcomponents.ts
16074
+ import { types as t4 } from "storybook/internal/babel";
16075
+ function findExactComponentMatch(components, componentName) {
16076
+ if (componentName)
16077
+ return components.find((component) => component.componentName === componentName);
16078
+ }
16079
+ function extractDeclaredSubcomponents(csf) {
16080
+ let rawSubcomponents = unwrapSubcomponentNode(
16081
+ csf._metaAnnotations.subcomponents,
16082
+ csf._ast.program
16083
+ );
16084
+ return !rawSubcomponents || !t4.isObjectExpression(rawSubcomponents) ? [] : rawSubcomponents.properties.flatMap((property) => {
16085
+ if (!t4.isObjectProperty(property))
16086
+ return [];
16087
+ let name = getObjectKeyName(property.key), directComponentName = getComponentExpressionName(property.value), componentExpression = unwrapSubcomponentNode(property.value, csf._ast.program), componentName = getComponentExpressionName(componentExpression) ?? directComponentName;
16088
+ return name && componentName ? [{ name, componentName }] : [];
16089
+ });
16090
+ }
16091
+ function findVariableInitialization(identifier, program) {
16092
+ for (let node of program.body) {
16093
+ let declaration = (t4.isVariableDeclaration(node) ? node.declarations : t4.isExportNamedDeclaration(node) && t4.isVariableDeclaration(node.declaration) ? node.declaration.declarations : void 0)?.find(
16094
+ (decl) => t4.isVariableDeclarator(decl) && t4.isIdentifier(decl.id) && decl.id.name === identifier
16095
+ );
16096
+ if (declaration?.init && t4.isExpression(declaration.init))
16097
+ return declaration.init;
15938
16098
  }
15939
- if (targetExpr || (targetExpr = varMap.get(exportName)), !!targetExpr)
15940
- return unwrapToFunctionAST(typescript, targetExpr, varMap, 0);
15941
16099
  }
15942
- function unwrapToFunctionAST(typescript, node, varMap, depth) {
15943
- if (!(depth > MAX_UNWRAP_DEPTH)) {
15944
- if (typescript.isFunctionExpression(node) || typescript.isArrowFunction(node) || typescript.isFunctionDeclaration(node))
15945
- return node;
15946
- if (typescript.isParenthesizedExpression(node) || typescript.isAsExpression(node) || typescript.isTypeAssertionExpression && typescript.isTypeAssertionExpression(node))
15947
- return unwrapToFunctionAST(typescript, node.expression, varMap, depth + 1);
15948
- if (typescript.isCallExpression(node)) {
15949
- let callee = node.expression;
15950
- if (typescript.isPropertyAccessExpression(callee) && typescript.isIdentifier(callee.expression) && callee.expression.text === "Object" && callee.name.text === "assign" && node.arguments.length >= 1 || node.arguments.length >= 1)
15951
- return unwrapToFunctionAST(typescript, node.arguments[0], varMap, depth + 1);
16100
+ function unwrapSubcomponentNode(node, program, visitedIdentifiers = /* @__PURE__ */ new Set()) {
16101
+ let current2 = node;
16102
+ for (; current2; ) {
16103
+ if (t4.isIdentifier(current2)) {
16104
+ if (visitedIdentifiers.has(current2.name))
16105
+ return;
16106
+ visitedIdentifiers.add(current2.name), current2 = findVariableInitialization(current2.name, program);
16107
+ continue;
15952
16108
  }
15953
- if (typescript.isIdentifier(node)) {
15954
- let init = varMap.get(node.text);
15955
- if (init)
15956
- return unwrapToFunctionAST(typescript, init, varMap, depth + 1);
16109
+ if (t4.isParenthesizedExpression(current2) || t4.isTSAsExpression(current2) || t4.isTSSatisfiesExpression(current2) || t4.isTSNonNullExpression(current2)) {
16110
+ current2 = current2.expression;
16111
+ continue;
15957
16112
  }
16113
+ return current2;
15958
16114
  }
15959
16115
  }
15960
- function findFunctionImpl(typescript, sf, name) {
15961
- for (let stmt of sf.statements)
15962
- if (typescript.isFunctionDeclaration(stmt) && stmt.name?.text === name && stmt.body)
15963
- return stmt;
16116
+ function getObjectKeyName(key) {
16117
+ if (t4.isIdentifier(key))
16118
+ return key.name;
16119
+ if (t4.isStringLiteral(key))
16120
+ return key.value;
15964
16121
  }
15965
- function hasExportModifier(typescript, node) {
15966
- return typescript.canHaveModifiers(node) && typescript.getModifiers(node)?.some((m) => m.kind === typescript.SyntaxKind.ExportKeyword) === !0;
16122
+ function getComponentExpressionName(node) {
16123
+ if (node) {
16124
+ if (t4.isIdentifier(node))
16125
+ return node.name;
16126
+ if (t4.isMemberExpression(node) && !node.computed) {
16127
+ let objectName = getComponentExpressionName(node.object), propertyName = getComponentExpressionName(node.property);
16128
+ return objectName && propertyName ? `${objectName}.${propertyName}` : void 0;
16129
+ }
16130
+ }
15967
16131
  }
15968
16132
 
15969
- // src/componentManifest/componentMeta/ComponentMetaProject.ts
15970
- var ComponentMetaProject = class {
15971
- constructor(typescript, commandLine, configFileName, fsFileSnapshots = /* @__PURE__ */ new Map(), getCommandLineFn) {
15972
- this.typescript = typescript;
15973
- this.commandLine = commandLine;
15974
- this.configFileName = configFileName;
15975
- this.fsFileSnapshots = fsFileSnapshots;
15976
- this.getCommandLineFn = getCommandLineFn;
15977
- this.projectVersion = 0;
15978
- this.shouldCheckRootFiles = !1;
15979
- /** Entries to extract — set by the generator, replayed during warmup for targeted type resolution. */
15980
- this.entries = [];
15981
- let language = (0, import_language_core.createLanguage)(
15982
- [{ getLanguageId: (fileName) => (0, import_typescript.resolveFileLanguageId)(fileName) }],
15983
- new import_language_core.FileMap(typescript.sys.useCaseSensitiveFileNames),
15984
- (fileName, includeFsFiles) => {
15985
- if (!includeFsFiles)
15986
- return;
15987
- let cache = fsFileSnapshots.get(fileName), modifiedTime = typescript.sys.getModifiedTime?.(fileName)?.valueOf();
15988
- if (!cache || cache[0] !== modifiedTime)
15989
- if (typescript.sys.fileExists(fileName)) {
15990
- let text = typescript.sys.readFile(fileName), snapshot2 = text !== void 0 ? typescript.ScriptSnapshot.fromString(text) : void 0;
15991
- fsFileSnapshots.set(fileName, [modifiedTime, snapshot2]);
15992
- } else
15993
- fsFileSnapshots.set(fileName, [modifiedTime, void 0]);
15994
- let snapshot = fsFileSnapshots.get(fileName)?.[1];
15995
- snapshot ? language.scripts.set(fileName, snapshot) : language.scripts.delete(fileName);
15996
- }
15997
- ), projectHost = {
15998
- getCurrentDirectory: () => configFileName ? path2.dirname(configFileName) : commandLine.options.rootDir ?? process.cwd(),
15999
- getCompilationSettings: () => this.commandLine.options,
16000
- getProjectReferences: () => this.commandLine.projectReferences,
16001
- getProjectVersion: () => (this.checkRootFilesUpdate(), this.projectVersion.toString()),
16002
- getScriptFileNames: () => (this.checkRootFilesUpdate(), this.commandLine.fileNames)
16003
- }, { languageServiceHost } = (0, import_typescript.createLanguageServiceHost)(
16004
- typescript,
16005
- typescript.sys,
16006
- language,
16007
- (s) => s,
16008
- // asScriptId — identity for React (no URI mapping needed)
16009
- projectHost
16010
- );
16011
- this.ls = typescript.createLanguageService(languageServiceHost);
16012
- }
16013
- getCommandLine() {
16014
- return this.commandLine;
16015
- }
16016
- dispose() {
16017
- clearTimeout(this.warmupTimer), this.ls.dispose();
16018
- }
16019
- // ---------------------------------------------------------------------------
16020
- // Project management
16021
- // ---------------------------------------------------------------------------
16022
- /**
16023
- * Batch-add multiple files to the project in one go. Only bumps projectVersion once, avoiding
16024
- * repeated program rebuilds.
16025
- */
16026
- ensureFiles(fileNames) {
16027
- let added = !1;
16028
- for (let fileName of fileNames)
16029
- this.commandLine.fileNames.includes(fileName) || (this.commandLine.fileNames.push(fileName), added = !0);
16030
- added && this.projectVersion++;
16031
- }
16032
- /**
16033
- * Adapted from:
16034
- * https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/kit/lib/createChecker.ts#L436-L447
16035
- */
16036
- checkRootFilesUpdate() {
16037
- if (!this.shouldCheckRootFiles || (this.shouldCheckRootFiles = !1, !this.getCommandLineFn))
16038
- return;
16039
- let newCommandLine = this.getCommandLineFn();
16040
- arrayItemsEqual(newCommandLine.fileNames, this.commandLine.fileNames) || (this.commandLine.fileNames = newCommandLine.fileNames, this.projectVersion++);
16041
- }
16042
- hasSourceFile(fileName) {
16043
- return !!this.ls.getProgram()?.getSourceFile(fileName);
16044
- }
16045
- /**
16046
- * Get all non-node_modules source file paths from the TS program. Used by ComponentMetaManager to
16047
- * watch directories for file changes.
16048
- */
16049
- getSourceFilePaths() {
16050
- let program = this.ls.getProgram();
16051
- return program ? program.getSourceFiles().map((sf) => sf.fileName.replace(/\\/g, "/")).filter((f) => !f.includes("node_modules")) : [];
16052
- }
16053
- /**
16054
- * Adapted from:
16055
- * https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/kit/lib/createChecker.ts#L409-L432
16056
- *
16057
- * Created events only set shouldCheckRootFiles (version bump happens in checkRootFilesUpdate if
16058
- * the file list actually changed). Deleted/created break early since they trigger a full config
16059
- * reparse — processing remaining changes is unnecessary.
16060
- */
16061
- onFilesChanged(changes) {
16062
- for (let { filePath } of changes)
16063
- this.fsFileSnapshots.delete(filePath);
16064
- let oldVersion = this.projectVersion, program = this.ls.getProgram();
16065
- for (let { filePath, type } of changes)
16066
- if (type === "changed")
16067
- program?.getSourceFile(filePath) && this.projectVersion++;
16068
- else if (type === "deleted") {
16069
- program?.getSourceFile(filePath) && this.projectVersion++, this.shouldCheckRootFiles = !0;
16070
- break;
16071
- } else if (type === "created") {
16072
- this.shouldCheckRootFiles = !0;
16073
- break;
16074
- }
16075
- this.projectVersion !== oldVersion && this.entries.length > 0 && (clearTimeout(this.warmupTimer), this.warmupTimer = setTimeout(() => {
16076
- try {
16077
- this.extractPropsFromStories(this.entries);
16078
- } catch {
16079
- }
16080
- }, 100), this.warmupTimer?.unref?.());
16081
- }
16082
- // ---------------------------------------------------------------------------
16083
- // Primary extraction method — probe-free
16084
- // ---------------------------------------------------------------------------
16085
- extractPropsFromStories(entries) {
16086
- this.entries = entries;
16087
- let allFiles = entries.flatMap(
16088
- (entry) => entry.component?.path ? [entry.storyPath, entry.component.path] : [entry.storyPath]
16089
- );
16090
- this.ensureFiles(allFiles), this.ensureFresh(allFiles);
16091
- let program = this.ls.getProgram();
16092
- if (!program)
16093
- return;
16094
- let checker = program.getTypeChecker(), serializationContextByComponentPath = /* @__PURE__ */ new Map();
16095
- for (let entry of entries)
16096
- try {
16097
- let storySourceFile = program.getSourceFile(entry.storyPath), entryComponent = entry.component, componentPath = entryComponent?.path, exportName = entryComponent?.importName;
16098
- if (!storySourceFile || !componentPath || !exportName || !entryComponent)
16099
- continue;
16100
- let importId = entryComponent.importId, isPackageImport = importId && !importId.startsWith("."), componentSourceFile;
16101
- if (isPackageImport) {
16102
- let resolved = this.typescript.resolveModuleName(
16103
- importId,
16104
- entry.storyPath,
16105
- this.commandLine.options,
16106
- this.typescript.sys
16107
- );
16108
- componentSourceFile = resolved.resolvedModule ? program.getSourceFile(resolved.resolvedModule.resolvedFileName) : program.getSourceFile(componentPath);
16109
- } else
16110
- componentSourceFile = program.getSourceFile(componentPath);
16111
- if (!componentSourceFile)
16112
- continue;
16113
- let resolvedComponent;
16114
- if (importId && (resolvedComponent = resolvePropsFromStoryFile(
16115
- this.typescript,
16116
- checker,
16117
- storySourceFile,
16118
- entryComponent
16119
- )), resolvedComponent || (resolvedComponent = this.resolveFromMetaComponent(
16120
- checker,
16121
- storySourceFile,
16122
- entryComponent
16123
- )), !resolvedComponent)
16124
- continue;
16125
- let serializationContext = serializationContextByComponentPath.get(componentPath);
16126
- if (serializationContext === void 0) {
16127
- let resolvedFileName = componentSourceFile.fileName;
16128
- serializationContext = {
16129
- sourceFile: componentSourceFile,
16130
- defaultsSourcePath: resolvedFileName.endsWith(".d.ts") || resolvedFileName.endsWith(".d.mts") || resolvedFileName.endsWith(".d.cts") ? componentPath : void 0
16131
- }, serializationContextByComponentPath.set(componentPath, serializationContext);
16132
- }
16133
- let doc = serializeComponentDoc(this.typescript, checker, {
16134
- sourceFile: serializationContext.sourceFile,
16135
- resolvedComponent,
16136
- defaultsSourcePath: serializationContext.defaultsSourcePath
16137
- });
16138
- doc && (entryComponent.reactComponentMeta = doc, entryComponent.componentJsDocTags = doc.jsDocTags, entryComponent.importOverride = entryComponent.componentJsDocTags?.import?.[0]?.trim());
16139
- } catch {
16140
- continue;
16141
- }
16142
- }
16143
- /**
16144
- * Check mtime for specific files and bump projectVersion if any changed.
16145
- *
16146
- * This bypasses the sync() gate in createLanguageServiceHost — sync() only runs when
16147
- * projectVersion changes, so mtime-based cache alone can't detect stale files. We do a targeted
16148
- * mtime check for the files we're about to extract from, ensuring freshness even when the
16149
- * fs.watch event hasn't arrived yet (race with HMR) or was missed entirely.
16150
- */
16151
- ensureFresh(fileNames) {
16152
- let stale = !1;
16153
- for (let fileName of fileNames) {
16154
- let cache = this.fsFileSnapshots.get(fileName);
16155
- if (!cache)
16156
- continue;
16157
- let currentMtime = this.typescript.sys.getModifiedTime?.(fileName)?.valueOf();
16158
- cache[0] !== currentMtime && (this.fsFileSnapshots.delete(fileName), stale = !0);
16159
- }
16160
- stale && this.projectVersion++;
16133
+ // src/componentManifest/resolveComponents.ts
16134
+ function findMatchingComponent(components, componentName, title) {
16135
+ let exactMatch = findExactComponentMatch(components, componentName);
16136
+ if (exactMatch)
16137
+ return exactMatch;
16138
+ let trimmedTitle = title.replace(/\s+/g, ""), matches = components.filter(
16139
+ (it) => trimmedTitle.includes(it.componentName) || it.localImportName && trimmedTitle.includes(it.localImportName) || it.importName && trimmedTitle.includes(it.importName)
16140
+ );
16141
+ if (matches.length <= 1)
16142
+ return matches[0];
16143
+ let best = matches[0];
16144
+ for (let cur of matches) {
16145
+ if (cur.jsxDepth === 0)
16146
+ return cur;
16147
+ (cur.jsxDepth ?? 1 / 0) < (best.jsxDepth ?? 1 / 0) && (best = cur);
16161
16148
  }
16162
- // ---------------------------------------------------------------------------
16163
- // Internal helpers
16164
- // ---------------------------------------------------------------------------
16165
- /**
16166
- * Path 2 fallback: resolve the component type from the story file's `meta.component` property.
16167
- * Only works when the user explicitly set `component:` in the meta — no node means no
16168
- * extraction.
16169
- */
16170
- resolveFromMetaComponent(checker, storySourceFile, componentRef) {
16171
- let { member: memberAccess } = componentRef, moduleSymbol = checker.getSymbolAtLocation(storySourceFile);
16172
- if (!moduleSymbol)
16173
- return;
16174
- let defaultExport = checker.getExportsOfModule(moduleSymbol).find((e) => e.getName() === "default");
16175
- if (!defaultExport)
16176
- return;
16177
- let componentProp = checker.getTypeOfSymbol(defaultExport).getProperty("component");
16178
- if (!componentProp)
16179
- return;
16180
- let componentType = checker.getTypeOfSymbol(componentProp), selectedSymbol = componentProp.valueDeclaration && this.typescript.isPropertyAssignment(componentProp.valueDeclaration) ? checker.getSymbolAtLocation(componentProp.valueDeclaration.initializer) : componentType.getSymbol?.();
16181
- if (memberAccess) {
16182
- let prop = componentType.getProperty(memberAccess);
16183
- if (prop)
16184
- componentType = checker.getTypeOfSymbol(prop), selectedSymbol = prop;
16185
- else
16186
- return;
16187
- }
16188
- let propsType = resolvePropsFromComponentType(this.typescript, checker, componentType);
16189
- if (!(!propsType || !selectedSymbol))
16149
+ return best;
16150
+ }
16151
+ async function resolveStoryFileComponents(options) {
16152
+ let { storyPath, title, typescriptOptions, docgenEngine } = options, storyFile = cachedReadTextFileSync(storyPath), csf = loadCsf(storyFile, { makeTitle: () => title }).parse(), componentName = csf._meta?.component, declaredSubcomponents = extractDeclaredSubcomponents(csf), allComponents = await getComponents({
16153
+ additionalComponentNames: declaredSubcomponents.map(
16154
+ (subcomponent) => subcomponent.componentName
16155
+ ),
16156
+ csf,
16157
+ storyFilePath: storyPath,
16158
+ typescriptOptions,
16159
+ docgenEngine
16160
+ }), component = findMatchingComponent(allComponents, componentName, title), subcomponents = declaredSubcomponents.map((declared) => ({
16161
+ name: declared.name,
16162
+ component: findExactComponentMatch(allComponents, declared.componentName)
16163
+ }));
16164
+ return { storyPath, storyFile, csf, componentName, allComponents, component, subcomponents };
16165
+ }
16166
+ function extractStorySnippets(csf, componentName, filterStoryIds) {
16167
+ return Object.entries(csf._stories).filter(([, story]) => !filterStoryIds || filterStoryIds.has(story.id)).map(([storyExport, story]) => {
16168
+ let name = story.name ?? storyNameFromExport(storyExport);
16169
+ try {
16170
+ let jsdocComment = extractDescription(csf._storyStatements[storyExport]), { tags = {}, description } = jsdocComment ? extractJSDocInfo(jsdocComment) : {}, finalDescription = (tags?.describe?.[0] || tags?.desc?.[0]) ?? description;
16190
16171
  return {
16191
- componentRef,
16192
- propsType,
16193
- symbol: selectedSymbol
16172
+ id: story.id,
16173
+ name,
16174
+ snippet: recast2.print(getCodeSnippet(csf, storyExport, componentName)).code,
16175
+ description: finalDescription?.trim(),
16176
+ summary: tags.summary?.[0]
16194
16177
  };
16195
- }
16196
- };
16197
- function arrayItemsEqual(a, b) {
16198
- if (a.length !== b.length)
16199
- return !1;
16200
- let set = new Set(a);
16201
- for (let file of b)
16202
- if (!set.has(file))
16203
- return !1;
16204
- return !0;
16178
+ } catch (e) {
16179
+ let err = e instanceof Error ? e : new Error(String(e));
16180
+ return { id: story.id, name, error: { name: err.name, message: err.message } };
16181
+ }
16182
+ });
16205
16183
  }
16206
16184
 
16207
- // src/componentManifest/componentMeta/ComponentMetaManager.ts
16208
- var rootTsConfigNames = ["tsconfig.json", "jsconfig.json"], DEFAULT_INFERRED_OPTIONS = {
16209
- strict: !0,
16210
- esModuleInterop: !0,
16211
- allowJs: !0,
16212
- skipLibCheck: !0
16213
- }, ComponentMetaManager = class {
16214
- constructor(typescript) {
16215
- this.typescript = typescript;
16216
- // Adapted from:
16217
- // https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/language-server/lib/project/typescriptProject.ts#L34-L37
16218
- this.configProjects = /* @__PURE__ */ new Map();
16219
- this.rootTsConfigs = /* @__PURE__ */ new Set();
16220
- this.searchedDirs = /* @__PURE__ */ new Set();
16221
- // Our own file watching layer
16222
- this.watching = !1;
16223
- this.watchersByDir = /* @__PURE__ */ new Map();
16224
- this.pendingEvents = /* @__PURE__ */ new Map();
16225
- // Adapted from:
16226
- // https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/kit/lib/createChecker.ts#L83
16227
- this.fsFileSnapshots = /* @__PURE__ */ new Map();
16228
- }
16229
- // ---------------------------------------------------------------------------
16230
- // Adapted from:
16231
- // https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/language-server/lib/project/typescriptProject.ts#L70-L79
16232
- // ---------------------------------------------------------------------------
16233
- getProjectForFile(fileName) {
16234
- let tsconfig = this.findMatchTSConfig(fileName);
16235
- return tsconfig ? this.getOrCreateConfiguredProject(tsconfig) ?? this.getOrCreateInferredProject(fileName) : this.getOrCreateInferredProject(fileName);
16185
+ // src/componentManifest/buildReactComponentDocgen.ts
16186
+ function getPackageInfo(componentPath, fallbackPath) {
16187
+ let nearestPkg = cachedFindUp("package.json", {
16188
+ cwd: path.dirname(componentPath ?? fallbackPath)
16189
+ });
16190
+ try {
16191
+ if (!nearestPkg)
16192
+ return;
16193
+ let parsed = JSON.parse(cachedReadTextFileSync(nearestPkg));
16194
+ return typeof parsed == "object" && parsed && "name" in parsed && typeof parsed.name == "string" ? parsed.name : void 0;
16195
+ } catch {
16196
+ return;
16236
16197
  }
16237
- /**
16238
- * Batch-extract component props across all entries, grouping by tsconfig project so each project
16239
- * builds its TS program only once.
16240
- */
16241
- batchExtract(entries) {
16242
- let extractableEntries = entries.filter(
16243
- (storyRef) => storyRef.component?.path && storyRef.component.importName
16244
- ), byProject = groupByToMap(
16245
- extractableEntries,
16246
- (storyRef) => this.getProjectForFile(storyRef.storyPath)
16247
- );
16248
- for (let [project, projectEntries] of byProject)
16249
- try {
16250
- project.extractPropsFromStories(projectEntries);
16251
- } catch (err) {
16252
- logger5.debug(`[reactComponentMeta] Batch extraction failed: ${err}`);
16198
+ }
16199
+ function getFallbackImport(packageName, componentName) {
16200
+ let exportName = componentName?.split(".").at(-1);
16201
+ return packageName && exportName ? `import { ${exportName} } from "${packageName}";` : "";
16202
+ }
16203
+ function relativizeComponentMetaPaths(doc) {
16204
+ let relativize = (fileName) => path.relative(process.cwd(), fileName), relativizeProp = (prop) => ({
16205
+ ...prop,
16206
+ parent: prop.parent ? { ...prop.parent, fileName: relativize(prop.parent.fileName) } : prop.parent,
16207
+ declarations: prop.declarations?.map((declaration) => ({
16208
+ ...declaration,
16209
+ fileName: relativize(declaration.fileName)
16210
+ }))
16211
+ });
16212
+ return {
16213
+ ...doc,
16214
+ props: Object.fromEntries(
16215
+ Object.entries(doc.props).map(([name, prop]) => [name, relativizeProp(prop)])
16216
+ )
16217
+ };
16218
+ }
16219
+ function getComponentDocgenData(component, docgenEngine) {
16220
+ let reactDocgen, reactDocgenTypescript, reactComponentMeta, docgenDescription, docgenJsDocTags, docgenError;
16221
+ if (docgenEngine === "react-docgen") {
16222
+ let result = component?.reactDocgen;
16223
+ reactDocgen = result?.type === "success" ? result.data : void 0, docgenDescription = reactDocgen?.description, docgenError = result?.type === "error" ? result.error : void 0;
16224
+ } else docgenEngine === "react-docgen-typescript" ? (reactDocgenTypescript = component?.reactDocgenTypescript, docgenDescription = reactDocgenTypescript?.description, docgenError = component?.reactDocgenTypescriptError) : (reactComponentMeta = component?.reactComponentMeta ? relativizeComponentMetaPaths(component.reactComponentMeta) : void 0, docgenDescription = reactComponentMeta?.description, docgenJsDocTags = component?.componentJsDocTags);
16225
+ return {
16226
+ docgenDescription,
16227
+ docgenError,
16228
+ docgenJsDocTags,
16229
+ reactComponentMeta,
16230
+ reactDocgen,
16231
+ reactDocgenTypescript
16232
+ };
16233
+ }
16234
+ function createSubcomponentDocgen({
16235
+ component,
16236
+ declaredName,
16237
+ docgenEngine,
16238
+ packageName,
16239
+ storyFilePath
16240
+ }) {
16241
+ let imports = getImports({ components: component ? [component] : [], packageName }).join(`
16242
+ `).trim() || getFallbackImport(packageName, component?.componentName), {
16243
+ reactDocgen,
16244
+ reactDocgenTypescript,
16245
+ reactComponentMeta,
16246
+ docgenDescription,
16247
+ docgenJsDocTags,
16248
+ docgenError
16249
+ } = getComponentDocgenData(component, docgenEngine), { description, summary, jsDocTags } = extractComponentDescription(
16250
+ void 0,
16251
+ docgenDescription,
16252
+ docgenJsDocTags
16253
+ );
16254
+ return {
16255
+ name: declaredName,
16256
+ path: component?.path ?? storyFilePath,
16257
+ description,
16258
+ summary,
16259
+ import: imports || void 0,
16260
+ jsDocTags,
16261
+ reactDocgen,
16262
+ reactDocgenTypescript,
16263
+ reactComponentMeta,
16264
+ error: docgenError ?? (component ? void 0 : {
16265
+ name: "No component import found",
16266
+ message: `No component file found for the "${declaredName}" subcomponent.`
16267
+ })
16268
+ };
16269
+ }
16270
+ function buildReactComponentDocgenFromResolved({
16271
+ entry,
16272
+ storyPath,
16273
+ storyFilePath,
16274
+ storyFile,
16275
+ csf,
16276
+ componentName,
16277
+ component,
16278
+ allComponents,
16279
+ subcomponents,
16280
+ docgenEngine,
16281
+ filterStoryIds
16282
+ }) {
16283
+ let componentId = getComponentIdFromEntry(entry), title = entry.title.split("/").at(-1).replace(/\s+/g, ""), packageName = getPackageInfo(component?.path, storyPath), fallbackImport = getFallbackImport(packageName, componentName), imports = getImports({ components: allComponents, packageName }).join(`
16284
+ `).trim() || fallbackImport, stories = extractStorySnippets(csf, component?.componentName, filterStoryIds), base2 = {
16285
+ componentId,
16286
+ name: componentName ?? title,
16287
+ path: storyFilePath,
16288
+ stories,
16289
+ import: imports || void 0,
16290
+ jsDocTags: {}
16291
+ }, {
16292
+ reactDocgen,
16293
+ reactDocgenTypescript,
16294
+ reactComponentMeta,
16295
+ docgenDescription,
16296
+ docgenJsDocTags,
16297
+ docgenError
16298
+ } = getComponentDocgenData(component, docgenEngine);
16299
+ if (!reactDocgen && !reactDocgenTypescript && !reactComponentMeta) {
16300
+ let error = csf._meta?.component ? {
16301
+ name: "No component import found",
16302
+ message: `No component file found for the "${csf.meta.component}" component.`
16303
+ } : {
16304
+ name: "No component found",
16305
+ message: "We could not detect the component from your story file. Specify meta.component."
16306
+ };
16307
+ return {
16308
+ ...base2,
16309
+ jsDocTags: base2.jsDocTags ?? {},
16310
+ error: docgenError ?? {
16311
+ name: error.name,
16312
+ message: (csf._metaStatementPath?.buildCodeFrameError(error.message).message ?? error.message) + `
16313
+
16314
+ ${entry.importPath}:
16315
+ ${storyFile}`
16253
16316
  }
16317
+ };
16254
16318
  }
16255
- // ---------------------------------------------------------------------------
16256
- // Adapted from:
16257
- // https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/language-server/lib/project/typescriptProject.ts#L101-L234
16258
- // ---------------------------------------------------------------------------
16259
- findMatchTSConfig(filePath) {
16260
- let fileName = filePath.replace(/\\/g, "/"), dir = path3.dirname(fileName);
16261
- for (; !this.searchedDirs.has(dir); ) {
16262
- this.searchedDirs.add(dir);
16263
- for (let tsConfigName of rootTsConfigNames) {
16264
- let tsconfigPath = path3.join(dir, tsConfigName).replace(/\\/g, "/");
16265
- this.typescript.sys.fileExists(tsconfigPath) && this.rootTsConfigs.add(tsconfigPath);
16319
+ let metaJsDoc = extractDescription2(csf._metaStatement) || void 0, { description, summary, jsDocTags } = extractComponentDescription(
16320
+ metaJsDoc,
16321
+ docgenDescription,
16322
+ docgenJsDocTags
16323
+ ), subcomponentEntries = Object.fromEntries(
16324
+ subcomponents.map((subcomponent) => [
16325
+ subcomponent.name,
16326
+ createSubcomponentDocgen({
16327
+ component: subcomponent.component,
16328
+ declaredName: subcomponent.name,
16329
+ docgenEngine,
16330
+ packageName,
16331
+ storyFilePath
16332
+ })
16333
+ ])
16334
+ );
16335
+ return {
16336
+ ...base2,
16337
+ description,
16338
+ summary,
16339
+ import: imports || void 0,
16340
+ reactDocgen,
16341
+ reactDocgenTypescript,
16342
+ reactComponentMeta,
16343
+ jsDocTags,
16344
+ ...Object.keys(subcomponentEntries).length > 0 ? { subcomponents: subcomponentEntries } : {},
16345
+ error: docgenError
16346
+ };
16347
+ }
16348
+ function toReactComponentManifest(resolved) {
16349
+ let { componentId, subcomponents, ...rest } = resolved;
16350
+ return {
16351
+ ...rest,
16352
+ id: componentId,
16353
+ ...subcomponents ? {
16354
+ subcomponents: Object.fromEntries(
16355
+ Object.entries(subcomponents).map(([key, sub]) => [
16356
+ key,
16357
+ {
16358
+ name: sub.name,
16359
+ path: sub.path,
16360
+ description: sub.description,
16361
+ summary: sub.summary,
16362
+ import: sub.import,
16363
+ jsDocTags: sub.jsDocTags,
16364
+ error: sub.error,
16365
+ reactDocgen: sub.reactDocgen,
16366
+ reactDocgenTypescript: sub.reactDocgenTypescript,
16367
+ reactComponentMeta: sub.reactComponentMeta
16368
+ }
16369
+ ])
16370
+ )
16371
+ } : {}
16372
+ };
16373
+ }
16374
+
16375
+ // src/componentManifest/componentMetaManagerSingleton.ts
16376
+ import { logger as logger8 } from "storybook/internal/node-logger";
16377
+
16378
+ // src/componentManifest/componentMeta/ComponentMetaManager.ts
16379
+ import { logger as logger7 } from "storybook/internal/node-logger";
16380
+ import { existsSync as existsSync3, watch } from "fs";
16381
+ import * as path3 from "path";
16382
+
16383
+ // src/componentManifest/componentMeta/ComponentMetaProject.ts
16384
+ var import_language_core = __toESM(require_language_core(), 1), import_typescript = __toESM(require_typescript(), 1);
16385
+ import * as path2 from "path";
16386
+
16387
+ // src/componentManifest/componentMeta/componentMetaExtractor.ts
16388
+ var LARGE_SOURCE_THRESHOLD = 30, MAX_UNWRAP_DEPTH = 5, MAX_SERIALIZATION_DEPTH = 5;
16389
+ function isLiteralType(type) {
16390
+ return type.isStringLiteral() || type.isNumberLiteral();
16391
+ }
16392
+ function isUnionType(type) {
16393
+ return type.isUnion();
16394
+ }
16395
+ function isWrappedExpression(typescript, expression) {
16396
+ return typescript.isParenthesizedExpression(expression) || typescript.isAsExpression(expression) || typescript.isNonNullExpression(expression) || (typescript.isSatisfiesExpression?.(expression) ?? !1);
16397
+ }
16398
+ function resolveAliasedSymbol(typescript, checker, symbol) {
16399
+ return symbol.flags & typescript.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
16400
+ }
16401
+ function getSymbolContextNode(symbol) {
16402
+ return symbol.valueDeclaration ?? symbol.getDeclarations()?.[0];
16403
+ }
16404
+ function resolveComponentSymbolFromNode(typescript, checker, node) {
16405
+ if (!node)
16406
+ return;
16407
+ let symbol = checker.getSymbolAtLocation(node);
16408
+ return symbol ? resolveComponentSymbol(typescript, checker, symbol, node) : void 0;
16409
+ }
16410
+ function resolveComponentSymbol(typescript, checker, symbol, contextNode, depth = 0) {
16411
+ let resolved = resolveAliasedSymbol(typescript, checker, symbol);
16412
+ if (depth > MAX_UNWRAP_DEPTH)
16413
+ return resolved;
16414
+ let declarationForPromotion = getSymbolContextNode(resolved);
16415
+ if (declarationForPromotion && (typescript.isArrowFunction(declarationForPromotion) || typescript.isFunctionExpression(declarationForPromotion)) && declarationForPromotion.parent && typescript.isVariableDeclaration(declarationForPromotion.parent) && typescript.isIdentifier(declarationForPromotion.parent.name)) {
16416
+ let variableSymbol = checker.getSymbolAtLocation(declarationForPromotion.parent.name);
16417
+ variableSymbol && (resolved = resolveAliasedSymbol(typescript, checker, variableSymbol));
16418
+ }
16419
+ let declaration = getSymbolContextNode(resolved);
16420
+ if (declaration) {
16421
+ if (typescript.isShorthandPropertyAssignment(declaration)) {
16422
+ let valueSymbol = checker.getShorthandAssignmentValueSymbol(declaration);
16423
+ if (valueSymbol)
16424
+ return resolveComponentSymbol(
16425
+ typescript,
16426
+ checker,
16427
+ valueSymbol,
16428
+ declaration.name,
16429
+ depth + 1
16430
+ );
16431
+ }
16432
+ if (typescript.isPropertyAssignment(declaration)) {
16433
+ let next = resolveComponentSymbolFromNode(typescript, checker, declaration.initializer);
16434
+ if (next)
16435
+ return next;
16436
+ }
16437
+ if (typescript.isBinaryExpression(declaration) && declaration.operatorToken.kind === typescript.SyntaxKind.EqualsToken) {
16438
+ let next = resolveComponentSymbolFromNode(typescript, checker, declaration.right);
16439
+ if (next)
16440
+ return next;
16441
+ }
16442
+ }
16443
+ let typeSymbol = (!!(resolved.flags & typescript.SymbolFlags.Property) || declaration !== void 0 && (typescript.isPropertyAssignment(declaration) || typescript.isShorthandPropertyAssignment(declaration) || typescript.isPropertySignature(declaration) || typescript.isPropertyDeclaration(declaration) || typescript.isBinaryExpression(declaration) && declaration.operatorToken.kind === typescript.SyntaxKind.EqualsToken)) && checker.getTypeOfSymbolAtLocation(resolved, contextNode).getSymbol?.();
16444
+ if (typeSymbol) {
16445
+ let resolvedTypeSymbol = resolveAliasedSymbol(typescript, checker, typeSymbol), typeDeclaration = getSymbolContextNode(resolvedTypeSymbol);
16446
+ if (resolvedTypeSymbol !== resolved && typeDeclaration)
16447
+ return resolveComponentSymbol(
16448
+ typescript,
16449
+ checker,
16450
+ resolvedTypeSymbol,
16451
+ typeDeclaration,
16452
+ depth + 1
16453
+ );
16454
+ }
16455
+ return resolved;
16456
+ }
16457
+ function resolvePropsFromStoryFile(typescript, checker, storySourceFile, componentRef) {
16458
+ let importSpecifier = componentRef.importId, importName = componentRef.importName, memberAccess = componentRef.member;
16459
+ if (!importSpecifier)
16460
+ return;
16461
+ let importSymbol;
16462
+ for (let stmt of storySourceFile.statements) {
16463
+ if (!typescript.isImportDeclaration(stmt))
16464
+ continue;
16465
+ let moduleSpec = stmt.moduleSpecifier;
16466
+ if (!typescript.isStringLiteral(moduleSpec) || moduleSpec.text !== importSpecifier)
16467
+ continue;
16468
+ let clause = stmt.importClause;
16469
+ if (clause) {
16470
+ if (importName === "default") {
16471
+ if (clause.name && (importSymbol = checker.getSymbolAtLocation(clause.name)), !importSymbol && clause.namedBindings && typescript.isNamedImports(clause.namedBindings)) {
16472
+ for (let spec of clause.namedBindings.elements)
16473
+ if ((spec.propertyName ?? spec.name).text === "default") {
16474
+ importSymbol = checker.getSymbolAtLocation(spec.name);
16475
+ break;
16476
+ }
16477
+ }
16478
+ } else if (clause.namedBindings && typescript.isNamedImports(clause.namedBindings)) {
16479
+ for (let spec of clause.namedBindings.elements)
16480
+ if ((spec.propertyName ?? spec.name).text === importName) {
16481
+ importSymbol = checker.getSymbolAtLocation(spec.name);
16482
+ break;
16483
+ }
16266
16484
  }
16267
- let parent = path3.dirname(dir);
16268
- if (parent === dir)
16485
+ if (!importSymbol && memberAccess && clause.namedBindings && typescript.isNamespaceImport(clause.namedBindings) && (importSymbol = checker.getSymbolAtLocation(clause.namedBindings.name)), importSymbol)
16269
16486
  break;
16270
- dir = parent;
16271
16487
  }
16272
- if (this.rootTsConfigs.size === 0)
16273
- return null;
16274
- let prepareClosestRootCommandLine = () => {
16275
- let matches = [];
16276
- for (let rootTsConfig of this.rootTsConfigs)
16277
- isFileInDir(fileName, path3.dirname(rootTsConfig)) && matches.push(rootTsConfig);
16278
- matches = matches.sort((a, b) => sortTSConfigs(fileName, a, b)), matches.length && getCommandLine(matches[0]);
16279
- }, findIndirectReferenceTsconfig = () => findTSConfig((tsconfig) => !!this.configProjects.get(tsconfig)?.hasSourceFile(fileName)), findDirectIncludeTsconfig = () => findTSConfig((tsconfig) => {
16280
- let commandLine = getCommandLine(tsconfig);
16281
- return new Set(commandLine?.fileNames ?? []).has(fileName);
16282
- }), findTSConfig = (match) => {
16283
- let checked = /* @__PURE__ */ new Set();
16284
- for (let rootTsConfig of [...this.rootTsConfigs].sort(
16285
- (a, b) => sortTSConfigs(fileName, a, b)
16286
- )) {
16287
- let project = this.configProjects.get(rootTsConfig);
16288
- if (project) {
16289
- let chains = getReferencesChains(project.getCommandLine(), rootTsConfig, []);
16290
- chains = chains.reverse();
16291
- for (let chain of chains)
16292
- for (let i = chain.length - 1; i >= 0; i--) {
16293
- let tsconfig = chain[i];
16294
- if (!checked.has(tsconfig) && (checked.add(tsconfig), match(tsconfig)))
16295
- return tsconfig;
16488
+ }
16489
+ if (!importSymbol)
16490
+ return;
16491
+ let result;
16492
+ function extractPropsFromJsx(node) {
16493
+ let sig = checker.getResolvedSignature(node);
16494
+ if (!sig)
16495
+ return;
16496
+ let params = sig.getParameters();
16497
+ return params.length === 0 ? checker.getTypeFromTypeNode(typescript.factory.createTypeLiteralNode([])) : checker.getTypeOfSymbolAtLocation(params[0], node);
16498
+ }
16499
+ function visit(node) {
16500
+ if (!result) {
16501
+ if (typescript.isJsxSelfClosingElement(node) || typescript.isJsxOpeningElement(node)) {
16502
+ let tagName = node.tagName;
16503
+ if (memberAccess) {
16504
+ if (typescript.isPropertyAccessExpression(tagName) && tagName.name.text === memberAccess) {
16505
+ let leftSym = checker.getSymbolAtLocation(tagName.expression);
16506
+ if (leftSym && importSymbol && leftSym === importSymbol) {
16507
+ let propsType = extractPropsFromJsx(node);
16508
+ if (propsType) {
16509
+ let memberSymbol = checker.getSymbolAtLocation(tagName.name) ?? checker.getTypeAtLocation(tagName.expression).getProperty(tagName.name.text) ?? resolveComponentSymbolFromNode(typescript, checker, tagName);
16510
+ result = {
16511
+ componentRef,
16512
+ propsType,
16513
+ symbol: memberSymbol ? resolveComponentSymbol(typescript, checker, memberSymbol, tagName.name) : resolveAliasedSymbol(typescript, checker, importSymbol)
16514
+ };
16515
+ return;
16516
+ }
16296
16517
  }
16297
- }
16298
- }
16299
- return null;
16300
- }, getReferencesChains = (commandLine, tsConfig, before) => {
16301
- if (commandLine.projectReferences?.length) {
16302
- let newChains = [];
16303
- for (let projectReference of commandLine.projectReferences) {
16304
- let tsConfigPath = projectReference.path.replace(/\\/g, "/");
16305
- if (this.typescript.sys.directoryExists(tsConfigPath)) {
16306
- let newTsConfigPath = path3.join(tsConfigPath, "tsconfig.json"), newJsConfigPath = path3.join(tsConfigPath, "jsconfig.json");
16307
- this.typescript.sys.fileExists(newTsConfigPath) ? tsConfigPath = newTsConfigPath : this.typescript.sys.fileExists(newJsConfigPath) && (tsConfigPath = newJsConfigPath);
16308
16518
  }
16309
- let beforeIndex = before.indexOf(tsConfigPath);
16310
- if (beforeIndex >= 0)
16311
- newChains.push(before.slice(0, Math.max(beforeIndex, 1)));
16312
- else {
16313
- let referenceCommandLine = getCommandLine(tsConfigPath);
16314
- if (referenceCommandLine)
16315
- for (let chain of getReferencesChains(referenceCommandLine, tsConfigPath, [
16316
- ...before,
16317
- tsConfig
16318
- ]))
16319
- newChains.push(chain);
16519
+ } else if (typescript.isIdentifier(tagName)) {
16520
+ let sym = checker.getSymbolAtLocation(tagName);
16521
+ if (sym && importSymbol && sym === importSymbol) {
16522
+ let propsType = extractPropsFromJsx(node);
16523
+ if (propsType) {
16524
+ result = {
16525
+ componentRef,
16526
+ propsType,
16527
+ symbol: resolveAliasedSymbol(typescript, checker, sym)
16528
+ };
16529
+ return;
16530
+ }
16320
16531
  }
16321
16532
  }
16322
- return newChains;
16323
- } else
16324
- return [[...before, tsConfig]];
16325
- }, getCommandLine = (tsConfig) => this.getOrCreateConfiguredProject(tsConfig)?.getCommandLine();
16326
- return prepareClosestRootCommandLine(), findDirectIncludeTsconfig() ?? findIndirectReferenceTsconfig();
16327
- }
16328
- // ---------------------------------------------------------------------------
16329
- // Adapted from:
16330
- // https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/language-server/lib/project/typescriptProject.ts#L236-L256
16331
- // ---------------------------------------------------------------------------
16332
- getOrCreateConfiguredProject(tsconfig) {
16333
- tsconfig = tsconfig.replace(/\\/g, "/");
16334
- let project = this.configProjects.get(tsconfig);
16335
- if (!project)
16336
- try {
16337
- let getCommandLine = () => this.parseConfigWorker(tsconfig);
16338
- project = new ComponentMetaProject(
16339
- this.typescript,
16340
- getCommandLine(),
16341
- tsconfig,
16342
- this.fsFileSnapshots,
16343
- getCommandLine
16344
- ), this.configProjects.set(tsconfig, project), this.watching && (this.watchDirectory(path3.dirname(tsconfig)), this.watchProgramSourceDirs(project));
16345
- } catch (err) {
16346
- return logger5.debug(`[reactComponentMeta] Failed to parse tsconfig ${tsconfig}: ${err}`), null;
16347
16533
  }
16348
- return project;
16349
- }
16350
- // ---------------------------------------------------------------------------
16351
- // Adapted from:
16352
- // https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/language-server/lib/project/typescriptProject.ts#L258-L284
16353
- // ---------------------------------------------------------------------------
16354
- getOrCreateInferredProject(fileName) {
16355
- return this.inferredProject || (this.inferredProject = new ComponentMetaProject(
16356
- this.typescript,
16357
- {
16358
- options: {
16359
- ...DEFAULT_INFERRED_OPTIONS,
16360
- target: this.typescript.ScriptTarget.Latest,
16361
- module: this.typescript.ModuleKind.ESNext,
16362
- moduleResolution: this.typescript.ModuleResolutionKind.Bundler,
16363
- jsx: this.typescript.JsxEmit.ReactJSX
16364
- },
16365
- fileNames: [],
16366
- errors: []
16367
- },
16368
- void 0,
16369
- this.fsFileSnapshots
16370
- )), this.inferredProject.ensureFiles([fileName]), this.inferredProject;
16371
- }
16372
- // ---------------------------------------------------------------------------
16373
- // Adapted from:
16374
- // https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/language-server/lib/project/typescriptProjectLs.ts#L262-L353
16375
- // ---------------------------------------------------------------------------
16376
- parseConfigWorker(tsconfig) {
16377
- let config = this.typescript.readJsonConfigFile(tsconfig, this.typescript.sys.readFile), content = this.typescript.parseJsonSourceFileConfigFileContent(
16378
- config,
16379
- this.typescript.sys,
16380
- path3.dirname(tsconfig),
16381
- {},
16382
- tsconfig
16383
- );
16384
- return content.options.outDir = void 0, content.fileNames = content.fileNames.map((fileName) => fileName.replace(/\\/g, "/")), content;
16385
- }
16386
- // ---------------------------------------------------------------------------
16387
- // File events
16388
- // ---------------------------------------------------------------------------
16389
- /**
16390
- * Broadcast file changes to all projects. Each project selectively bumps projectVersion.
16391
- *
16392
- * Adapted from:
16393
- * https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/kit/lib/createChecker.ts#L409-L432
16394
- */
16395
- onFilesChanged(changes) {
16396
- for (let project of this.configProjects.values())
16397
- project.onFilesChanged(changes);
16398
- this.inferredProject?.onFilesChanged(changes);
16399
- }
16400
- /**
16401
- * Adapted from:
16402
- * https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/language-server/lib/project/typescriptProject.ts#L43-L68
16403
- */
16404
- onConfigChanged(configPath, type) {
16405
- if (configPath = configPath.replace(/\\/g, "/"), type === "created")
16406
- this.rootTsConfigs.add(configPath);
16407
- else if ((type === "changed" || type === "deleted") && this.configProjects.has(configPath)) {
16408
- type === "deleted" && this.rootTsConfigs.delete(configPath);
16409
- let project = this.configProjects.get(configPath);
16410
- this.configProjects.delete(configPath), project?.dispose();
16534
+ typescript.forEachChild(node, visit);
16411
16535
  }
16412
- this.searchedDirs.clear();
16413
16536
  }
16414
- // ---------------------------------------------------------------------------
16415
- // Our own file watching layer (no Volar equivalent — we're standalone)
16416
- // ---------------------------------------------------------------------------
16417
- startWatching() {
16418
- if (!this.watching) {
16419
- this.watching = !0;
16420
- for (let tsconfig of this.configProjects.keys())
16421
- this.watchDirectory(path3.dirname(tsconfig));
16422
- this.watchProgramSourceDirs();
16423
- }
16537
+ return visit(storySourceFile), result;
16538
+ }
16539
+ function resolvePropsFromComponentType(typescript, checker, componentType) {
16540
+ let callSigs = componentType.getCallSignatures();
16541
+ if (callSigs.length > 0) {
16542
+ let sig = callSigs[0];
16543
+ if (sig.parameters.length === 0)
16544
+ return checker.getVoidType();
16545
+ let propsType = checker.getTypeOfSymbol(sig.parameters[0]);
16546
+ if (!(propsType.flags & typescript.TypeFlags.Any))
16547
+ return propsType;
16424
16548
  }
16425
- /**
16426
- * Watch directories that contain source files from all TS programs. This covers monorepo setups
16427
- * where stories import components via path aliases (e.g. apps/storybook/ imports from
16428
- * packages/ui/ via tsconfig paths).
16429
- */
16430
- watchProgramSourceDirs(singleProject) {
16431
- let dirs = /* @__PURE__ */ new Set();
16432
- if (singleProject)
16433
- for (let filePath of singleProject.getSourceFilePaths())
16434
- dirs.add(path3.dirname(filePath));
16435
- else {
16436
- for (let project of this.configProjects.values())
16437
- for (let filePath of project.getSourceFilePaths())
16438
- dirs.add(path3.dirname(filePath));
16439
- if (this.inferredProject)
16440
- for (let filePath of this.inferredProject.getSourceFilePaths())
16441
- dirs.add(path3.dirname(filePath));
16549
+ let ctorSigs = componentType.getConstructSignatures();
16550
+ for (let sig of ctorSigs) {
16551
+ let propsSym = sig.getReturnType().getProperty("props");
16552
+ if (propsSym) {
16553
+ let propsType = checker.getTypeOfSymbol(propsSym);
16554
+ if (!(propsType.flags & typescript.TypeFlags.Any))
16555
+ return propsType;
16442
16556
  }
16443
- let roots = /* @__PURE__ */ new Set();
16444
- for (let dir of dirs) {
16445
- let candidate = dir;
16446
- for (; candidate !== path3.dirname(candidate); ) {
16447
- let normalized = candidate.replace(/\\/g, "/"), alreadyWatched = !1;
16448
- for (let watched of this.watchersByDir.keys())
16449
- if (normalized === watched || normalized.startsWith(watched + "/")) {
16450
- alreadyWatched = !0;
16451
- break;
16452
- }
16453
- if (alreadyWatched)
16454
- break;
16455
- if (this.typescript.sys.fileExists(path3.join(candidate, "package.json")) || this.typescript.sys.fileExists(path3.join(candidate, "tsconfig.json"))) {
16456
- roots.add(candidate);
16457
- break;
16458
- }
16459
- candidate = path3.dirname(candidate);
16460
- }
16557
+ }
16558
+ }
16559
+ function getPropSourceFile(prop) {
16560
+ let declarations = prop.getDeclarations();
16561
+ if (declarations?.length) {
16562
+ for (let decl of declarations) {
16563
+ let fileName = decl.getSourceFile().fileName;
16564
+ if (!fileName.includes("node_modules") && !fileName.endsWith(".d.ts"))
16565
+ return fileName;
16461
16566
  }
16462
- for (let root of roots)
16463
- this.watchDirectory(root);
16567
+ return declarations[0].getSourceFile().fileName;
16464
16568
  }
16465
- watchDirectory(dir) {
16466
- if (!this.watching)
16467
- return;
16468
- let normalized = dir.replace(/\\/g, "/");
16469
- for (let watched of this.watchersByDir.keys())
16470
- if (normalized === watched || normalized.startsWith(watched + "/"))
16471
- return;
16472
- for (let [watched, watcher] of this.watchersByDir)
16473
- watched.startsWith(normalized + "/") && (watcher.close(), this.watchersByDir.delete(watched));
16474
- try {
16475
- let watcher = watch(dir, { recursive: !0 }, (eventType, filename) => {
16476
- if (!filename)
16477
- return;
16478
- let filePath = path3.resolve(dir, filename).replace(/\\/g, "/");
16479
- if (filePath.includes("/node_modules/") || filePath.includes("/.git/"))
16480
- return;
16481
- let existing = this.pendingEvents.get(filePath);
16482
- existing && clearTimeout(existing), this.pendingEvents.set(
16483
- filePath,
16484
- setTimeout(() => {
16485
- this.pendingEvents.delete(filePath), eventType === "rename" ? existsSync3(filePath) ? this.handleFileEvent(filePath, "created") : this.handleFileEvent(filePath, "deleted") : this.handleFileEvent(filePath, "changed");
16486
- }, 50)
16487
- );
16488
- });
16489
- watcher.unref(), this.watchersByDir.set(normalized, watcher);
16490
- } catch (err) {
16491
- logger5.debug(`[reactComponentMeta] Failed to watch directory ${normalized}: ${err}`);
16492
- }
16493
- }
16494
- stopWatching() {
16495
- for (let timeout of this.pendingEvents.values())
16496
- clearTimeout(timeout);
16497
- this.pendingEvents.clear();
16498
- for (let watcher of this.watchersByDir.values())
16499
- watcher.close();
16500
- this.watchersByDir.clear(), this.watching = !1;
16501
- }
16502
- /**
16503
- * Map raw fs.watch events to LSP-style FileChangeType before broadcasting.
16504
- *
16505
- * Fs.watch reports atomic saves (sed -i, editors) as `rename` → we classify as `created` (file
16506
- * exists after rename). But an IDE/LSP would report an atomic save of an _existing_ file as
16507
- * `Changed`, not `Created`.
16508
- *
16509
- * We reclassify here so that onFilesChanged stays 1:1 with Volar Kit.
16510
- */
16511
- handleFileEvent(filePath, type) {
16512
- if (type === "created") {
16513
- for (let project of this.configProjects.values())
16514
- if (project.hasSourceFile(filePath)) {
16515
- type = "changed";
16516
- break;
16517
- }
16518
- type === "created" && this.inferredProject?.hasSourceFile(filePath) && (type = "changed");
16519
- }
16520
- let basename3 = path3.basename(filePath);
16521
- if (rootTsConfigNames.includes(basename3)) {
16522
- this.onConfigChanged(filePath, type);
16523
- return;
16524
- }
16525
- this.onFilesChanged([{ filePath, type }]);
16526
- }
16527
- dispose() {
16528
- this.stopWatching();
16529
- for (let project of this.configProjects.values())
16530
- project.dispose();
16531
- this.inferredProject?.dispose(), this.configProjects.clear(), this.inferredProject = void 0, this.fsFileSnapshots.clear(), this.searchedDirs.clear(), this.rootTsConfigs.clear();
16532
- }
16533
- };
16534
- function sortTSConfigs(file, a, b) {
16535
- let inA = isFileInDir(file, path3.dirname(a)), inB = isFileInDir(file, path3.dirname(b));
16536
- if (inA !== inB)
16537
- return (inB ? 1 : 0) - (inA ? 1 : 0);
16538
- let aLength = a.split("/").length, bLength = b.split("/").length;
16539
- if (aLength === bLength) {
16540
- let aWeight = path3.basename(a) === "tsconfig.json" ? 1 : 0;
16541
- return (path3.basename(b) === "tsconfig.json" ? 1 : 0) - aWeight;
16569
+ }
16570
+ function getParentType(typescript, prop) {
16571
+ let declarations = prop.getDeclarations();
16572
+ if (!declarations?.length)
16573
+ return;
16574
+ let node = declarations[0].parent;
16575
+ for (; node; ) {
16576
+ if (typescript.isInterfaceDeclaration(node) || typescript.isTypeAliasDeclaration(node))
16577
+ return {
16578
+ name: node.name.getText(),
16579
+ fileName: node.getSourceFile().fileName
16580
+ };
16581
+ node = node.parent;
16542
16582
  }
16543
- return bLength - aLength;
16544
16583
  }
16545
- function isFileInDir(fileName, dir) {
16546
- let relative3 = path3.relative(dir, fileName);
16547
- return !!relative3 && !relative3.startsWith("..") && !path3.isAbsolute(relative3);
16584
+ function getAllDeclarationParents(typescript, prop) {
16585
+ let declarations = prop.getDeclarations();
16586
+ if (!declarations?.length)
16587
+ return;
16588
+ let parents = [];
16589
+ for (let declaration of declarations) {
16590
+ let { parent } = declaration;
16591
+ parent && (typescript.isInterfaceDeclaration(parent) || typescript.isTypeAliasDeclaration(parent) ? parents.push({
16592
+ name: parent.name.getText(),
16593
+ fileName: parent.getSourceFile().fileName
16594
+ }) : typescript.isTypeLiteralNode(parent) && parents.push({
16595
+ name: "TypeLiteral",
16596
+ fileName: parent.getSourceFile().fileName
16597
+ }));
16598
+ }
16599
+ return parents.length > 0 ? parents : void 0;
16548
16600
  }
16549
-
16550
- // src/componentManifest/generateCodeSnippet.ts
16551
- import { types as t2 } from "storybook/internal/babel";
16552
- function getCodeSnippet(csf, storyName, componentName) {
16553
- let storyDeclaration = csf._storyDeclarationPath[storyName], metaObj = csf._metaNode;
16554
- if (!storyDeclaration) {
16555
- let message = "Expected story to be a function or variable declaration";
16556
- throw csf._storyPaths[storyName]?.buildCodeFrameError(message) ?? message;
16601
+ function serializeType(typescript, checker, type, isRequired, depth = 0) {
16602
+ if (depth > MAX_SERIALIZATION_DEPTH)
16603
+ return { name: checker.typeToString(type) };
16604
+ if (type.isUnion()) {
16605
+ let nonUndefinedTypes = type.types.filter(
16606
+ (t6) => !(t6.getFlags() & typescript.TypeFlags.Undefined)
16607
+ ), literalMembers = nonUndefinedTypes.filter(isLiteralType);
16608
+ if (literalMembers.length > 0 && literalMembers.length === nonUndefinedTypes.length)
16609
+ return {
16610
+ name: "enum",
16611
+ raw: literalMembers.map((m) => checker.typeToString(m)).join(" | "),
16612
+ value: literalMembers.map((m) => ({
16613
+ value: JSON.stringify(m.value)
16614
+ }))
16615
+ };
16616
+ if (!isRequired && nonUndefinedTypes.length === 1 && nonUndefinedTypes.length < type.types.length)
16617
+ return { name: checker.typeToString(nonUndefinedTypes[0]) };
16557
16618
  }
16558
- let storyPath;
16559
- if (storyDeclaration.isFunctionDeclaration())
16560
- storyPath = storyDeclaration;
16561
- else if (storyDeclaration.isVariableDeclarator()) {
16562
- let init = storyDeclaration.get("init");
16563
- invariant(
16564
- init.isExpression(),
16565
- () => storyDeclaration.buildCodeFrameError("Expected story initializer to be an expression").message
16566
- ), storyPath = init;
16567
- } else
16568
- throw storyDeclaration.buildCodeFrameError(
16569
- "Expected story to be a function or variable declaration"
16570
- );
16571
- let normalizedPath = storyPath;
16572
- if (storyPath.isCallExpression()) {
16573
- let callee = storyPath.get("callee");
16574
- if (callee.isMemberExpression()) {
16575
- let obj = callee.get("object"), prop = callee.get("property"), isBind = prop.isIdentifier() && prop.node.name === "bind" || t2.isStringLiteral(prop.node) && prop.node.value === "bind";
16576
- if (obj.isIdentifier() && isBind) {
16577
- let resolved = resolveIdentifierInit(storyDeclaration, obj);
16578
- resolved && (normalizedPath = resolved);
16619
+ let constraint = type.getConstraint?.();
16620
+ return constraint && constraint !== type ? serializeType(typescript, checker, constraint, isRequired, depth + 1) : { name: checker.typeToString(type) };
16621
+ }
16622
+ function unwrapToFunction(typescript, node, depth = 0, checker) {
16623
+ if (!(depth > MAX_UNWRAP_DEPTH)) {
16624
+ if (typescript.isArrowFunction(node) || typescript.isFunctionExpression(node) || typescript.isFunctionDeclaration(node))
16625
+ return node;
16626
+ if (typescript.isCallExpression(node))
16627
+ for (let arg of node.arguments) {
16628
+ let fn = unwrapToFunction(typescript, arg, depth + 1, checker);
16629
+ if (fn)
16630
+ return fn;
16579
16631
  }
16580
- }
16581
- if (storyPath === normalizedPath) {
16582
- let args = storyPath.get("arguments");
16583
- if (args.length !== 0) {
16584
- invariant(
16585
- args.length === 1,
16586
- () => storyPath.buildCodeFrameError("Could not evaluate story expression").message
16587
- );
16588
- let storyArg = args[0];
16589
- invariant(
16590
- storyArg.isExpression(),
16591
- () => storyPath.buildCodeFrameError("Could not evaluate story expression").message
16592
- ), normalizedPath = storyArg;
16632
+ if (typescript.isParenthesizedExpression(node) || typescript.isAsExpression(node))
16633
+ return unwrapToFunction(typescript, node.expression, depth + 1, checker);
16634
+ if (typescript.isIdentifier(node) && checker) {
16635
+ let symbol = checker.getSymbolAtLocation(node);
16636
+ if (symbol) {
16637
+ let decl = (symbol.flags & typescript.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol).valueDeclaration;
16638
+ if (decl && typescript.isVariableDeclaration(decl) && decl.initializer)
16639
+ return unwrapToFunction(typescript, decl.initializer, depth + 1, checker);
16640
+ if (decl && typescript.isFunctionDeclaration(decl))
16641
+ return decl;
16593
16642
  }
16594
16643
  }
16595
16644
  }
16596
- normalizedPath = normalizedPath.isTSSatisfiesExpression() || normalizedPath.isTSAsExpression() ? normalizedPath.get("expression") : normalizedPath;
16597
- let storyFn;
16598
- if (normalizedPath.isArrowFunctionExpression() || normalizedPath.isFunctionExpression() || normalizedPath.isFunctionDeclaration())
16599
- storyFn = normalizedPath;
16600
- else if (!normalizedPath.isObjectExpression() && !(normalizedPath.isCallExpression() && Array.isArray(normalizedPath.node.arguments) && normalizedPath.node.arguments.length === 0))
16601
- throw normalizedPath.buildCodeFrameError(
16602
- "Expected story to be csf factory, function or an object expression"
16603
- );
16604
- let storyProps = normalizedPath.isObjectExpression() ? normalizedPath.get("properties").filter((p) => p.isObjectProperty()) : [], metaPath = pathForNode(csf._file.path, metaObj), metaProps = metaPath?.isObjectExpression() ? metaPath.get("properties").filter((p) => p.isObjectProperty()) : [], getRenderPath = (object) => {
16605
- let renderPath = object.find((p) => keyOf(p.node) === "render")?.get("value");
16606
- if (!renderPath)
16607
- return { kind: "missing" };
16608
- if (renderPath.isIdentifier()) {
16609
- let resolved = resolveIdentifierInit(storyDeclaration, renderPath);
16610
- return resolved && (resolved.isArrowFunctionExpression() || resolved.isFunctionExpression() || resolved.isFunctionDeclaration()) ? { kind: "resolved", path: resolved } : { kind: "unresolved" };
16611
- }
16612
- if (!(renderPath.isArrowFunctionExpression() || renderPath.isFunctionExpression()))
16613
- throw renderPath.buildCodeFrameError(
16614
- "Expected render to be an arrow function or function expression"
16615
- );
16616
- return { kind: "resolved", path: renderPath };
16617
- }, metaRender = getRenderPath(metaProps), storyRender = getRenderPath(storyProps);
16618
- storyFn || (storyFn = storyRender.kind === "resolved" ? storyRender.path : storyRender.kind === "missing" && metaRender.kind === "resolved" ? metaRender.path : void 0);
16619
- let metaArgs = metaArgsRecord(metaObj ?? null), storyArgsPath = storyProps.filter((p) => keyOf(p.node) === "args").map((p) => p.get("value")).find((v) => v.isObjectExpression()), storyArgs = argsRecordFromObjectPath(storyArgsPath), storyAssignedArgsPath = storyArgsAssignmentPath(csf._file.path, storyName), storyAssignedArgs = argsRecordFromObjectPath(storyAssignedArgsPath), merged = { ...metaArgs, ...storyArgs, ...storyAssignedArgs }, entries = Object.entries(merged).filter(([k]) => k !== "children"), validEntries = entries.filter(([k, v]) => isValidJsxAttrName(k) && v != null), invalidEntries = entries.filter(([k, v]) => !isValidJsxAttrName(k) && v != null), injectedAttrs = validEntries.map(([k, v]) => toAttr(k, v)).filter((a) => a != null);
16620
- if (storyFn) {
16621
- let fn = storyFn.node;
16622
- if (t2.isArrowFunctionExpression(fn) && (t2.isJSXElement(fn.body) || t2.isJSXFragment(fn.body))) {
16623
- let spreadRes = transformArgsSpreadsInJsx(fn.body, merged), inlineRes = inlineArgsInJsx(spreadRes.node, merged);
16624
- if (spreadRes.changed || inlineRes.changed) {
16625
- let newFn = t2.arrowFunctionExpression([], inlineRes.node, fn.async);
16626
- return t2.variableDeclaration("const", [
16627
- t2.variableDeclarator(t2.identifier(storyName), newFn)
16628
- ]);
16629
- }
16630
- }
16631
- let stmts = t2.isFunctionDeclaration(fn) || t2.isArrowFunctionExpression(fn) && t2.isBlockStatement(fn.body) || t2.isFunctionExpression(fn) && t2.isBlockStatement(fn.body) ? fn.body.body : void 0;
16632
- if (stmts) {
16633
- let changed = !1, newBody = stmts.map((stmt) => {
16634
- if (t2.isReturnStatement(stmt) && stmt.argument && (t2.isJSXElement(stmt.argument) || t2.isJSXFragment(stmt.argument))) {
16635
- let spreadRes = transformArgsSpreadsInJsx(stmt.argument, merged), inlineRes = inlineArgsInJsx(spreadRes.node, merged);
16636
- if (spreadRes.changed || inlineRes.changed)
16637
- return changed = !0, t2.returnStatement(inlineRes.node);
16638
- }
16639
- return stmt;
16640
- });
16641
- if (changed)
16642
- return t2.isFunctionDeclaration(fn) ? t2.functionDeclaration(
16643
- t2.identifier(storyName),
16644
- [],
16645
- t2.blockStatement(newBody),
16646
- fn.generator,
16647
- fn.async
16648
- ) : t2.variableDeclaration("const", [
16649
- t2.variableDeclarator(
16650
- t2.identifier(storyName),
16651
- t2.arrowFunctionExpression([], t2.blockStatement(newBody), fn.async)
16652
- )
16653
- ]);
16645
+ }
16646
+ function resolveLiteralValue(typescript, checker, node, depth = 0) {
16647
+ if (depth > MAX_UNWRAP_DEPTH || typescript.isStringLiteral(node) || typescript.isNumericLiteral(node) || typescript.isNoSubstitutionTemplateLiteral(node) || node.kind === typescript.SyntaxKind.TrueKeyword || node.kind === typescript.SyntaxKind.FalseKeyword || node.kind === typescript.SyntaxKind.NullKeyword)
16648
+ return node.getText();
16649
+ if (typescript.isIdentifier(node)) {
16650
+ if (node.text === "undefined")
16651
+ return "undefined";
16652
+ let symbol = checker.getSymbolAtLocation(node);
16653
+ if (!symbol)
16654
+ return node.getText();
16655
+ let decl = (symbol.flags & typescript.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol).valueDeclaration;
16656
+ return decl && typescript.isVariableDeclaration(decl) && decl.initializer || decl && typescript.isEnumMember(decl) && decl.initializer || decl && typescript.isBindingElement(decl) && decl.initializer ? resolveLiteralValue(typescript, checker, decl.initializer, depth + 1) : node.getText();
16657
+ }
16658
+ if (typescript.isPropertyAccessExpression(node)) {
16659
+ let symbol = checker.getSymbolAtLocation(node);
16660
+ if (symbol) {
16661
+ let decl = symbol.valueDeclaration;
16662
+ if (decl && typescript.isEnumMember(decl) && decl.initializer || decl && typescript.isPropertyAssignment(decl) && decl.initializer || decl && typescript.isVariableDeclaration(decl) && decl.initializer)
16663
+ return resolveLiteralValue(typescript, checker, decl.initializer, depth + 1);
16654
16664
  }
16655
- return t2.isFunctionDeclaration(fn) ? t2.functionDeclaration(t2.identifier(storyName), fn.params, fn.body, fn.generator, fn.async) : t2.variableDeclaration("const", [t2.variableDeclarator(t2.identifier(storyName), fn)]);
16665
+ return node.getText();
16656
16666
  }
16657
- invariant(componentName, "Could not generate snippet without component name.");
16658
- let invalidSpread = buildInvalidSpread(invalidEntries), name = t2.jsxIdentifier(componentName), openingElAttrs = invalidSpread ? [...injectedAttrs, invalidSpread] : injectedAttrs, children = toJsxChildren(merged.children), selfClosing = children.length === 0, arrow = t2.arrowFunctionExpression(
16659
- [],
16660
- t2.jsxElement(
16661
- t2.jsxOpeningElement(name, openingElAttrs, selfClosing),
16662
- selfClosing ? null : t2.jsxClosingElement(name),
16663
- children,
16664
- selfClosing
16665
- )
16666
- );
16667
- return t2.variableDeclaration("const", [t2.variableDeclarator(t2.identifier(storyName), arrow)]);
16667
+ return node.getText();
16668
16668
  }
16669
- function buildInvalidSpread(entries) {
16670
- if (entries.length === 0)
16671
- return null;
16672
- let objectProps = entries.map(
16673
- ([k, v]) => t2.objectProperty(t2.stringLiteral(k), t2.isExpression(v) ? v : t2.identifier("undefined"))
16674
- );
16675
- return t2.jsxSpreadAttribute(t2.objectExpression(objectProps));
16676
- }
16677
- var keyOf = (p) => t2.isIdentifier(p.key) ? p.key.name : t2.isStringLiteral(p.key) ? p.key.value : null, isValidJsxAttrName = (n) => /^[A-Za-z_][A-Za-z0-9_:-]*$/.test(n), argsRecordFromObjectPath = (objPath) => objPath ? Object.fromEntries(
16678
- objPath.get("properties").filter((p) => p.isObjectProperty()).map((p) => [keyOf(p.node), p.get("value").node]).filter((e) => !!e[0])
16679
- ) : {};
16680
- function storyArgsAssignmentPath(program, storyName) {
16681
- let found = null;
16682
- return program.traverse({
16683
- AssignmentExpression(p) {
16684
- let left = p.get("left"), right = p.get("right");
16685
- if (left.isMemberExpression()) {
16686
- let obj = left.get("object"), prop = left.get("property"), isStoryIdent = obj.isIdentifier() && obj.node.name === storyName, isArgsProp = prop.isIdentifier() && prop.node.name === "args" && !left.node.computed || t2.isStringLiteral(prop.node) && left.node.computed && prop.node.value === "args";
16687
- isStoryIdent && isArgsProp && right.isObjectExpression() && (found = right);
16688
- }
16669
+ function collectBindingDefaults(typescript, pattern, defaults, checker) {
16670
+ for (let element of pattern.elements)
16671
+ if (element.initializer) {
16672
+ let propName = element.propertyName ? element.propertyName.getText() : element.name.getText();
16673
+ defaults.set(
16674
+ propName,
16675
+ checker ? resolveLiteralValue(typescript, checker, element.initializer) : element.initializer.getText()
16676
+ );
16689
16677
  }
16690
- }), found;
16691
16678
  }
16692
- var argsRecordFromObjectNode = (obj) => obj ? Object.fromEntries(
16693
- obj.properties.filter((p) => t2.isObjectProperty(p)).map((p) => [keyOf(p), p.value]).filter((e) => !!e[0])
16694
- ) : {}, metaArgsRecord = (meta) => {
16695
- if (!meta)
16696
- return {};
16697
- let argsProp = meta.properties.find(
16698
- (p) => t2.isObjectProperty(p) && keyOf(p) === "args"
16699
- );
16700
- return argsProp && t2.isObjectExpression(argsProp.value) ? argsRecordFromObjectNode(argsProp.value) : {};
16701
- }, toAttr = (key, value) => t2.isBooleanLiteral(value) ? value.value ? t2.jsxAttribute(t2.jsxIdentifier(key), null) : t2.jsxAttribute(t2.jsxIdentifier(key), t2.jsxExpressionContainer(value)) : t2.isStringLiteral(value) ? t2.jsxAttribute(t2.jsxIdentifier(key), t2.stringLiteral(value.value)) : t2.isExpression(value) ? t2.jsxAttribute(t2.jsxIdentifier(key), t2.jsxExpressionContainer(value)) : null, toJsxChildren = (node) => node ? t2.isStringLiteral(node) ? [t2.jsxText(node.value)] : t2.isJSXElement(node) || t2.isJSXFragment(node) ? [node] : t2.isExpression(node) ? [t2.jsxExpressionContainer(node)] : [] : [];
16702
- function getArgsMemberKey(expr) {
16703
- if (t2.isMemberExpression(expr) && t2.isIdentifier(expr.object) && expr.object.name === "args") {
16704
- if (t2.isIdentifier(expr.property) && !expr.computed)
16705
- return expr.property.name;
16706
- if (t2.isStringLiteral(expr.property) && expr.computed)
16707
- return expr.property.value;
16708
- }
16709
- if (t2.isOptionalMemberExpression?.(expr) && t2.isIdentifier(expr.object) && expr.object.name === "args") {
16710
- let prop = expr.property;
16711
- if (t2.isIdentifier(prop) && !expr.computed)
16712
- return prop.name;
16713
- if (t2.isStringLiteral(prop) && expr.computed)
16714
- return prop.value;
16715
- }
16716
- return null;
16679
+ function unwrapExpression(typescript, expression) {
16680
+ let current2 = expression;
16681
+ for (; isWrappedExpression(typescript, current2); )
16682
+ current2 = current2.expression;
16683
+ return current2;
16717
16684
  }
16718
- function inlineArgsInJsx(node, merged) {
16719
- let changed = !1;
16720
- if (t2.isJSXElement(node)) {
16721
- let opening = node.openingElement, newAttrs = opening.attributes.flatMap((a) => {
16722
- if (!t2.isJSXAttribute(a))
16723
- return [a];
16724
- let name = t2.isJSXIdentifier(a.name) ? a.name.name : null;
16725
- if (!(name && a.value && t2.isJSXExpressionContainer(a.value)))
16726
- return [a];
16727
- let key = getArgsMemberKey(a.value.expression);
16728
- if (!(key && key in merged))
16729
- return [a];
16730
- let repl = toAttr(name, merged[key]);
16731
- return changed = !0, repl ? [repl] : [];
16732
- }), newChildren = node.children.flatMap((c) => {
16733
- if (t2.isJSXElement(c) || t2.isJSXFragment(c)) {
16734
- let res = inlineArgsInJsx(c, merged);
16735
- return changed ||= res.changed, [res.node];
16736
- }
16737
- return t2.isJSXExpressionContainer(c) && getArgsMemberKey(c.expression) === "children" && merged.children ? (changed = !0, toJsxChildren(merged.children)) : [c];
16738
- }), selfClosing = opening.selfClosing && newChildren.length === 0;
16739
- return {
16740
- node: t2.jsxElement(
16741
- t2.jsxOpeningElement(opening.name, newAttrs, selfClosing),
16742
- selfClosing ? null : node.closingElement ?? t2.jsxClosingElement(opening.name),
16743
- newChildren,
16744
- selfClosing
16745
- ),
16746
- changed
16747
- };
16748
- }
16749
- let fragChildren = node.children.flatMap((c) => {
16750
- if (t2.isJSXElement(c) || t2.isJSXFragment(c)) {
16751
- let res = inlineArgsInJsx(c, merged);
16752
- return changed ||= res.changed, [res.node];
16753
- }
16754
- return t2.isJSXExpressionContainer(c) && getArgsMemberKey(c.expression) === "children" && "children" in merged ? (changed = !0, toJsxChildren(merged.children)) : [c];
16755
- });
16756
- return { node: t2.jsxFragment(node.openingFragment, node.closingFragment, fragChildren), changed };
16685
+ function isPropsIdentifier(typescript, node, paramName, checker) {
16686
+ if (!typescript.isIdentifier(node))
16687
+ return !1;
16688
+ if (!checker)
16689
+ return node.text === paramName.text;
16690
+ let symbol = checker.getSymbolAtLocation(node), paramSymbol = checker.getSymbolAtLocation(paramName);
16691
+ return symbol !== void 0 && symbol === paramSymbol;
16757
16692
  }
16758
- function transformArgsSpreadsInJsx(node, merged) {
16759
- let changed = !1, makeInjectedPieces = (existing) => {
16760
- let entries = Object.entries(merged).filter(([k, v]) => v != null && k !== "children"), validEntries = entries.filter(([k]) => isValidJsxAttrName(k)), invalidEntries = entries.filter(([k]) => !isValidJsxAttrName(k)), injectedAttrs = validEntries.map(([k, v]) => toAttr(k, v)).filter((a) => !!a).filter((a) => t2.isJSXIdentifier(a.name) && !existing.has(a.name.name)), invalidSpread = buildInvalidSpread(invalidEntries.filter(([k]) => !existing.has(k)));
16761
- return invalidSpread ? [...injectedAttrs, invalidSpread] : injectedAttrs;
16762
- };
16763
- if (t2.isJSXElement(node)) {
16764
- let opening = node.openingElement, attrs = opening.attributes, isArgsSpread = (a) => t2.isJSXSpreadAttribute(a) && t2.isIdentifier(a.argument) && a.argument.name === "args", sawArgsSpread = attrs.some(isArgsSpread), firstIdx = attrs.findIndex(isArgsSpread), nonArgsAttrs = attrs.filter((a) => !isArgsSpread(a)), insertionIndex = sawArgsSpread ? attrs.slice(0, firstIdx).filter((a) => !isArgsSpread(a)).length : 0, newAttrs = sawArgsSpread ? (() => {
16765
- let existing = new Set(
16766
- nonArgsAttrs.filter((a) => t2.isJSXAttribute(a)).flatMap((a) => t2.isJSXIdentifier(a.name) ? [a.name.name] : [])
16767
- ), pieces = makeInjectedPieces(existing);
16768
- return changed = !0, [
16769
- ...nonArgsAttrs.slice(0, insertionIndex),
16770
- ...pieces,
16771
- ...nonArgsAttrs.slice(insertionIndex)
16772
- ];
16773
- })() : nonArgsAttrs, newChildren = node.children.flatMap((c) => {
16774
- if (t2.isJSXElement(c) || t2.isJSXFragment(c)) {
16775
- let res = transformArgsSpreadsInJsx(c, merged);
16776
- return changed ||= res.changed, [res.node];
16777
- }
16778
- return [c];
16779
- }), children = sawArgsSpread && newChildren.length === 0 && merged.children ? (changed = !0, toJsxChildren(merged.children)) : newChildren, selfClosing = children.length === 0;
16780
- return {
16781
- node: t2.jsxElement(
16782
- t2.jsxOpeningElement(opening.name, newAttrs, selfClosing),
16783
- selfClosing ? null : node.closingElement ?? t2.jsxClosingElement(opening.name),
16784
- children,
16785
- selfClosing
16786
- ),
16787
- changed
16788
- };
16789
- }
16790
- let fragChildren = node.children.flatMap((c) => {
16791
- if (t2.isJSXElement(c) || t2.isJSXFragment(c)) {
16792
- let res = transformArgsSpreadsInJsx(c, merged);
16793
- return changed ||= res.changed, [res.node];
16794
- }
16795
- return [c];
16796
- });
16797
- return { node: t2.jsxFragment(node.openingFragment, node.closingFragment, fragChildren), changed };
16693
+ function isPropsDerivedInitializer(typescript, initializer, paramName, checker) {
16694
+ let expr = unwrapExpression(typescript, initializer);
16695
+ return isPropsIdentifier(typescript, expr, paramName, checker) ? !0 : typescript.isAwaitExpression(expr) ? isPropsDerivedInitializer(typescript, expr.expression, paramName, checker) : typescript.isBinaryExpression(expr) && [
16696
+ typescript.SyntaxKind.BarBarToken,
16697
+ typescript.SyntaxKind.QuestionQuestionToken,
16698
+ typescript.SyntaxKind.AmpersandAmpersandToken
16699
+ ].includes(expr.operatorToken.kind) ? isPropsDerivedInitializer(typescript, expr.left, paramName, checker) || isPropsDerivedInitializer(typescript, expr.right, paramName, checker) : typescript.isConditionalExpression(expr) ? isPropsDerivedInitializer(typescript, expr.whenTrue, paramName, checker) || isPropsDerivedInitializer(typescript, expr.whenFalse, paramName, checker) : typescript.isCallExpression(expr) || typescript.isNewExpression(expr) ? expr.arguments?.some(
16700
+ (arg) => isPropsDerivedInitializer(typescript, arg, paramName, checker)
16701
+ ) ?? !1 : !1;
16798
16702
  }
16799
- function resolveIdentifierInit(storyPath, identifier) {
16800
- let programPath = storyPath.findParent((p) => p.isProgram());
16801
- if (!programPath)
16802
- return null;
16803
- for (let stmt of programPath.get("body")) {
16804
- if (stmt.isFunctionDeclaration() && stmt.node.id?.name === identifier.node.name)
16805
- return stmt;
16806
- if (stmt.isExportNamedDeclaration()) {
16807
- let decl = stmt.get("declaration");
16808
- if (decl.isFunctionDeclaration() && decl.node.id?.name === identifier.node.name)
16809
- return decl;
16703
+ function extractDestructuringDefaults(typescript, resolved, checker) {
16704
+ let defaults = /* @__PURE__ */ new Map(), decl = resolved.valueDeclaration;
16705
+ if (!decl)
16706
+ return defaults;
16707
+ let fn;
16708
+ if (typescript.isFunctionDeclaration(decl)) {
16709
+ if (fn = decl, !fn.body) {
16710
+ let allDecls = resolved.getDeclarations?.() ?? [];
16711
+ for (let d of allDecls)
16712
+ if (typescript.isFunctionDeclaration(d) && d.body) {
16713
+ fn = d;
16714
+ break;
16715
+ }
16810
16716
  }
16811
- }
16812
- let match = programPath.get("body").flatMap((stmt) => {
16813
- if (stmt.isVariableDeclaration())
16814
- return stmt.get("declarations");
16815
- if (stmt.isExportNamedDeclaration()) {
16816
- let decl = stmt.get("declaration");
16817
- if (decl && decl.isVariableDeclaration())
16818
- return decl.get("declarations");
16717
+ } else typescript.isVariableDeclaration(decl) && decl.initializer ? fn = unwrapToFunction(typescript, decl.initializer, 0, checker) : typescript.isExportAssignment(decl) && decl.expression && (fn = unwrapToFunction(typescript, decl.expression, 0, checker));
16718
+ if (!fn)
16719
+ return defaults;
16720
+ let firstParam = fn.parameters[0];
16721
+ if (!firstParam)
16722
+ return defaults;
16723
+ if (typescript.isObjectBindingPattern(firstParam.name))
16724
+ return collectBindingDefaults(typescript, firstParam.name, defaults, checker), defaults;
16725
+ let propsParamName = typescript.isIdentifier(firstParam.name) ? firstParam.name : void 0;
16726
+ if (fn.body && propsParamName) {
16727
+ let body = typescript.isBlock(fn.body) ? fn.body : void 0;
16728
+ if (body) {
16729
+ for (let stmt of body.statements)
16730
+ if (typescript.isVariableStatement(stmt))
16731
+ for (let varDecl of stmt.declarationList.declarations)
16732
+ typescript.isObjectBindingPattern(varDecl.name) && varDecl.initializer && isPropsDerivedInitializer(typescript, varDecl.initializer, propsParamName, checker) && collectBindingDefaults(typescript, varDecl.name, defaults, checker);
16819
16733
  }
16820
- return [];
16821
- }).find((d) => {
16822
- let id = d.get("id");
16823
- return id.isIdentifier() && id.node.name === identifier.node.name;
16824
- });
16825
- if (!match)
16826
- return null;
16827
- let init = match.get("init");
16828
- return init && init.isExpression() ? init : null;
16734
+ }
16735
+ return defaults;
16829
16736
  }
16830
- function pathForNode(program, target) {
16831
- if (!target)
16832
- return;
16833
- let found;
16834
- return program.traverse({
16835
- enter(p) {
16836
- p.node && p.node === target && (found = p, p.stop());
16737
+ function collectObjectLiteralDefaults(typescript, checker, obj, defaults) {
16738
+ for (let prop of obj.properties)
16739
+ if (typescript.isPropertyAssignment(prop) && prop.name) {
16740
+ let name = prop.name.getText();
16741
+ defaults.set(name, resolveLiteralValue(typescript, checker, prop.initializer));
16742
+ } else if (typescript.isShorthandPropertyAssignment(prop)) {
16743
+ let name = prop.name.getText(), symbol = checker.getShorthandAssignmentValueSymbol(prop);
16744
+ symbol?.valueDeclaration && typescript.isVariableDeclaration(symbol.valueDeclaration) && symbol.valueDeclaration.initializer ? defaults.set(
16745
+ name,
16746
+ resolveLiteralValue(typescript, checker, symbol.valueDeclaration.initializer)
16747
+ ) : defaults.set(name, name);
16837
16748
  }
16838
- }), found;
16839
16749
  }
16840
-
16841
- // src/componentManifest/getComponentImports.ts
16842
- import { dirname as dirname8 } from "node:path";
16843
- import { babelParse as babelParse2, recast, types as t3 } from "storybook/internal/babel";
16844
- import { logger as logger7 } from "storybook/internal/node-logger";
16845
-
16846
- // src/componentManifest/reactDocgenTypescript.ts
16847
- import { dirname as dirname7 } from "node:path";
16848
- import { logger as logger6 } from "storybook/internal/node-logger";
16849
- var typeScriptPromise, reactDocgenTypescriptPromise, loadTypeScript = () => typeScriptPromise ??= import("typescript"), loadReactDocgenTypescript = () => reactDocgenTypescriptPromise ??= import("react-docgen-typescript"), LARGE_NON_USER_SOURCE_THRESHOLD = 30, getPropSource = (prop) => prop.parent?.fileName ?? prop.declarations?.[0]?.fileName, getLargeNonUserPropSources = (props) => {
16850
- let countBySource = /* @__PURE__ */ new Map();
16851
- for (let prop of Object.values(props)) {
16852
- let source = getPropSource(prop);
16853
- (source?.includes("node_modules") || source?.endsWith(".d.ts")) && countBySource.set(source, (countBySource.get(source) ?? 0) + 1);
16854
- }
16855
- let largeNonUserSources = /* @__PURE__ */ new Set();
16856
- for (let [source, count] of countBySource)
16857
- count > LARGE_NON_USER_SOURCE_THRESHOLD && largeNonUserSources.add(source);
16858
- return largeNonUserSources;
16859
- };
16860
- function findDisplayNameAssignment(typescript, sourceFile, identifierName) {
16861
- for (let statement of sourceFile.statements) {
16862
- if (!typescript.isExpressionStatement(statement))
16863
- continue;
16864
- let expr = statement.expression;
16865
- if (typescript.isBinaryExpression(expr) && expr.operatorToken.kind === typescript.SyntaxKind.EqualsToken && typescript.isPropertyAccessExpression(expr.left) && expr.left.name.text === "displayName" && typescript.isIdentifier(expr.left.expression) && expr.left.expression.text === identifierName && typescript.isStringLiteral(expr.right))
16866
- return expr.right.text;
16750
+ function extractStaticDefaultProps(typescript, checker, resolved) {
16751
+ let defaults = /* @__PURE__ */ new Map(), decl = resolved.valueDeclaration ?? resolved.getDeclarations()?.[0];
16752
+ if (!decl)
16753
+ return defaults;
16754
+ let componentSourceFile = decl.getSourceFile();
16755
+ for (let stmt of componentSourceFile.statements) {
16756
+ if (typescript.isClassDeclaration(stmt) && stmt.name) {
16757
+ if (checker.getSymbolAtLocation(stmt.name) !== resolved)
16758
+ continue;
16759
+ for (let member of stmt.members) {
16760
+ if (!typescript.isPropertyDeclaration(member) || !member.name || member.name.getText() !== "defaultProps" || !member.initializer)
16761
+ continue;
16762
+ let initializer = member.initializer;
16763
+ if (typescript.isIdentifier(initializer)) {
16764
+ let symDecl = checker.getSymbolAtLocation(initializer)?.valueDeclaration;
16765
+ symDecl && typescript.isVariableDeclaration(symDecl) && symDecl.initializer && (initializer = symDecl.initializer);
16766
+ }
16767
+ typescript.isObjectLiteralExpression(initializer) && collectObjectLiteralDefaults(typescript, checker, initializer, defaults);
16768
+ }
16769
+ }
16770
+ if (typescript.isExpressionStatement(stmt) && typescript.isBinaryExpression(stmt.expression) && stmt.expression.operatorToken.kind === typescript.SyntaxKind.EqualsToken) {
16771
+ let left = stmt.expression.left;
16772
+ if (!typescript.isPropertyAccessExpression(left) || left.name.text !== "defaultProps")
16773
+ continue;
16774
+ let targetSymbol = checker.getSymbolAtLocation(left.expression);
16775
+ if (!targetSymbol || (targetSymbol.flags & typescript.SymbolFlags.Alias ? checker.getAliasedSymbol(targetSymbol) : targetSymbol) !== resolved)
16776
+ continue;
16777
+ let right = stmt.expression.right;
16778
+ if (typescript.isIdentifier(right)) {
16779
+ let symDecl = checker.getSymbolAtLocation(right)?.valueDeclaration;
16780
+ symDecl && typescript.isVariableDeclaration(symDecl) && symDecl.initializer && (right = symDecl.initializer);
16781
+ }
16782
+ typescript.isObjectLiteralExpression(right) && collectObjectLiteralDefaults(typescript, checker, right, defaults);
16783
+ }
16867
16784
  }
16785
+ return defaults;
16868
16786
  }
16869
- function getExportNameMap(typescript, checker, sourceFile) {
16870
- let moduleSymbol = checker.getSymbolAtLocation(sourceFile);
16871
- if (!moduleSymbol)
16872
- return /* @__PURE__ */ new Map();
16873
- let result = /* @__PURE__ */ new Map(), fileName = sourceFile.fileName.replace(/.*\//, "").replace(/\.[^.]+$/, "");
16874
- for (let exportSymbol of checker.getExportsOfModule(moduleSymbol)) {
16875
- let resolved = exportSymbol.flags & typescript.SymbolFlags.Alias ? checker.getAliasedSymbol(exportSymbol) : exportSymbol, declaration = resolved.valueDeclaration ?? resolved.getDeclarations()?.[0];
16876
- if (!declaration)
16877
- continue;
16878
- let type = checker.getTypeOfSymbolAtLocation(resolved, declaration), isStateless = type.getCallSignatures().some((sig) => {
16879
- let params = sig.getParameters();
16880
- return params.length === 1 || params.length > 0 && params[0].getName() === "props";
16881
- }), isStateful = type.getConstructSignatures().some(
16882
- (sig) => sig.getReturnType().getProperty("props") !== void 0
16883
- );
16884
- if (isStateless || isStateful) {
16885
- let exportName = exportSymbol.getName(), resolvedName = resolved.getName();
16886
- result.set(resolvedName, exportName), exportName === "default" && result.set(fileName, "default");
16887
- let displayNameValue = findDisplayNameAssignment(typescript, sourceFile, resolvedName);
16888
- displayNameValue && result.set(displayNameValue, exportName);
16889
- }
16890
- }
16891
- return result;
16787
+ function getJSDocDefault(typescript, prop, checker) {
16788
+ let tags = prop.getJsDocTags(checker);
16789
+ for (let tag of tags)
16790
+ if (tag.name === "default" || tag.name === "defaultValue")
16791
+ return typescript.displayPartsToString(tag.text) || void 0;
16892
16792
  }
16893
- var cachedCompilerOptions, cachedFileNames, previousProgram, parser, cachedParserOptionsKey;
16894
- function invalidateParser() {
16895
- parser = void 0, cachedCompilerOptions = void 0, cachedFileNames = void 0, cachedParserOptionsKey = void 0;
16793
+ function extractPropItem(typescript, checker, prop, contextNode, defaultsMap) {
16794
+ let isRequired = !!!(prop.flags & typescript.SymbolFlags.Optional), propType = checker.getTypeOfSymbolAtLocation(prop, contextNode), type = serializeType(typescript, checker, propType, isRequired), description = typescript.displayPartsToString(prop.getDocumentationComment(checker)), parent = getParentType(typescript, prop), declarations = getAllDeclarationParents(typescript, prop), propName = prop.getName(), destructuringDefault = defaultsMap?.get(propName), jsDocDefault = getJSDocDefault(typescript, prop, checker), defaultStr = destructuringDefault ?? jsDocDefault;
16795
+ return {
16796
+ name: propName,
16797
+ required: isRequired,
16798
+ type,
16799
+ description,
16800
+ defaultValue: defaultStr !== void 0 ? { value: defaultStr } : null,
16801
+ parent,
16802
+ declarations
16803
+ };
16896
16804
  }
16897
- async function getParser5(userOptions) {
16898
- let [typescript, reactDocgenTypescript] = await Promise.all([
16899
- loadTypeScript(),
16900
- loadReactDocgenTypescript()
16901
- ]), optionsKey = JSON.stringify(userOptions ?? {});
16902
- if (parser && cachedParserOptionsKey !== optionsKey && (parser = void 0), !parser) {
16903
- let configPath = findTsconfigPath(process.cwd());
16904
- if (cachedCompilerOptions = { noErrorTruncation: !0, strict: !0 }, configPath) {
16905
- let { config } = typescript.readConfigFile(configPath, typescript.sys.readFile), parsed = typescript.parseJsonConfigFileContent(
16906
- config,
16907
- typescript.sys,
16908
- dirname7(configPath)
16909
- );
16910
- cachedCompilerOptions = { ...parsed.options, noErrorTruncation: !0 }, cachedFileNames = parsed.fileNames;
16911
- } else
16912
- logger6.warn(
16913
- "No tsconfig.json (or tsconfig.base.json / tsconfig.app.json) found. TypeScript component props will not be documented by react-docgen-typescript. Create a tsconfig.json in your project root to enable automatic controls."
16914
- );
16915
- let program = typescript.createProgram(
16916
- cachedFileNames ?? [],
16917
- cachedCompilerOptions,
16918
- void 0,
16919
- previousProgram
16920
- );
16921
- previousProgram = program;
16922
- let parserOptions = {
16923
- shouldExtractLiteralValuesFromEnum: !0,
16924
- shouldRemoveUndefinedFromOptional: !0,
16925
- ...userOptions,
16926
- // Always force savePropValueAsString so default values are in a consistent format
16927
- savePropValueAsString: !0
16928
- };
16929
- parser = {
16930
- program,
16931
- fileParser: reactDocgenTypescript.withCompilerOptions(cachedCompilerOptions, parserOptions)
16932
- }, cachedParserOptionsKey = optionsKey;
16805
+ function getBulkSourceExclusions(properties) {
16806
+ let propSourceCache = /* @__PURE__ */ new Map(), getSource = (prop) => {
16807
+ let cached2 = propSourceCache.get(prop);
16808
+ return cached2 === void 0 && !propSourceCache.has(prop) && (cached2 = getPropSourceFile(prop), propSourceCache.set(prop, cached2)), cached2;
16809
+ }, sourceCount = /* @__PURE__ */ new Map();
16810
+ for (let prop of properties) {
16811
+ let source = getSource(prop);
16812
+ source && (source.includes("node_modules") || source.endsWith(".d.ts")) && sourceCount.set(source, (sourceCount.get(source) ?? 0) + 1);
16933
16813
  }
16934
- return { ...parser, typescript };
16814
+ let bulkSources = new Set(
16815
+ [...sourceCount.entries()].filter(([, count]) => count > LARGE_SOURCE_THRESHOLD).map(([source]) => source)
16816
+ ), excluded = /* @__PURE__ */ new Set();
16817
+ for (let prop of properties) {
16818
+ let source = getSource(prop);
16819
+ source && bulkSources.has(source) && excluded.add(prop.getName());
16820
+ }
16821
+ return excluded;
16935
16822
  }
16936
- function matchComponentDoc(docs, {
16937
- importName,
16938
- localImportName,
16939
- componentName
16823
+ function computeDisplayName({
16824
+ exportSymbol,
16825
+ resolvedSymbol
16940
16826
  }) {
16941
- if (docs.length !== 0)
16942
- return docs.length === 1 ? docs[0] : docs.find(
16943
- (doc) => doc.exportName === importName || doc.exportName === localImportName || doc.displayName === importName || doc.displayName === localImportName || doc.displayName === componentName
16944
- );
16827
+ let resolvedName = resolvedSymbol.getName();
16828
+ if (!exportSymbol)
16829
+ return resolvedName && resolvedName !== "default" && resolvedName !== "__function" ? resolvedName : void 0;
16830
+ let exportName = exportSymbol.getName();
16831
+ return exportName === "default" ? resolvedName && resolvedName !== "default" && resolvedName !== "__function" ? resolvedName : void 0 : exportName;
16945
16832
  }
16946
- function getReactDocgenTypescriptError(path5, {
16947
- importName,
16948
- localImportName,
16949
- componentName
16950
- }, docs) {
16951
- return docs.length === 0 ? {
16952
- name: "react-docgen-typescript found no component docs",
16953
- message: [
16954
- `File: ${path5}`,
16955
- "react-docgen-typescript did not return any component docs for this file."
16956
- ].join(`
16957
- `)
16958
- } : {
16959
- name: "react-docgen-typescript could not match component docs",
16960
- message: [
16961
- `File: ${path5}`,
16962
- "react-docgen-typescript returned component docs for this file, but none matched the story's component import.",
16963
- `Looked for: componentName=${componentName}, localImportName=${localImportName ?? "<none>"}, importName=${importName ?? "<none>"}.`
16964
- ].join(`
16965
- `)
16966
- };
16833
+ function extractComponentJsDocTags(typescript, checker, symbol) {
16834
+ let tags = symbol.getJsDocTags(checker);
16835
+ if (tags.length === 0)
16836
+ return;
16837
+ let groupedTags = groupBy(tags, (tag) => tag.name);
16838
+ return Object.fromEntries(
16839
+ Object.entries(groupedTags).map(([name, grouped]) => [
16840
+ name,
16841
+ (grouped ?? []).map((tag) => typescript.displayPartsToString(tag.text ?? []).trim())
16842
+ ])
16843
+ );
16967
16844
  }
16968
- var parseWithReactDocgenTypescript = asyncCache(
16969
- async (filePath, userOptions) => {
16970
- let { program, fileParser, typescript } = await getParser5(userOptions), checker = program.getTypeChecker(), sourceFile = program.getSourceFile(filePath), docs = fileParser.parseWithProgramProvider(filePath, () => program), exportNameMap = sourceFile ? getExportNameMap(typescript, checker, sourceFile) : /* @__PURE__ */ new Map();
16971
- return docs.map((doc) => {
16972
- let largeNonUserSources = getLargeNonUserPropSources(doc.props);
16973
- return {
16974
- ...doc,
16975
- // Use name-based lookup: displayName is the resolved symbol name, so look it up in the
16976
- // export map to get the public export name. Falls back to displayName when not aliased.
16977
- exportName: exportNameMap.get(doc.displayName) ?? doc.displayName,
16978
- // Filter out bulk props from non-user sources (React built-ins, DOM, CSS-in-JS system props)
16979
- props: Object.fromEntries(
16980
- Object.entries(doc.props).filter(([, prop]) => {
16981
- let source = getPropSource(prop);
16982
- return !source || !largeNonUserSources.has(source);
16983
- })
16984
- )
16985
- };
16986
- });
16987
- },
16988
- { name: "parseWithReactDocgenTypescript" }
16989
- );
16990
-
16991
- // src/componentManifest/getComponentImports.ts
16992
- var baseIdentifier = (component) => component.split(".")[0] ?? component, isTypeSpecifier = (s) => t3.isImportSpecifier(s) && s.importKind === "type", importedName = (im) => t3.isIdentifier(im) ? im.name : im.value, addUniqueBy = (arr, item, eq2) => {
16993
- arr.find(eq2) || arr.push(item);
16994
- }, getComponents = async ({
16995
- csf,
16996
- storyFilePath,
16997
- typescriptOptions = {},
16998
- docgenEngine,
16999
- additionalComponentNames = []
17000
- }) => {
17001
- let { reactDocgenTypescriptOptions } = typescriptOptions, program = csf._file.path, componentSet = /* @__PURE__ */ new Set(), componentDepth = /* @__PURE__ */ new Map(), localToImport = /* @__PURE__ */ new Map(), jsxDepth = 0;
17002
- program.traverse({
17003
- JSXElement: {
17004
- enter() {
17005
- jsxDepth++;
17006
- },
17007
- exit() {
17008
- jsxDepth--;
17009
- }
17010
- },
17011
- JSXOpeningElement(p) {
17012
- let n = p.node.name, name;
17013
- if (t3.isJSXIdentifier(n))
17014
- name = n.name, name && /[A-Z]/.test(name.charAt(0)) && componentSet.add(name);
17015
- else if (t3.isJSXMemberExpression(n)) {
17016
- let jsxNameToString = (nm) => t3.isJSXIdentifier(nm) ? nm.name : `${jsxNameToString(nm.object)}.${jsxNameToString(nm.property)}`;
17017
- name = jsxNameToString(n), componentSet.add(name);
17018
- }
17019
- if (name) {
17020
- let depth = jsxDepth - 1, existing = componentDepth.get(name);
17021
- (existing === void 0 || depth < existing) && componentDepth.set(name, depth);
17022
- }
17023
- }
17024
- });
17025
- let metaComp = csf._meta?.component;
17026
- metaComp && componentSet.add(metaComp);
17027
- for (let componentName of additionalComponentNames)
17028
- componentSet.add(componentName);
17029
- let components = Array.from(componentSet).sort((a, b) => a.localeCompare(b)), body = program.get("body");
17030
- for (let stmt of body) {
17031
- if (!stmt.isImportDeclaration())
17032
- continue;
17033
- let decl = stmt.node;
17034
- if (decl.importKind === "type")
17035
- continue;
17036
- let specifiers = decl.specifiers ?? [];
17037
- if (specifiers.length !== 0)
17038
- for (let s of specifiers) {
17039
- if (!("local" in s) || !s.local || isTypeSpecifier(s))
17040
- continue;
17041
- let importId = decl.source.value;
17042
- if (t3.isImportDefaultSpecifier(s))
17043
- localToImport.set(s.local.name, { importId, importName: "default" });
17044
- else if (t3.isImportNamespaceSpecifier(s))
17045
- localToImport.set(s.local.name, { importId, importName: "*" });
17046
- else if (t3.isImportSpecifier(s)) {
17047
- let imported = importedName(s.imported);
17048
- localToImport.set(s.local.name, { importId, importName: imported });
16845
+ function serializeComponentDoc(typescript, checker, {
16846
+ sourceFile,
16847
+ resolvedComponent,
16848
+ defaultsSourcePath
16849
+ }) {
16850
+ let { componentRef, propsType, symbol } = resolvedComponent, exportName = componentRef.importName;
16851
+ if (!exportName)
16852
+ return;
16853
+ let displayNameOverride = componentRef.componentName, isMemberSelection = !!componentRef.member, filePath = componentRef.path ?? sourceFile.fileName, resolved = resolveAliasedSymbol(typescript, checker, symbol), contextNode = resolved.valueDeclaration ?? resolved.getDeclarations()?.[0];
16854
+ if (!contextNode)
16855
+ return;
16856
+ let moduleSymbol = checker.getSymbolAtLocation(sourceFile), exportSymbol = moduleSymbol ? checker.getExportsOfModule(moduleSymbol).find((candidate) => candidate.getName() === exportName) : void 0, allProperties, unionForceOptional;
16857
+ if (isUnionType(propsType)) {
16858
+ let seen = /* @__PURE__ */ new Map(), forceOptional = /* @__PURE__ */ new Set(), unionMembers = propsType.types, allMemberPropSets = [];
16859
+ for (let member of unionMembers) {
16860
+ let memberPropNames = /* @__PURE__ */ new Set();
16861
+ for (let prop of member.getApparentProperties()) {
16862
+ let name = prop.getName();
16863
+ memberPropNames.add(name);
16864
+ let propType = checker.getTypeOfSymbolAtLocation(prop, contextNode), isOptional = !!(prop.flags & typescript.SymbolFlags.Optional), isDegraded = !!(propType.getFlags() & typescript.TypeFlags.Never) || !!(propType.getFlags() & typescript.TypeFlags.Undefined);
16865
+ (isOptional || isDegraded) && forceOptional.add(name);
16866
+ let existing = seen.get(name);
16867
+ if (!existing)
16868
+ seen.set(name, prop);
16869
+ else if (!isDegraded) {
16870
+ let existingType = checker.getTypeOfSymbolAtLocation(existing, contextNode);
16871
+ (!!(existingType.getFlags() & typescript.TypeFlags.Never) || !!(existingType.getFlags() & typescript.TypeFlags.Undefined)) && seen.set(name, prop);
17049
16872
  }
17050
16873
  }
16874
+ allMemberPropSets.push(memberPropNames);
16875
+ }
16876
+ for (let name of seen.keys())
16877
+ allMemberPropSets.every((s) => s.has(name)) || forceOptional.add(name);
16878
+ allProperties = Array.from(seen.values()), unionForceOptional = forceOptional;
16879
+ } else
16880
+ allProperties = propsType.getApparentProperties();
16881
+ let excluded = getBulkSourceExclusions(allProperties), defaultsMap = extractDestructuringDefaults(typescript, resolved, checker);
16882
+ if (defaultsMap.size === 0 && defaultsSourcePath) {
16883
+ let fallbackDefaults = extractDefaultsFromSourceFile(typescript, defaultsSourcePath, {
16884
+ exportName,
16885
+ localName: resolved.getName(),
16886
+ preferLocalName: isMemberSelection
16887
+ });
16888
+ for (let [key, value] of fallbackDefaults)
16889
+ defaultsMap.set(key, value);
17051
16890
  }
17052
- let isLocallyDefinedWithoutImport = (base2) => {
17053
- let binding = program.scope.getBinding(base2);
17054
- return binding ? !!!(binding.path.isImportSpecifier?.() || binding.path.isImportDefaultSpecifier?.() || binding.path.isImportNamespaceSpecifier?.()) : !1;
17055
- }, filteredComponents = components.filter(
17056
- (c) => !isLocallyDefinedWithoutImport(baseIdentifier(c))
17057
- );
17058
- return (await Promise.all(
17059
- filteredComponents.map(async (c) => {
17060
- let depth = componentDepth.get(c), dot = c.indexOf("."), component = dot !== -1 ? (() => {
17061
- let ns = c.slice(0, dot), mem = c.slice(dot + 1), direct = localToImport.get(ns);
17062
- return direct ? direct.importName === "*" ? {
17063
- componentName: c,
17064
- localImportName: ns,
17065
- importId: direct.importId,
17066
- importName: mem,
17067
- namespace: ns,
17068
- member: mem,
17069
- jsxDepth: depth
17070
- } : {
17071
- componentName: c,
17072
- localImportName: ns,
17073
- importId: direct.importId,
17074
- importName: direct.importName,
17075
- member: mem,
17076
- jsxDepth: depth
17077
- } : { componentName: c, member: mem, jsxDepth: depth };
17078
- })() : (() => {
17079
- let direct = localToImport.get(c);
17080
- return direct ? {
17081
- componentName: c,
17082
- localImportName: c,
17083
- importId: direct.importId,
17084
- importName: direct.importName,
17085
- jsxDepth: depth
17086
- } : { componentName: c, jsxDepth: depth };
17087
- })(), path5, isPackage = !1;
17088
- try {
17089
- component.importId && storyFilePath && (path5 = cachedResolveImport(matchPath(component.importId, dirname8(storyFilePath)), {
17090
- basedir: dirname8(storyFilePath)
17091
- }));
17092
- } catch (e) {
17093
- logger7.debug(e);
17094
- }
17095
- try {
17096
- component.importId && !component.importId.startsWith(".") && storyFilePath && (cachedResolveImport(component.importId, { basedir: dirname8(storyFilePath) }), isPackage = !0);
17097
- } catch {
17098
- }
17099
- let componentWithPackage = { ...component, isPackage };
17100
- if (path5) {
17101
- if (docgenEngine === "react-docgen-typescript") {
17102
- let reactDocgenTypescript, reactDocgenTypescriptError;
17103
- try {
17104
- let docs = await parseWithReactDocgenTypescript(path5, reactDocgenTypescriptOptions);
17105
- reactDocgenTypescript = matchComponentDoc(docs, component), reactDocgenTypescript || (reactDocgenTypescriptError = getReactDocgenTypescriptError(path5, component, docs));
17106
- } catch (e) {
17107
- let message = e instanceof Error ? e.message : String(e);
17108
- logger7.debug(`react-docgen-typescript failed for ${path5}: ${message}`), reactDocgenTypescriptError = {
17109
- name: "react-docgen-typescript parse error",
17110
- message: `File: ${path5}
17111
- ${message}`
17112
- };
17113
- }
17114
- let importOverride = reactDocgenTypescript ? getImportTag(reactDocgenTypescript) : void 0;
17115
- return {
17116
- ...componentWithPackage,
17117
- path: path5,
17118
- ...reactDocgenTypescript ? { reactDocgenTypescript } : {},
17119
- ...reactDocgenTypescriptError ? { reactDocgenTypescriptError } : {},
17120
- importOverride
17121
- };
16891
+ let staticDefaults = extractStaticDefaultProps(typescript, checker, resolved);
16892
+ for (let [key, value] of staticDefaults)
16893
+ defaultsMap.has(key) || defaultsMap.set(key, value);
16894
+ let props = {};
16895
+ for (let prop of allProperties) {
16896
+ if (excluded.has(prop.getName()))
16897
+ continue;
16898
+ let item = extractPropItem(typescript, checker, prop, contextNode, defaultsMap);
16899
+ unionForceOptional?.has(prop.getName()) && (item.required = !1), props[prop.getName()] = item;
16900
+ }
16901
+ let displayName = (isMemberSelection ? displayNameOverride : void 0) ?? computeDisplayName({
16902
+ exportSymbol,
16903
+ resolvedSymbol: resolved
16904
+ }) ?? displayNameOverride, description = typescript.displayPartsToString(resolved.getDocumentationComment(checker)), selectedJsDocTags = extractComponentJsDocTags(typescript, checker, resolved), exportResolved = exportSymbol && exportSymbol !== resolved ? resolveAliasedSymbol(typescript, checker, exportSymbol) : void 0, exportJsDocTags = exportResolved ? extractComponentJsDocTags(typescript, checker, exportResolved) : void 0, jsDocTags = selectedJsDocTags?.import || !exportJsDocTags?.import ? selectedJsDocTags : {
16905
+ ...selectedJsDocTags ?? {},
16906
+ import: exportJsDocTags.import
16907
+ };
16908
+ return {
16909
+ displayName,
16910
+ exportName,
16911
+ filePath,
16912
+ description,
16913
+ jsDocTags,
16914
+ props
16915
+ };
16916
+ }
16917
+ function extractDefaultsFromSourceFile(typescript, filePath, {
16918
+ exportName,
16919
+ localName,
16920
+ preferLocalName = !1
16921
+ }) {
16922
+ let defaults = /* @__PURE__ */ new Map(), content = typescript.sys.readFile(filePath);
16923
+ if (!content)
16924
+ return defaults;
16925
+ let sf = typescript.createSourceFile(
16926
+ filePath,
16927
+ content,
16928
+ typescript.ScriptTarget.Latest,
16929
+ /* setParentNodes */
16930
+ !0
16931
+ ), varMap = /* @__PURE__ */ new Map();
16932
+ for (let stmt of sf.statements) {
16933
+ if (typescript.isVariableStatement(stmt))
16934
+ for (let decl of stmt.declarationList.declarations)
16935
+ typescript.isIdentifier(decl.name) && decl.initializer && varMap.set(decl.name.text, decl.initializer);
16936
+ typescript.isFunctionDeclaration(stmt) && stmt.name && varMap.set(stmt.name.text, stmt);
16937
+ }
16938
+ let fn = preferLocalName ? findLocalFunction(typescript, sf, localName, varMap) ?? findExportedFunction(typescript, sf, exportName, varMap) : findExportedFunction(typescript, sf, exportName, varMap) ?? findLocalFunction(typescript, sf, localName, varMap);
16939
+ if (!fn)
16940
+ return defaults;
16941
+ let firstParam = fn.parameters[0];
16942
+ if (!firstParam)
16943
+ return defaults;
16944
+ if (typescript.isObjectBindingPattern(firstParam.name))
16945
+ collectBindingDefaults(typescript, firstParam.name, defaults);
16946
+ else if (fn.body) {
16947
+ let propsParamName = typescript.isIdentifier(firstParam.name) ? firstParam.name : void 0, body = typescript.isBlock(fn.body) ? fn.body : void 0;
16948
+ if (body && propsParamName) {
16949
+ for (let stmt of body.statements)
16950
+ if (typescript.isVariableStatement(stmt))
16951
+ for (let varDecl of stmt.declarationList.declarations)
16952
+ typescript.isObjectBindingPattern(varDecl.name) && varDecl.initializer && isPropsDerivedInitializer(typescript, varDecl.initializer, propsParamName) && collectBindingDefaults(typescript, varDecl.name, defaults);
16953
+ }
16954
+ }
16955
+ return defaults;
16956
+ }
16957
+ function findLocalFunction(typescript, sf, localName, varMap) {
16958
+ if (!localName)
16959
+ return;
16960
+ let targetExpr = varMap.get(localName);
16961
+ if (targetExpr)
16962
+ return unwrapToFunctionAST(typescript, targetExpr, varMap, 0);
16963
+ }
16964
+ function findExportedFunction(typescript, sf, exportName, varMap) {
16965
+ let targetExpr;
16966
+ for (let stmt of sf.statements) {
16967
+ if (exportName === "default" && typescript.isExportAssignment(stmt) && !stmt.isExportEquals) {
16968
+ targetExpr = stmt.expression;
16969
+ break;
16970
+ }
16971
+ if (typescript.isVariableStatement(stmt) && hasExportModifier(typescript, stmt)) {
16972
+ for (let decl of stmt.declarationList.declarations)
16973
+ if (typescript.isIdentifier(decl.name) && decl.name.text === exportName && decl.initializer) {
16974
+ targetExpr = decl.initializer;
16975
+ break;
17122
16976
  }
17123
- if (docgenEngine === "react-docgen") {
17124
- let reactDocgen = getReactDocgen(path5, componentWithPackage);
17125
- return {
17126
- ...componentWithPackage,
17127
- path: path5,
17128
- reactDocgen,
17129
- importOverride: reactDocgen.type === "success" ? getImportTag(reactDocgen.data) : void 0
17130
- };
16977
+ if (targetExpr)
16978
+ break;
16979
+ }
16980
+ if (typescript.isFunctionDeclaration(stmt) && hasExportModifier(typescript, stmt) && stmt.name?.text === exportName)
16981
+ return findFunctionImpl(typescript, sf, stmt.name.text) ?? stmt;
16982
+ if (typescript.isExportDeclaration(stmt) && stmt.exportClause && typescript.isNamedExports(stmt.exportClause)) {
16983
+ for (let spec of stmt.exportClause.elements) {
16984
+ let exported = spec.name.text, local = spec.propertyName ? spec.propertyName.text : spec.name.text;
16985
+ if (exported === exportName) {
16986
+ targetExpr = varMap.get(local);
16987
+ break;
17131
16988
  }
17132
- if (docgenEngine === "react-component-meta")
17133
- return {
17134
- ...componentWithPackage,
17135
- path: path5
17136
- };
17137
16989
  }
17138
- return componentWithPackage;
17139
- })
17140
- )).sort((a, b) => a.componentName.localeCompare(b.componentName));
17141
- }, getImports = ({
17142
- components,
17143
- packageName
17144
- }) => {
17145
- let withSource = components.filter((c) => !!c.importId).map((c, idx) => {
17146
- let importId = c.importId, overrideSource = (() => {
17147
- if (c.importOverride)
17148
- try {
17149
- let src = babelParse2(c.importOverride).program.body.find((n) => t3.isImportDeclaration(n))?.source?.value;
17150
- return typeof src == "string" ? src : void 0;
17151
- } catch {
16990
+ if (targetExpr)
16991
+ break;
16992
+ }
16993
+ }
16994
+ if (targetExpr || (targetExpr = varMap.get(exportName)), !!targetExpr)
16995
+ return unwrapToFunctionAST(typescript, targetExpr, varMap, 0);
16996
+ }
16997
+ function unwrapToFunctionAST(typescript, node, varMap, depth) {
16998
+ if (!(depth > MAX_UNWRAP_DEPTH)) {
16999
+ if (typescript.isFunctionExpression(node) || typescript.isArrowFunction(node) || typescript.isFunctionDeclaration(node))
17000
+ return node;
17001
+ if (typescript.isParenthesizedExpression(node) || typescript.isAsExpression(node) || typescript.isTypeAssertionExpression && typescript.isTypeAssertionExpression(node))
17002
+ return unwrapToFunctionAST(typescript, node.expression, varMap, depth + 1);
17003
+ if (typescript.isCallExpression(node)) {
17004
+ let callee = node.expression;
17005
+ if (typescript.isPropertyAccessExpression(callee) && typescript.isIdentifier(callee.expression) && callee.expression.text === "Object" && callee.name.text === "assign" && node.arguments.length >= 1 || node.arguments.length >= 1)
17006
+ return unwrapToFunctionAST(typescript, node.arguments[0], varMap, depth + 1);
17007
+ }
17008
+ if (typescript.isIdentifier(node)) {
17009
+ let init = varMap.get(node.text);
17010
+ if (init)
17011
+ return unwrapToFunctionAST(typescript, init, varMap, depth + 1);
17012
+ }
17013
+ }
17014
+ }
17015
+ function findFunctionImpl(typescript, sf, name) {
17016
+ for (let stmt of sf.statements)
17017
+ if (typescript.isFunctionDeclaration(stmt) && stmt.name?.text === name && stmt.body)
17018
+ return stmt;
17019
+ }
17020
+ function hasExportModifier(typescript, node) {
17021
+ return typescript.canHaveModifiers(node) && typescript.getModifiers(node)?.some((m) => m.kind === typescript.SyntaxKind.ExportKeyword) === !0;
17022
+ }
17023
+
17024
+ // src/componentManifest/componentMeta/ComponentMetaProject.ts
17025
+ var ComponentMetaProject = class {
17026
+ constructor(typescript, commandLine, configFileName, fsFileSnapshots = /* @__PURE__ */ new Map(), getCommandLineFn) {
17027
+ this.typescript = typescript;
17028
+ this.commandLine = commandLine;
17029
+ this.configFileName = configFileName;
17030
+ this.fsFileSnapshots = fsFileSnapshots;
17031
+ this.getCommandLineFn = getCommandLineFn;
17032
+ this.projectVersion = 0;
17033
+ this.shouldCheckRootFiles = !1;
17034
+ /** Entries to extract — set by the generator, replayed during warmup for targeted type resolution. */
17035
+ this.entries = [];
17036
+ let language = (0, import_language_core.createLanguage)(
17037
+ [{ getLanguageId: (fileName) => (0, import_typescript.resolveFileLanguageId)(fileName) }],
17038
+ new import_language_core.FileMap(typescript.sys.useCaseSensitiveFileNames),
17039
+ (fileName, includeFsFiles) => {
17040
+ if (!includeFsFiles)
17152
17041
  return;
17153
- }
17154
- })(), rewritten = overrideSource !== void 0 ? overrideSource : (
17155
- // only rewrite to the package name it the import id is not already a valid package
17156
- // tsconfig paths such as ~/components/Button and components/Button are not seen as packages
17157
- packageName && !c.isPackage ? packageName : importId
17042
+ let cache = fsFileSnapshots.get(fileName), modifiedTime = typescript.sys.getModifiedTime?.(fileName)?.valueOf();
17043
+ if (!cache || cache[0] !== modifiedTime)
17044
+ if (typescript.sys.fileExists(fileName)) {
17045
+ let text = typescript.sys.readFile(fileName), snapshot2 = text !== void 0 ? typescript.ScriptSnapshot.fromString(text) : void 0;
17046
+ fsFileSnapshots.set(fileName, [modifiedTime, snapshot2]);
17047
+ } else
17048
+ fsFileSnapshots.set(fileName, [modifiedTime, void 0]);
17049
+ let snapshot = fsFileSnapshots.get(fileName)?.[1];
17050
+ snapshot ? language.scripts.set(fileName, snapshot) : language.scripts.delete(fileName);
17051
+ }
17052
+ ), projectHost = {
17053
+ getCurrentDirectory: () => configFileName ? path2.dirname(configFileName) : commandLine.options.rootDir ?? process.cwd(),
17054
+ getCompilationSettings: () => this.commandLine.options,
17055
+ getProjectReferences: () => this.commandLine.projectReferences,
17056
+ getProjectVersion: () => (this.checkRootFilesUpdate(), this.projectVersion.toString()),
17057
+ getScriptFileNames: () => (this.checkRootFilesUpdate(), this.commandLine.fileNames)
17058
+ }, { languageServiceHost } = (0, import_typescript.createLanguageServiceHost)(
17059
+ typescript,
17060
+ typescript.sys,
17061
+ language,
17062
+ (s) => s,
17063
+ // asScriptId — identity for React (no URI mapping needed)
17064
+ projectHost
17065
+ );
17066
+ this.ls = typescript.createLanguageService(languageServiceHost);
17067
+ }
17068
+ getCommandLine() {
17069
+ return this.commandLine;
17070
+ }
17071
+ dispose() {
17072
+ clearTimeout(this.warmupTimer), this.ls.dispose();
17073
+ }
17074
+ // ---------------------------------------------------------------------------
17075
+ // Project management
17076
+ // ---------------------------------------------------------------------------
17077
+ /**
17078
+ * Batch-add multiple files to the project in one go. Only bumps projectVersion once, avoiding
17079
+ * repeated program rebuilds.
17080
+ */
17081
+ ensureFiles(fileNames) {
17082
+ let added = !1;
17083
+ for (let fileName of fileNames)
17084
+ this.commandLine.fileNames.includes(fileName) || (this.commandLine.fileNames.push(fileName), added = !0);
17085
+ added && this.projectVersion++;
17086
+ }
17087
+ /**
17088
+ * Adapted from:
17089
+ * https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/kit/lib/createChecker.ts#L436-L447
17090
+ */
17091
+ checkRootFilesUpdate() {
17092
+ if (!this.shouldCheckRootFiles || (this.shouldCheckRootFiles = !1, !this.getCommandLineFn))
17093
+ return;
17094
+ let newCommandLine = this.getCommandLineFn();
17095
+ arrayItemsEqual(newCommandLine.fileNames, this.commandLine.fileNames) || (this.commandLine.fileNames = newCommandLine.fileNames, this.projectVersion++);
17096
+ }
17097
+ hasSourceFile(fileName) {
17098
+ return !!this.ls.getProgram()?.getSourceFile(fileName);
17099
+ }
17100
+ /**
17101
+ * Get all non-node_modules source file paths from the TS program. Used by ComponentMetaManager to
17102
+ * watch directories for file changes.
17103
+ */
17104
+ getSourceFilePaths() {
17105
+ let program = this.ls.getProgram();
17106
+ return program ? program.getSourceFiles().map((sf) => sf.fileName.replace(/\\/g, "/")).filter((f) => !f.includes("node_modules")) : [];
17107
+ }
17108
+ /**
17109
+ * Adapted from:
17110
+ * https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/kit/lib/createChecker.ts#L409-L432
17111
+ *
17112
+ * Created events only set shouldCheckRootFiles (version bump happens in checkRootFilesUpdate if
17113
+ * the file list actually changed). Deleted/created break early since they trigger a full config
17114
+ * reparse — processing remaining changes is unnecessary.
17115
+ */
17116
+ onFilesChanged(changes) {
17117
+ for (let { filePath } of changes)
17118
+ this.fsFileSnapshots.delete(filePath);
17119
+ let oldVersion = this.projectVersion, program = this.ls.getProgram();
17120
+ for (let { filePath, type } of changes)
17121
+ if (type === "changed")
17122
+ program?.getSourceFile(filePath) && this.projectVersion++;
17123
+ else if (type === "deleted") {
17124
+ program?.getSourceFile(filePath) && this.projectVersion++, this.shouldCheckRootFiles = !0;
17125
+ break;
17126
+ } else if (type === "created") {
17127
+ this.shouldCheckRootFiles = !0;
17128
+ break;
17129
+ }
17130
+ this.projectVersion !== oldVersion && this.entries.length > 0 && (clearTimeout(this.warmupTimer), this.warmupTimer = setTimeout(() => {
17131
+ try {
17132
+ this.extractPropsFromStories(this.entries);
17133
+ } catch {
17134
+ }
17135
+ }, 100), this.warmupTimer?.unref?.());
17136
+ }
17137
+ // ---------------------------------------------------------------------------
17138
+ // Primary extraction method — probe-free
17139
+ // ---------------------------------------------------------------------------
17140
+ extractPropsFromStories(entries) {
17141
+ this.entries = entries;
17142
+ let allFiles = entries.flatMap(
17143
+ (entry) => entry.component?.path ? [entry.storyPath, entry.component.path] : [entry.storyPath]
17158
17144
  );
17159
- return { c, src: t3.stringLiteral(rewritten), key: rewritten, ord: idx };
17160
- }), orderOfSource = {};
17161
- for (let w of withSource)
17162
- orderOfSource[w.key] === void 0 && (orderOfSource[w.key] = w.ord);
17163
- let buckets = /* @__PURE__ */ new Map(), ensureBucket = (key, src) => {
17164
- let prev = buckets.get(key);
17165
- if (prev)
17166
- return prev;
17167
- let b = {
17168
- source: src,
17169
- defaults: [],
17170
- namespaces: [],
17171
- named: [],
17172
- order: orderOfSource[key] ?? 0
17173
- };
17174
- return buckets.set(key, b), b;
17175
- };
17176
- for (let { c, src, key } of withSource) {
17177
- let b = ensureBucket(key, src), rewritten = src.value !== c.importId, overrideSpec = (() => {
17178
- if (c.importOverride)
17179
- try {
17180
- let decl = babelParse2(c.importOverride).program.body.find((n) => t3.isImportDeclaration(n));
17181
- if (!decl)
17182
- return;
17183
- let spec = (decl.specifiers ?? []).find((s) => !isTypeSpecifier(s));
17184
- return spec ? t3.isImportNamespaceSpecifier(spec) ? { kind: "namespace", local: spec.local.name } : t3.isImportDefaultSpecifier(spec) ? { kind: "default" } : t3.isImportSpecifier(spec) ? { kind: "named", imported: t3.isIdentifier(spec.imported) ? spec.imported.name : spec.imported.value } : void 0 : void 0;
17185
- } catch {
17186
- return;
17145
+ this.ensureFiles(allFiles), this.ensureFresh(allFiles);
17146
+ let program = this.ls.getProgram();
17147
+ if (!program)
17148
+ return;
17149
+ let checker = program.getTypeChecker(), serializationContextByComponentPath = /* @__PURE__ */ new Map();
17150
+ for (let entry of entries)
17151
+ try {
17152
+ let storySourceFile = program.getSourceFile(entry.storyPath), entryComponent = entry.component, componentPath = entryComponent?.path, exportName = entryComponent?.importName;
17153
+ if (!storySourceFile || !componentPath || !exportName || !entryComponent)
17154
+ continue;
17155
+ let importId = entryComponent.importId, isPackageImport = importId && !importId.startsWith("."), componentSourceFile;
17156
+ if (isPackageImport) {
17157
+ let resolved = this.typescript.resolveModuleName(
17158
+ importId,
17159
+ entry.storyPath,
17160
+ this.commandLine.options,
17161
+ this.typescript.sys
17162
+ );
17163
+ componentSourceFile = resolved.resolvedModule ? program.getSourceFile(resolved.resolvedModule.resolvedFileName) : program.getSourceFile(componentPath);
17164
+ } else
17165
+ componentSourceFile = program.getSourceFile(componentPath);
17166
+ if (!componentSourceFile)
17167
+ continue;
17168
+ let resolvedComponent;
17169
+ if (importId && (resolvedComponent = resolvePropsFromStoryFile(
17170
+ this.typescript,
17171
+ checker,
17172
+ storySourceFile,
17173
+ entryComponent
17174
+ )), resolvedComponent || (resolvedComponent = this.resolveFromMetaComponent(
17175
+ checker,
17176
+ storySourceFile,
17177
+ entryComponent
17178
+ )), !resolvedComponent)
17179
+ continue;
17180
+ let serializationContext = serializationContextByComponentPath.get(componentPath);
17181
+ if (serializationContext === void 0) {
17182
+ let resolvedFileName = componentSourceFile.fileName;
17183
+ serializationContext = {
17184
+ sourceFile: componentSourceFile,
17185
+ defaultsSourcePath: resolvedFileName.endsWith(".d.ts") || resolvedFileName.endsWith(".d.mts") || resolvedFileName.endsWith(".d.cts") ? componentPath : void 0
17186
+ }, serializationContextByComponentPath.set(componentPath, serializationContext);
17187
17187
  }
17188
- })();
17189
- if (overrideSpec) {
17190
- if (overrideSpec.kind === "namespace") {
17191
- let ns = t3.identifier(overrideSpec.local);
17192
- addUniqueBy(b.namespaces, ns, (n) => n.name === ns.name);
17193
- continue;
17194
- }
17195
- if (!c.localImportName)
17196
- continue;
17197
- if (overrideSpec.kind === "default") {
17198
- let id = t3.identifier(c.localImportName);
17199
- addUniqueBy(b.defaults, id, (d) => d.name === id.name);
17188
+ let doc = serializeComponentDoc(this.typescript, checker, {
17189
+ sourceFile: serializationContext.sourceFile,
17190
+ resolvedComponent,
17191
+ defaultsSourcePath: serializationContext.defaultsSourcePath
17192
+ });
17193
+ doc && (entryComponent.reactComponentMeta = doc, entryComponent.componentJsDocTags = doc.jsDocTags, entryComponent.importOverride = entryComponent.componentJsDocTags?.import?.[0]?.trim());
17194
+ } catch {
17200
17195
  continue;
17201
17196
  }
17202
- if (overrideSpec.kind === "named") {
17203
- let local = t3.identifier(c.localImportName), imported = t3.identifier(overrideSpec.imported);
17204
- addUniqueBy(
17205
- b.named,
17206
- t3.importSpecifier(local, imported),
17207
- (n) => n.local.name === local.name && importedName(n.imported) === imported.name
17208
- );
17197
+ }
17198
+ /**
17199
+ * Check mtime for specific files and bump projectVersion if any changed.
17200
+ *
17201
+ * This bypasses the sync() gate in createLanguageServiceHost — sync() only runs when
17202
+ * projectVersion changes, so mtime-based cache alone can't detect stale files. We do a targeted
17203
+ * mtime check for the files we're about to extract from, ensuring freshness even when the
17204
+ * fs.watch event hasn't arrived yet (race with HMR) or was missed entirely.
17205
+ */
17206
+ ensureFresh(fileNames) {
17207
+ let stale = !1;
17208
+ for (let fileName of fileNames) {
17209
+ let cache = this.fsFileSnapshots.get(fileName);
17210
+ if (!cache)
17209
17211
  continue;
17210
- }
17212
+ let currentMtime = this.typescript.sys.getModifiedTime?.(fileName)?.valueOf();
17213
+ cache[0] !== currentMtime && (this.fsFileSnapshots.delete(fileName), stale = !0);
17211
17214
  }
17212
- if (c.namespace) {
17213
- if (rewritten) {
17214
- if (!c.importName)
17215
- continue;
17216
- let member = c.importName, id = t3.identifier(member);
17217
- addUniqueBy(
17218
- b.named,
17219
- t3.importSpecifier(id, id),
17220
- (n) => n.local.name === member && importedName(n.imported) === member
17221
- );
17222
- } else {
17223
- let ns = t3.identifier(c.namespace);
17224
- addUniqueBy(b.namespaces, ns, (n) => n.name === ns.name);
17225
- }
17226
- continue;
17215
+ stale && this.projectVersion++;
17216
+ }
17217
+ // ---------------------------------------------------------------------------
17218
+ // Internal helpers
17219
+ // ---------------------------------------------------------------------------
17220
+ /**
17221
+ * Path 2 fallback: resolve the component type from the story file's `meta.component` property.
17222
+ * Only works when the user explicitly set `component:` in the meta — no node means no
17223
+ * extraction.
17224
+ */
17225
+ resolveFromMetaComponent(checker, storySourceFile, componentRef) {
17226
+ let { member: memberAccess } = componentRef, moduleSymbol = checker.getSymbolAtLocation(storySourceFile);
17227
+ if (!moduleSymbol)
17228
+ return;
17229
+ let defaultExport = checker.getExportsOfModule(moduleSymbol).find((e) => e.getName() === "default");
17230
+ if (!defaultExport)
17231
+ return;
17232
+ let componentProp = checker.getTypeOfSymbol(defaultExport).getProperty("component");
17233
+ if (!componentProp)
17234
+ return;
17235
+ let componentType = checker.getTypeOfSymbol(componentProp), selectedSymbol = componentProp.valueDeclaration && this.typescript.isPropertyAssignment(componentProp.valueDeclaration) ? checker.getSymbolAtLocation(componentProp.valueDeclaration.initializer) : componentType.getSymbol?.();
17236
+ if (memberAccess) {
17237
+ let prop = componentType.getProperty(memberAccess);
17238
+ if (prop)
17239
+ componentType = checker.getTypeOfSymbol(prop), selectedSymbol = prop;
17240
+ else
17241
+ return;
17227
17242
  }
17228
- if (c.importName === "default") {
17229
- if (!c.localImportName)
17230
- continue;
17231
- if (rewritten) {
17232
- let id = t3.identifier(c.localImportName);
17233
- addUniqueBy(
17234
- b.named,
17235
- t3.importSpecifier(id, id),
17236
- (n) => n.local.name === id.name && importedName(n.imported) === id.name
17237
- );
17238
- } else {
17239
- let id = t3.identifier(c.localImportName);
17240
- addUniqueBy(b.defaults, id, (d) => d.name === id.name);
17243
+ let propsType = resolvePropsFromComponentType(this.typescript, checker, componentType);
17244
+ if (!(!propsType || !selectedSymbol))
17245
+ return {
17246
+ componentRef,
17247
+ propsType,
17248
+ symbol: selectedSymbol
17249
+ };
17250
+ }
17251
+ };
17252
+ function arrayItemsEqual(a, b) {
17253
+ if (a.length !== b.length)
17254
+ return !1;
17255
+ let set = new Set(a);
17256
+ for (let file of b)
17257
+ if (!set.has(file))
17258
+ return !1;
17259
+ return !0;
17260
+ }
17261
+
17262
+ // src/componentManifest/componentMeta/ComponentMetaManager.ts
17263
+ var rootTsConfigNames = ["tsconfig.json", "jsconfig.json"], DEFAULT_INFERRED_OPTIONS = {
17264
+ strict: !0,
17265
+ esModuleInterop: !0,
17266
+ allowJs: !0,
17267
+ skipLibCheck: !0
17268
+ }, ComponentMetaManager = class {
17269
+ constructor(typescript) {
17270
+ this.typescript = typescript;
17271
+ // Adapted from:
17272
+ // https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/language-server/lib/project/typescriptProject.ts#L34-L37
17273
+ this.configProjects = /* @__PURE__ */ new Map();
17274
+ this.rootTsConfigs = /* @__PURE__ */ new Set();
17275
+ this.searchedDirs = /* @__PURE__ */ new Set();
17276
+ // Our own file watching layer
17277
+ this.watching = !1;
17278
+ this.watchersByDir = /* @__PURE__ */ new Map();
17279
+ this.pendingEvents = /* @__PURE__ */ new Map();
17280
+ // Adapted from:
17281
+ // https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/kit/lib/createChecker.ts#L83
17282
+ this.fsFileSnapshots = /* @__PURE__ */ new Map();
17283
+ }
17284
+ // ---------------------------------------------------------------------------
17285
+ // Adapted from:
17286
+ // https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/language-server/lib/project/typescriptProject.ts#L70-L79
17287
+ // ---------------------------------------------------------------------------
17288
+ getProjectForFile(fileName) {
17289
+ let tsconfig = this.findMatchTSConfig(fileName);
17290
+ return tsconfig ? this.getOrCreateConfiguredProject(tsconfig) ?? this.getOrCreateInferredProject(fileName) : this.getOrCreateInferredProject(fileName);
17291
+ }
17292
+ /**
17293
+ * Batch-extract component props across all entries, grouping by tsconfig project so each project
17294
+ * builds its TS program only once.
17295
+ */
17296
+ batchExtract(entries) {
17297
+ let extractableEntries = entries.filter(
17298
+ (storyRef) => storyRef.component?.path && storyRef.component.importName
17299
+ ), byProject = groupByToMap(
17300
+ extractableEntries,
17301
+ (storyRef) => this.getProjectForFile(storyRef.storyPath)
17302
+ );
17303
+ for (let [project, projectEntries] of byProject)
17304
+ try {
17305
+ project.extractPropsFromStories(projectEntries);
17306
+ } catch (err) {
17307
+ logger7.debug(`[reactComponentMeta] Batch extraction failed: ${err}`);
17241
17308
  }
17242
- continue;
17243
- }
17244
- if (c.importName) {
17245
- if (!c.localImportName)
17246
- continue;
17247
- let local = t3.identifier(c.localImportName), imported = t3.identifier(c.importName);
17248
- addUniqueBy(
17249
- b.named,
17250
- t3.importSpecifier(local, imported),
17251
- (n) => n.local.name === local.name && importedName(n.imported) === imported.name
17252
- );
17253
- continue;
17309
+ }
17310
+ // ---------------------------------------------------------------------------
17311
+ // Adapted from:
17312
+ // https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/language-server/lib/project/typescriptProject.ts#L101-L234
17313
+ // ---------------------------------------------------------------------------
17314
+ findMatchTSConfig(filePath) {
17315
+ let fileName = filePath.replace(/\\/g, "/"), dir = path3.dirname(fileName);
17316
+ for (; !this.searchedDirs.has(dir); ) {
17317
+ this.searchedDirs.add(dir);
17318
+ for (let tsConfigName of rootTsConfigNames) {
17319
+ let tsconfigPath = path3.join(dir, tsConfigName).replace(/\\/g, "/");
17320
+ this.typescript.sys.fileExists(tsconfigPath) && this.rootTsConfigs.add(tsconfigPath);
17321
+ }
17322
+ let parent = path3.dirname(dir);
17323
+ if (parent === dir)
17324
+ break;
17325
+ dir = parent;
17254
17326
  }
17255
- }
17256
- let merged = [], printDecl = (specs, src) => {
17257
- let node = t3.importDeclaration(specs, src), code = recast.print(node, {}).code;
17258
- merged.push(code);
17259
- }, sortedBuckets = Array.from(buckets.values()).sort((a, b) => a.order - b.order);
17260
- for (let bucket of sortedBuckets) {
17261
- let { source, defaults, namespaces, named } = bucket;
17262
- if (!(defaults.length === 0 && namespaces.length === 0 && named.length === 0))
17263
- if (namespaces.length > 0) {
17264
- let firstSpecs = [];
17265
- defaults[0] && firstSpecs.push(t3.importDefaultSpecifier(defaults[0])), firstSpecs.push(t3.importNamespaceSpecifier(namespaces[0])), printDecl(firstSpecs, source), named.length > 0 && printDecl(named, source);
17266
- for (let d of defaults.slice(1))
17267
- printDecl([t3.importDefaultSpecifier(d)], source);
17268
- for (let ns of namespaces.slice(1))
17269
- printDecl([t3.importNamespaceSpecifier(ns)], source);
17270
- } else {
17271
- if (defaults.length > 0 || named.length > 0) {
17272
- let specs = [];
17273
- defaults[0] && specs.push(t3.importDefaultSpecifier(defaults[0])), specs.push(...named), printDecl(specs, source);
17327
+ if (this.rootTsConfigs.size === 0)
17328
+ return null;
17329
+ let prepareClosestRootCommandLine = () => {
17330
+ let matches = [];
17331
+ for (let rootTsConfig of this.rootTsConfigs)
17332
+ isFileInDir(fileName, path3.dirname(rootTsConfig)) && matches.push(rootTsConfig);
17333
+ matches = matches.sort((a, b) => sortTSConfigs(fileName, a, b)), matches.length && getCommandLine(matches[0]);
17334
+ }, findIndirectReferenceTsconfig = () => findTSConfig((tsconfig) => !!this.configProjects.get(tsconfig)?.hasSourceFile(fileName)), findDirectIncludeTsconfig = () => findTSConfig((tsconfig) => {
17335
+ let commandLine = getCommandLine(tsconfig);
17336
+ return new Set(commandLine?.fileNames ?? []).has(fileName);
17337
+ }), findTSConfig = (match) => {
17338
+ let checked = /* @__PURE__ */ new Set();
17339
+ for (let rootTsConfig of [...this.rootTsConfigs].sort(
17340
+ (a, b) => sortTSConfigs(fileName, a, b)
17341
+ )) {
17342
+ let project = this.configProjects.get(rootTsConfig);
17343
+ if (project) {
17344
+ let chains = getReferencesChains(project.getCommandLine(), rootTsConfig, []);
17345
+ chains = chains.reverse();
17346
+ for (let chain of chains)
17347
+ for (let i = chain.length - 1; i >= 0; i--) {
17348
+ let tsconfig = chain[i];
17349
+ if (!checked.has(tsconfig) && (checked.add(tsconfig), match(tsconfig)))
17350
+ return tsconfig;
17351
+ }
17274
17352
  }
17275
- for (let d of defaults.slice(1))
17276
- printDecl([t3.importDefaultSpecifier(d)], source);
17277
17353
  }
17354
+ return null;
17355
+ }, getReferencesChains = (commandLine, tsConfig, before) => {
17356
+ if (commandLine.projectReferences?.length) {
17357
+ let newChains = [];
17358
+ for (let projectReference of commandLine.projectReferences) {
17359
+ let tsConfigPath = projectReference.path.replace(/\\/g, "/");
17360
+ if (this.typescript.sys.directoryExists(tsConfigPath)) {
17361
+ let newTsConfigPath = path3.join(tsConfigPath, "tsconfig.json"), newJsConfigPath = path3.join(tsConfigPath, "jsconfig.json");
17362
+ this.typescript.sys.fileExists(newTsConfigPath) ? tsConfigPath = newTsConfigPath : this.typescript.sys.fileExists(newJsConfigPath) && (tsConfigPath = newJsConfigPath);
17363
+ }
17364
+ let beforeIndex = before.indexOf(tsConfigPath);
17365
+ if (beforeIndex >= 0)
17366
+ newChains.push(before.slice(0, Math.max(beforeIndex, 1)));
17367
+ else {
17368
+ let referenceCommandLine = getCommandLine(tsConfigPath);
17369
+ if (referenceCommandLine)
17370
+ for (let chain of getReferencesChains(referenceCommandLine, tsConfigPath, [
17371
+ ...before,
17372
+ tsConfig
17373
+ ]))
17374
+ newChains.push(chain);
17375
+ }
17376
+ }
17377
+ return newChains;
17378
+ } else
17379
+ return [[...before, tsConfig]];
17380
+ }, getCommandLine = (tsConfig) => this.getOrCreateConfiguredProject(tsConfig)?.getCommandLine();
17381
+ return prepareClosestRootCommandLine(), findDirectIncludeTsconfig() ?? findIndirectReferenceTsconfig();
17382
+ }
17383
+ // ---------------------------------------------------------------------------
17384
+ // Adapted from:
17385
+ // https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/language-server/lib/project/typescriptProject.ts#L236-L256
17386
+ // ---------------------------------------------------------------------------
17387
+ getOrCreateConfiguredProject(tsconfig) {
17388
+ tsconfig = tsconfig.replace(/\\/g, "/");
17389
+ let project = this.configProjects.get(tsconfig);
17390
+ if (!project)
17391
+ try {
17392
+ let getCommandLine = () => this.parseConfigWorker(tsconfig);
17393
+ project = new ComponentMetaProject(
17394
+ this.typescript,
17395
+ getCommandLine(),
17396
+ tsconfig,
17397
+ this.fsFileSnapshots,
17398
+ getCommandLine
17399
+ ), this.configProjects.set(tsconfig, project), this.watching && (this.watchDirectory(path3.dirname(tsconfig)), this.watchProgramSourceDirs(project));
17400
+ } catch (err) {
17401
+ return logger7.debug(`[reactComponentMeta] Failed to parse tsconfig ${tsconfig}: ${err}`), null;
17402
+ }
17403
+ return project;
17278
17404
  }
17279
- return merged;
17280
- };
17281
-
17282
- // src/componentManifest/subcomponents.ts
17283
- import { types as t4 } from "storybook/internal/babel";
17284
- function findExactComponentMatch(components, componentName) {
17285
- if (componentName)
17286
- return components.find((component) => component.componentName === componentName);
17287
- }
17288
- function extractDeclaredSubcomponents(csf) {
17289
- let rawSubcomponents = unwrapSubcomponentNode(
17290
- csf._metaAnnotations.subcomponents,
17291
- csf._ast.program
17292
- );
17293
- return !rawSubcomponents || !t4.isObjectExpression(rawSubcomponents) ? [] : rawSubcomponents.properties.flatMap((property) => {
17294
- if (!t4.isObjectProperty(property))
17295
- return [];
17296
- let name = getObjectKeyName(property.key), directComponentName = getComponentExpressionName(property.value), componentExpression = unwrapSubcomponentNode(property.value, csf._ast.program), componentName = getComponentExpressionName(componentExpression) ?? directComponentName;
17297
- return name && componentName ? [{ name, componentName }] : [];
17298
- });
17299
- }
17300
- function findVariableInitialization(identifier, program) {
17301
- for (let node of program.body) {
17302
- let declaration = (t4.isVariableDeclaration(node) ? node.declarations : t4.isExportNamedDeclaration(node) && t4.isVariableDeclaration(node.declaration) ? node.declaration.declarations : void 0)?.find(
17303
- (decl) => t4.isVariableDeclarator(decl) && t4.isIdentifier(decl.id) && decl.id.name === identifier
17405
+ // ---------------------------------------------------------------------------
17406
+ // Adapted from:
17407
+ // https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/language-server/lib/project/typescriptProject.ts#L258-L284
17408
+ // ---------------------------------------------------------------------------
17409
+ getOrCreateInferredProject(fileName) {
17410
+ return this.inferredProject || (this.inferredProject = new ComponentMetaProject(
17411
+ this.typescript,
17412
+ {
17413
+ options: {
17414
+ ...DEFAULT_INFERRED_OPTIONS,
17415
+ target: this.typescript.ScriptTarget.Latest,
17416
+ module: this.typescript.ModuleKind.ESNext,
17417
+ moduleResolution: this.typescript.ModuleResolutionKind.Bundler,
17418
+ jsx: this.typescript.JsxEmit.ReactJSX
17419
+ },
17420
+ fileNames: [],
17421
+ errors: []
17422
+ },
17423
+ void 0,
17424
+ this.fsFileSnapshots
17425
+ )), this.inferredProject.ensureFiles([fileName]), this.inferredProject;
17426
+ }
17427
+ // ---------------------------------------------------------------------------
17428
+ // Adapted from:
17429
+ // https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/language-server/lib/project/typescriptProjectLs.ts#L262-L353
17430
+ // ---------------------------------------------------------------------------
17431
+ parseConfigWorker(tsconfig) {
17432
+ let config = this.typescript.readJsonConfigFile(tsconfig, this.typescript.sys.readFile), content = this.typescript.parseJsonSourceFileConfigFileContent(
17433
+ config,
17434
+ this.typescript.sys,
17435
+ path3.dirname(tsconfig),
17436
+ {},
17437
+ tsconfig
17304
17438
  );
17305
- if (declaration?.init && t4.isExpression(declaration.init))
17306
- return declaration.init;
17439
+ return content.options.outDir = void 0, content.fileNames = content.fileNames.map((fileName) => fileName.replace(/\\/g, "/")), content;
17307
17440
  }
17308
- }
17309
- function unwrapSubcomponentNode(node, program, visitedIdentifiers = /* @__PURE__ */ new Set()) {
17310
- let current2 = node;
17311
- for (; current2; ) {
17312
- if (t4.isIdentifier(current2)) {
17313
- if (visitedIdentifiers.has(current2.name))
17314
- return;
17315
- visitedIdentifiers.add(current2.name), current2 = findVariableInitialization(current2.name, program);
17316
- continue;
17441
+ // ---------------------------------------------------------------------------
17442
+ // File events
17443
+ // ---------------------------------------------------------------------------
17444
+ /**
17445
+ * Broadcast file changes to all projects. Each project selectively bumps projectVersion.
17446
+ *
17447
+ * Adapted from:
17448
+ * https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/kit/lib/createChecker.ts#L409-L432
17449
+ */
17450
+ onFilesChanged(changes) {
17451
+ for (let project of this.configProjects.values())
17452
+ project.onFilesChanged(changes);
17453
+ this.inferredProject?.onFilesChanged(changes);
17454
+ }
17455
+ /**
17456
+ * Adapted from:
17457
+ * https://github.com/volarjs/volar.js/blob/882cd56d46a13d272f34e451f495d3d62251969a/packages/language-server/lib/project/typescriptProject.ts#L43-L68
17458
+ */
17459
+ onConfigChanged(configPath, type) {
17460
+ if (configPath = configPath.replace(/\\/g, "/"), type === "created")
17461
+ this.rootTsConfigs.add(configPath);
17462
+ else if ((type === "changed" || type === "deleted") && this.configProjects.has(configPath)) {
17463
+ type === "deleted" && this.rootTsConfigs.delete(configPath);
17464
+ let project = this.configProjects.get(configPath);
17465
+ this.configProjects.delete(configPath), project?.dispose();
17317
17466
  }
17318
- if (t4.isParenthesizedExpression(current2) || t4.isTSAsExpression(current2) || t4.isTSSatisfiesExpression(current2) || t4.isTSNonNullExpression(current2)) {
17319
- current2 = current2.expression;
17320
- continue;
17467
+ this.searchedDirs.clear();
17468
+ }
17469
+ // ---------------------------------------------------------------------------
17470
+ // Our own file watching layer (no Volar equivalent — we're standalone)
17471
+ // ---------------------------------------------------------------------------
17472
+ startWatching() {
17473
+ if (!this.watching) {
17474
+ this.watching = !0;
17475
+ for (let tsconfig of this.configProjects.keys())
17476
+ this.watchDirectory(path3.dirname(tsconfig));
17477
+ this.watchProgramSourceDirs();
17321
17478
  }
17322
- return current2;
17323
17479
  }
17324
- }
17325
- function getObjectKeyName(key) {
17326
- if (t4.isIdentifier(key))
17327
- return key.name;
17328
- if (t4.isStringLiteral(key))
17329
- return key.value;
17330
- }
17331
- function getComponentExpressionName(node) {
17332
- if (node) {
17333
- if (t4.isIdentifier(node))
17334
- return node.name;
17335
- if (t4.isMemberExpression(node) && !node.computed) {
17336
- let objectName = getComponentExpressionName(node.object), propertyName = getComponentExpressionName(node.property);
17337
- return objectName && propertyName ? `${objectName}.${propertyName}` : void 0;
17480
+ /**
17481
+ * Watch directories that contain source files from all TS programs. This covers monorepo setups
17482
+ * where stories import components via path aliases (e.g. apps/storybook/ imports from
17483
+ * packages/ui/ via tsconfig paths).
17484
+ */
17485
+ watchProgramSourceDirs(singleProject) {
17486
+ let dirs = /* @__PURE__ */ new Set();
17487
+ if (singleProject)
17488
+ for (let filePath of singleProject.getSourceFilePaths())
17489
+ dirs.add(path3.dirname(filePath));
17490
+ else {
17491
+ for (let project of this.configProjects.values())
17492
+ for (let filePath of project.getSourceFilePaths())
17493
+ dirs.add(path3.dirname(filePath));
17494
+ if (this.inferredProject)
17495
+ for (let filePath of this.inferredProject.getSourceFilePaths())
17496
+ dirs.add(path3.dirname(filePath));
17497
+ }
17498
+ let roots = /* @__PURE__ */ new Set();
17499
+ for (let dir of dirs) {
17500
+ let candidate = dir;
17501
+ for (; candidate !== path3.dirname(candidate); ) {
17502
+ let normalized = candidate.replace(/\\/g, "/"), alreadyWatched = !1;
17503
+ for (let watched of this.watchersByDir.keys())
17504
+ if (normalized === watched || normalized.startsWith(watched + "/")) {
17505
+ alreadyWatched = !0;
17506
+ break;
17507
+ }
17508
+ if (alreadyWatched)
17509
+ break;
17510
+ if (this.typescript.sys.fileExists(path3.join(candidate, "package.json")) || this.typescript.sys.fileExists(path3.join(candidate, "tsconfig.json"))) {
17511
+ roots.add(candidate);
17512
+ break;
17513
+ }
17514
+ candidate = path3.dirname(candidate);
17515
+ }
17338
17516
  }
17517
+ for (let root of roots)
17518
+ this.watchDirectory(root);
17339
17519
  }
17340
- }
17341
-
17342
- // src/componentManifest/generator.ts
17343
- var componentMetaManager;
17344
- async function createComponentMetaManager(watch2) {
17345
- if (componentMetaManager && watch2)
17346
- return componentMetaManager;
17347
- try {
17348
- let ts = await import("typescript"), manager = new ComponentMetaManager(ts);
17349
- return watch2 && (componentMetaManager = manager), manager;
17350
- } catch {
17351
- logger8.debug(
17352
- "[reactComponentMeta] TypeScript not available, skipping component meta extraction"
17353
- );
17354
- }
17355
- }
17356
- function isAttachedDocsEntry(entry) {
17357
- return entry.type === "docs" && entry.tags?.includes(Tag.ATTACHED_MDX) === !0 && entry.storiesImports.length > 0;
17358
- }
17359
- function selectComponentEntries(manifestEntries) {
17360
- let entriesByComponentId = /* @__PURE__ */ new Map();
17361
- return manifestEntries.filter(
17362
- (entry) => entry.type === "story" && entry.subtype === "story" || // Attached docs entries are the only docs entries that can contribute to a
17363
- // component manifest, because they point back to a story file through storiesImports.
17364
- isAttachedDocsEntry(entry)
17365
- ).forEach((entry) => {
17366
- let componentId = entry.id.split("--")[0], existingEntry = entriesByComponentId.get(componentId);
17367
- if (!existingEntry) {
17368
- entriesByComponentId.set(componentId, entry);
17520
+ watchDirectory(dir) {
17521
+ if (!this.watching)
17369
17522
  return;
17523
+ let normalized = dir.replace(/\\/g, "/");
17524
+ for (let watched of this.watchersByDir.keys())
17525
+ if (normalized === watched || normalized.startsWith(watched + "/"))
17526
+ return;
17527
+ for (let [watched, watcher] of this.watchersByDir)
17528
+ watched.startsWith(normalized + "/") && (watcher.close(), this.watchersByDir.delete(watched));
17529
+ try {
17530
+ let watcher = watch(dir, { recursive: !0 }, (eventType, filename) => {
17531
+ if (!filename)
17532
+ return;
17533
+ let filePath = path3.resolve(dir, filename).replace(/\\/g, "/");
17534
+ if (filePath.includes("/node_modules/") || filePath.includes("/.git/"))
17535
+ return;
17536
+ let existing = this.pendingEvents.get(filePath);
17537
+ existing && clearTimeout(existing), this.pendingEvents.set(
17538
+ filePath,
17539
+ setTimeout(() => {
17540
+ this.pendingEvents.delete(filePath), eventType === "rename" ? existsSync3(filePath) ? this.handleFileEvent(filePath, "created") : this.handleFileEvent(filePath, "deleted") : this.handleFileEvent(filePath, "changed");
17541
+ }, 50)
17542
+ );
17543
+ });
17544
+ watcher.unref(), this.watchersByDir.set(normalized, watcher);
17545
+ } catch (err) {
17546
+ logger7.debug(`[reactComponentMeta] Failed to watch directory ${normalized}: ${err}`);
17370
17547
  }
17371
- existingEntry.type === "docs" && entry.type === "story" && entriesByComponentId.set(componentId, entry);
17372
- }), [...entriesByComponentId.values()];
17373
- }
17374
- function findMatchingComponent(components, componentName, title) {
17375
- let exactMatch = findExactComponentMatch(components, componentName);
17376
- if (exactMatch)
17377
- return exactMatch;
17378
- let trimmedTitle = title.replace(/\s+/g, ""), matches = components.filter(
17379
- (it) => trimmedTitle.includes(it.componentName) || it.localImportName && trimmedTitle.includes(it.localImportName) || it.importName && trimmedTitle.includes(it.importName)
17380
- );
17381
- if (matches.length <= 1)
17382
- return matches[0];
17383
- let best = matches[0];
17384
- for (let cur of matches) {
17385
- if (cur.jsxDepth === 0)
17386
- return cur;
17387
- (cur.jsxDepth ?? 1 / 0) < (best.jsxDepth ?? 1 / 0) && (best = cur);
17388
17548
  }
17389
- return best;
17390
- }
17391
- function getPackageInfo(componentPath, fallbackPath) {
17392
- let nearestPkg = cachedFindUp("package.json", {
17393
- cwd: path.dirname(componentPath ?? fallbackPath)
17394
- });
17395
- try {
17396
- if (!nearestPkg)
17549
+ stopWatching() {
17550
+ for (let timeout of this.pendingEvents.values())
17551
+ clearTimeout(timeout);
17552
+ this.pendingEvents.clear();
17553
+ for (let watcher of this.watchersByDir.values())
17554
+ watcher.close();
17555
+ this.watchersByDir.clear(), this.watching = !1;
17556
+ }
17557
+ /**
17558
+ * Map raw fs.watch events to LSP-style FileChangeType before broadcasting.
17559
+ *
17560
+ * Fs.watch reports atomic saves (sed -i, editors) as `rename` → we classify as `created` (file
17561
+ * exists after rename). But an IDE/LSP would report an atomic save of an _existing_ file as
17562
+ * `Changed`, not `Created`.
17563
+ *
17564
+ * We reclassify here so that onFilesChanged stays 1:1 with Volar Kit.
17565
+ */
17566
+ handleFileEvent(filePath, type) {
17567
+ if (type === "created") {
17568
+ for (let project of this.configProjects.values())
17569
+ if (project.hasSourceFile(filePath)) {
17570
+ type = "changed";
17571
+ break;
17572
+ }
17573
+ type === "created" && this.inferredProject?.hasSourceFile(filePath) && (type = "changed");
17574
+ }
17575
+ let basename3 = path3.basename(filePath);
17576
+ if (rootTsConfigNames.includes(basename3)) {
17577
+ this.onConfigChanged(filePath, type);
17397
17578
  return;
17398
- let parsed = JSON.parse(cachedReadTextFileSync(nearestPkg));
17399
- return typeof parsed == "object" && parsed && "name" in parsed && typeof parsed.name == "string" ? parsed.name : void 0;
17400
- } catch {
17401
- return;
17579
+ }
17580
+ this.onFilesChanged([{ filePath, type }]);
17402
17581
  }
17582
+ dispose() {
17583
+ this.stopWatching();
17584
+ for (let project of this.configProjects.values())
17585
+ project.dispose();
17586
+ this.inferredProject?.dispose(), this.configProjects.clear(), this.inferredProject = void 0, this.fsFileSnapshots.clear(), this.searchedDirs.clear(), this.rootTsConfigs.clear();
17587
+ }
17588
+ };
17589
+ function sortTSConfigs(file, a, b) {
17590
+ let inA = isFileInDir(file, path3.dirname(a)), inB = isFileInDir(file, path3.dirname(b));
17591
+ if (inA !== inB)
17592
+ return (inB ? 1 : 0) - (inA ? 1 : 0);
17593
+ let aLength = a.split("/").length, bLength = b.split("/").length;
17594
+ if (aLength === bLength) {
17595
+ let aWeight = path3.basename(a) === "tsconfig.json" ? 1 : 0;
17596
+ return (path3.basename(b) === "tsconfig.json" ? 1 : 0) - aWeight;
17597
+ }
17598
+ return bLength - aLength;
17403
17599
  }
17404
- function getFallbackImport(packageName, componentName) {
17405
- let exportName = componentName?.split(".").at(-1);
17406
- return packageName && exportName ? `import { ${exportName} } from "${packageName}";` : "";
17407
- }
17408
- function getComponentDocgenData(component, docgenEngine) {
17409
- let reactDocgen, reactDocgenTypescript, reactComponentMeta, docgenDescription, docgenJsDocTags, docgenError;
17410
- if (docgenEngine === "react-docgen") {
17411
- let result = component?.reactDocgen;
17412
- reactDocgen = result?.type === "success" ? result.data : void 0, docgenDescription = reactDocgen?.description, docgenError = result?.type === "error" ? result.error : void 0;
17413
- } else docgenEngine === "react-docgen-typescript" ? (reactDocgenTypescript = component?.reactDocgenTypescript, docgenDescription = reactDocgenTypescript?.description, docgenError = component?.reactDocgenTypescriptError) : (reactComponentMeta = component?.reactComponentMeta, docgenDescription = reactComponentMeta?.description, docgenJsDocTags = component?.componentJsDocTags);
17414
- return {
17415
- docgenDescription,
17416
- docgenError,
17417
- docgenJsDocTags,
17418
- reactComponentMeta,
17419
- reactDocgen,
17420
- reactDocgenTypescript
17421
- };
17422
- }
17423
- function createSubcomponentManifest({
17424
- component,
17425
- declaredName,
17426
- docgenEngine,
17427
- packageName,
17428
- storyFilePath
17429
- }) {
17430
- let imports = getImports({ components: component ? [component] : [], packageName }).join(`
17431
- `).trim() || getFallbackImport(packageName, component?.componentName), {
17432
- reactDocgen,
17433
- reactDocgenTypescript,
17434
- reactComponentMeta,
17435
- docgenDescription,
17436
- docgenJsDocTags,
17437
- docgenError
17438
- } = getComponentDocgenData(component, docgenEngine), { description, summary, jsDocTags } = extractComponentDescription(
17439
- void 0,
17440
- docgenDescription,
17441
- docgenJsDocTags
17442
- );
17443
- return {
17444
- name: declaredName,
17445
- path: component?.path ?? storyFilePath,
17446
- description,
17447
- summary,
17448
- import: imports || void 0,
17449
- jsDocTags,
17450
- reactDocgen,
17451
- reactDocgenTypescript,
17452
- reactComponentMeta,
17453
- error: docgenError ?? (component ? void 0 : {
17454
- name: "No component import found",
17455
- message: `No component file found for the "${declaredName}" subcomponent.`
17456
- })
17457
- };
17600
+ function isFileInDir(fileName, dir) {
17601
+ let relative3 = path3.relative(dir, fileName);
17602
+ return !!relative3 && !relative3.startsWith("..") && !path3.isAbsolute(relative3);
17458
17603
  }
17459
- function extractStories(csf, componentName, manifestEntries) {
17460
- let manifestEntryIds = new Set(manifestEntries.map((entry) => entry.id));
17461
- return Object.entries(csf._stories).filter(
17462
- ([, story]) => (
17463
- // Only include stories that are in the list of entries already filtered for the 'manifest' tag
17464
- manifestEntryIds.has(story.id)
17465
- )
17466
- ).map(([storyExport, story]) => {
17604
+
17605
+ // src/componentManifest/componentMetaManagerSingleton.ts
17606
+ var componentMetaManagerPromise;
17607
+ function getSharedComponentMetaManager() {
17608
+ return componentMetaManagerPromise || (componentMetaManagerPromise = (async () => {
17467
17609
  try {
17468
- let jsdocComment = extractDescription(csf._storyStatements[storyExport]), { tags = {}, description } = jsdocComment ? extractJSDocInfo(jsdocComment) : {}, finalDescription = (tags?.describe?.[0] || tags?.desc?.[0]) ?? description;
17469
- return {
17470
- id: story.id,
17471
- name: story.name ?? storyNameFromExport(storyExport),
17472
- snippet: recast2.print(getCodeSnippet(csf, storyExport, componentName)).code,
17473
- description: finalDescription?.trim(),
17474
- summary: tags.summary?.[0]
17475
- };
17476
- } catch (e) {
17477
- return invariant(e instanceof Error), {
17478
- id: story.id,
17479
- name: story.name ?? storyNameFromExport(storyExport),
17480
- error: { name: e.name, message: e.message }
17481
- };
17610
+ let ts = await import("typescript");
17611
+ return new ComponentMetaManager(ts);
17612
+ } catch {
17613
+ logger8.debug(
17614
+ "[reactComponentMeta] TypeScript not available, skipping component meta extraction."
17615
+ );
17616
+ return;
17482
17617
  }
17483
- });
17484
- }
17485
- function extractComponentDescription(metaJsDoc, docgenDescription, docgenJsDocTags) {
17486
- let jsdocComment = metaJsDoc || docgenDescription, extracted = jsdocComment ? extractJSDocInfo(jsdocComment) : void 0, tags = docgenJsDocTags ?? extracted?.tags ?? {}, description = extracted?.description;
17487
- return {
17488
- description: ((tags?.describe?.[0] || tags?.desc?.[0]) ?? description)?.trim(),
17489
- summary: tags.summary?.[0],
17490
- jsDocTags: tags
17491
- };
17618
+ })()), componentMetaManagerPromise;
17492
17619
  }
17620
+
17621
+ // src/componentManifest/generator.ts
17493
17622
  var manifests = async (existingManifests = {}, options) => {
17494
17623
  let { manifestEntries, presets, watch: watch2 } = options, typescriptOptions = await presets?.apply("typescript", {}) ?? {}, docgenEngine = (await presets?.apply("features", {}))?.experimentalReactComponentMeta ? "react-component-meta" : typescriptOptions.reactDocgen || "react-docgen";
17495
17624
  invalidateCache(), invalidateParser();
17496
- let startTime = performance.now(), manager = docgenEngine === "react-component-meta" ? await createComponentMetaManager(watch2) : null;
17497
- try {
17498
- let entriesByUniqueComponent = selectComponentEntries(manifestEntries), resolvedEntries = await Promise.all(
17499
- entriesByUniqueComponent.map(async (entry) => {
17500
- let storyFilePath = entry.type === "story" ? entry.importPath : (
17501
- // For attached docs entries, storiesImports[0] points to the stories file being attached to
17502
- entry.storiesImports[0]
17503
- ), storyPath = path.join(process.cwd(), storyFilePath), storyFile = cachedReadTextFileSync(storyPath), csf = loadCsf(storyFile, {
17504
- makeTitle: () => entry.title
17505
- }).parse(), componentName = csf._meta?.component, declaredSubcomponents = extractDeclaredSubcomponents(csf), allComponents = await getComponents({
17506
- additionalComponentNames: declaredSubcomponents.map(
17507
- (subcomponent) => subcomponent.componentName
17508
- ),
17509
- csf,
17510
- storyFilePath: storyPath,
17511
- typescriptOptions,
17512
- docgenEngine
17513
- }), component = findMatchingComponent(allComponents, componentName, entry.title), subcomponents = declaredSubcomponents.map((declaredSubcomponent) => ({
17514
- component: findExactComponentMatch(allComponents, declaredSubcomponent.componentName),
17515
- name: declaredSubcomponent.name
17516
- }));
17517
- return {
17518
- storyPath,
17519
- component,
17520
- entry,
17521
- storyFilePath,
17522
- storyFile,
17523
- csf,
17524
- componentName,
17525
- allComponents,
17526
- subcomponents
17527
- };
17528
- })
17529
- );
17530
- docgenEngine === "react-component-meta" && manager && manager.batchExtract(
17531
- resolvedEntries.flatMap(({ storyPath, component, subcomponents }) => [
17532
- ...component ? [{ storyPath, component }] : [],
17533
- ...subcomponents.filter(
17534
- (subcomponent) => subcomponent.component !== void 0
17535
- ).map((subcomponent) => ({
17536
- storyPath,
17537
- component: subcomponent.component
17538
- }))
17539
- ])
17540
- );
17541
- let components = resolvedEntries.map(
17542
- ({
17625
+ let startTime = performance.now(), manager = docgenEngine === "react-component-meta" ? await getSharedComponentMetaManager() : void 0, entriesByUniqueComponent = [
17626
+ ...selectComponentEntriesByComponentId(manifestEntries).values()
17627
+ ], resolvedEntries = await Promise.all(
17628
+ entriesByUniqueComponent.map(async (entry) => {
17629
+ let storyFilePath = getStoryImportPathFromEntry(entry);
17630
+ if (!storyFilePath)
17631
+ throw new Error(`No story file path for index entry ${entry.id}`);
17632
+ let storyPath = path.join(process.cwd(), storyFilePath), resolved = await resolveStoryFileComponents({
17543
17633
  storyPath,
17544
- component,
17634
+ title: entry.title,
17635
+ typescriptOptions,
17636
+ docgenEngine
17637
+ });
17638
+ return { entry, storyFilePath, ...resolved };
17639
+ })
17640
+ );
17641
+ docgenEngine === "react-component-meta" && manager && manager.batchExtract(
17642
+ resolvedEntries.flatMap(({ storyPath, component, subcomponents }) => [
17643
+ ...component ? [{ storyPath, component }] : [],
17644
+ ...subcomponents.filter(
17645
+ (subcomponent) => subcomponent.component !== void 0
17646
+ ).map((subcomponent) => ({
17647
+ storyPath,
17648
+ component: subcomponent.component
17649
+ }))
17650
+ ])
17651
+ );
17652
+ let manifestEntryIds = new Set(manifestEntries.map((entry) => entry.id)), components = resolvedEntries.map(
17653
+ ({
17654
+ storyPath,
17655
+ component,
17656
+ entry,
17657
+ storyFilePath,
17658
+ storyFile,
17659
+ csf,
17660
+ componentName,
17661
+ allComponents,
17662
+ subcomponents
17663
+ }) => toReactComponentManifest(
17664
+ buildReactComponentDocgenFromResolved({
17545
17665
  entry,
17666
+ storyPath,
17546
17667
  storyFilePath,
17547
17668
  storyFile,
17548
17669
  csf,
17549
17670
  componentName,
17671
+ component,
17550
17672
  allComponents,
17551
- subcomponents
17552
- }) => {
17553
- let id = entry.id.split("--")[0], title = entry.title.split("/").at(-1).replace(/\s+/g, ""), packageName = getPackageInfo(component?.path, storyPath), fallbackImport = getFallbackImport(packageName, componentName), imports = getImports({ components: allComponents, packageName }).join(`
17554
- `).trim() || fallbackImport, stories = extractStories(csf, component?.componentName, manifestEntries), base2 = {
17555
- id,
17556
- name: componentName ?? title,
17557
- path: storyFilePath,
17558
- stories,
17559
- import: imports,
17560
- jsDocTags: {}
17561
- }, {
17562
- reactDocgen,
17563
- reactDocgenTypescript,
17564
- reactComponentMeta,
17565
- docgenDescription,
17566
- docgenJsDocTags,
17567
- docgenError
17568
- } = getComponentDocgenData(component, docgenEngine);
17569
- if (!reactDocgen && !reactDocgenTypescript && !reactComponentMeta) {
17570
- let error = csf._meta?.component ? {
17571
- name: "No component import found",
17572
- message: `No component file found for the "${csf.meta.component}" component.`
17573
- } : {
17574
- name: "No component found",
17575
- message: "We could not detect the component from your story file. Specify meta.component."
17576
- };
17577
- return {
17578
- ...base2,
17579
- error: docgenError ?? {
17580
- name: error.name,
17581
- message: (csf._metaStatementPath?.buildCodeFrameError(error.message).message ?? error.message) + `
17582
-
17583
- ${entry.importPath}:
17584
- ${storyFile}`
17585
- }
17586
- };
17587
- }
17588
- let metaJsDoc = extractDescription(csf._metaStatement) || void 0, { description, summary, jsDocTags } = extractComponentDescription(
17589
- metaJsDoc,
17590
- docgenDescription,
17591
- docgenJsDocTags
17592
- ), subcomponentEntries = Object.fromEntries(
17593
- subcomponents.map((subcomponent) => [
17594
- subcomponent.name,
17595
- createSubcomponentManifest({
17596
- component: subcomponent.component,
17597
- declaredName: subcomponent.name,
17598
- docgenEngine,
17599
- packageName,
17600
- storyFilePath
17601
- })
17602
- ])
17603
- );
17604
- return {
17605
- ...base2,
17606
- description,
17607
- summary,
17608
- import: imports,
17609
- reactDocgen,
17610
- reactDocgenTypescript,
17611
- reactComponentMeta,
17612
- jsDocTags,
17613
- ...Object.keys(subcomponentEntries).length > 0 ? { subcomponents: subcomponentEntries } : {},
17614
- error: docgenError
17615
- };
17616
- }
17617
- ).filter((component) => component !== void 0);
17618
- manager && watch2 && manager.startWatching();
17619
- let durationMs = Math.round(performance.now() - startTime);
17620
- return {
17621
- ...existingManifests,
17622
- components: {
17623
- v: 0,
17624
- components: Object.fromEntries(components.map((component) => [component.id, component])),
17625
- meta: {
17626
- docgen: docgenEngine,
17627
- durationMs
17628
- }
17673
+ subcomponents,
17674
+ docgenEngine,
17675
+ filterStoryIds: manifestEntryIds
17676
+ })
17677
+ )
17678
+ ).filter((component) => component !== void 0);
17679
+ manager && watch2 && manager.startWatching();
17680
+ let durationMs = Math.round(performance.now() - startTime);
17681
+ return {
17682
+ ...existingManifests,
17683
+ components: {
17684
+ v: 0,
17685
+ components: Object.fromEntries(components.map((component) => [component.id, component])),
17686
+ meta: {
17687
+ docgen: docgenEngine,
17688
+ durationMs
17629
17689
  }
17630
- };
17631
- } finally {
17632
- manager && !watch2 && manager.dispose();
17633
- }
17690
+ }
17691
+ };
17634
17692
  };
17635
17693
 
17636
17694
  // src/enrichCsf.ts
@@ -17706,6 +17764,120 @@ var enrichCsf = async (input, options) => {
17706
17764
  };
17707
17765
  };
17708
17766
 
17767
+ // src/docgen/preset.ts
17768
+ import { STORY_FILE_TEST_REGEXP, getStoryImportPathFromEntry as getStoryImportPathFromEntry3 } from "storybook/internal/common";
17769
+
17770
+ // src/docgen/buildDocgen.ts
17771
+ import { getStoryImportPathFromEntry as getStoryImportPathFromEntry2 } from "storybook/internal/common";
17772
+ function mapProps(doc) {
17773
+ return doc ? Object.values(doc.props).map((prop) => ({
17774
+ name: prop.name,
17775
+ required: prop.required,
17776
+ type: prop.type,
17777
+ description: prop.description,
17778
+ defaultValue: prop.defaultValue,
17779
+ parent: prop.parent,
17780
+ declarations: prop.declarations
17781
+ })) : [];
17782
+ }
17783
+ function mapSubcomponentToDocgen(sub) {
17784
+ return {
17785
+ name: sub.name,
17786
+ path: sub.path,
17787
+ description: sub.description,
17788
+ summary: sub.summary,
17789
+ import: sub.import,
17790
+ jsDocTags: sub.jsDocTags,
17791
+ props: mapProps(sub.reactComponentMeta),
17792
+ error: sub.error
17793
+ };
17794
+ }
17795
+ function toDocgenPayload(resolved) {
17796
+ let stories = resolved.stories.length > 0 ? resolved.stories.map((story) => ({
17797
+ id: story.id,
17798
+ name: story.name,
17799
+ snippet: story.snippet,
17800
+ description: story.description,
17801
+ summary: story.summary,
17802
+ error: story.error
17803
+ })) : void 0, subcomponents = resolved.subcomponents && Object.keys(resolved.subcomponents).length > 0 ? Object.fromEntries(
17804
+ Object.entries(resolved.subcomponents).map(([key, sub]) => [
17805
+ key,
17806
+ mapSubcomponentToDocgen(sub)
17807
+ ])
17808
+ ) : void 0;
17809
+ return {
17810
+ componentId: resolved.componentId,
17811
+ name: resolved.name,
17812
+ path: resolved.path,
17813
+ import: resolved.import,
17814
+ description: resolved.description ?? "",
17815
+ summary: resolved.summary,
17816
+ jsDocTags: resolved.jsDocTags,
17817
+ props: mapProps(resolved.reactComponentMeta),
17818
+ error: resolved.error,
17819
+ ...subcomponents ? { subcomponents } : {},
17820
+ ...stories ? { stories } : {}
17821
+ };
17822
+ }
17823
+ async function buildDocgenPayload(input, context) {
17824
+ let storyFilePath = getStoryImportPathFromEntry2(input.entry);
17825
+ if (!storyFilePath)
17826
+ return;
17827
+ let storyPath = (context.resolvePath ?? ((importPath) => path.join(process.cwd(), importPath)))(storyFilePath), resolved;
17828
+ try {
17829
+ resolved = await resolveStoryFileComponents({
17830
+ storyPath,
17831
+ title: input.entry.title,
17832
+ typescriptOptions: context.typescriptOptions,
17833
+ docgenEngine: "react-component-meta"
17834
+ });
17835
+ } catch {
17836
+ return;
17837
+ }
17838
+ let { csf, componentName, component, allComponents, subcomponents, storyFile } = resolved, usableSubcomponents = subcomponents.filter(
17839
+ (sub) => sub.component !== void 0
17840
+ ), storyRefs = [
17841
+ ...component ? [{ storyPath, component }] : [],
17842
+ ...usableSubcomponents.map((sub) => ({ storyPath, component: sub.component }))
17843
+ ];
17844
+ storyRefs.length > 0 && context.componentMetaManager.batchExtract(storyRefs);
17845
+ let componentDocgen = buildReactComponentDocgenFromResolved({
17846
+ entry: input.entry,
17847
+ storyPath,
17848
+ storyFilePath,
17849
+ storyFile,
17850
+ csf,
17851
+ componentName,
17852
+ component,
17853
+ allComponents,
17854
+ subcomponents,
17855
+ docgenEngine: "react-component-meta"
17856
+ });
17857
+ return toDocgenPayload(componentDocgen);
17858
+ }
17859
+
17860
+ // src/docgen/preset.ts
17861
+ var experimental_docgenProvider = async (nextDocgen, options) => {
17862
+ let typescriptOptionsPromise = options.presets?.apply(
17863
+ "typescript",
17864
+ {}
17865
+ ) ?? Promise.resolve({});
17866
+ return getSharedComponentMetaManager(), async (input) => {
17867
+ let storyImportPath = getStoryImportPathFromEntry3(input.entry);
17868
+ if (!storyImportPath || !STORY_FILE_TEST_REGEXP.test(storyImportPath))
17869
+ return nextDocgen(input);
17870
+ let componentMetaManager = await getSharedComponentMetaManager();
17871
+ if (!componentMetaManager)
17872
+ return nextDocgen(input);
17873
+ let ours = await buildDocgenPayload(input, {
17874
+ componentMetaManager,
17875
+ typescriptOptions: await typescriptOptionsPromise
17876
+ });
17877
+ return ours ? { ...await nextDocgen(input), ...ours } : nextDocgen(input);
17878
+ };
17879
+ };
17880
+
17709
17881
  // src/preset.ts
17710
17882
  var addons = [
17711
17883
  import.meta.resolve("@storybook/react-dom-shim/preset")
@@ -17759,6 +17931,7 @@ async function internal_getArgTypesData(_input, options) {
17759
17931
  var optimizeViteDeps = ["react-dom/test-utils"];
17760
17932
  export {
17761
17933
  addons,
17934
+ experimental_docgenProvider,
17762
17935
  enrichCsf as experimental_enrichCsf,
17763
17936
  manifests as experimental_manifests,
17764
17937
  internal_getArgTypesData,