UNPKG

storybook

Version:

Storybook: Develop, document, and test UI components in isolation

1,141 lines 53.2 kB
import CJS_COMPAT_NODE_URL_qjinduibsyq from 'node:url';
import CJS_COMPAT_NODE_PATH_qjinduibsyq from 'node:path';
import CJS_COMPAT_NODE_MODULE_qjinduibsyq from "node:module";

var __filename = CJS_COMPAT_NODE_URL_qjinduibsyq.fileURLToPath(import.meta.url);
var __dirname = CJS_COMPAT_NODE_PATH_qjinduibsyq.dirname(__filename);
var require = CJS_COMPAT_NODE_MODULE_qjinduibsyq.createRequire(import.meta.url);

// ------------------------------------------------------------
// end of CJS compatibility banner, injected by Storybook's esbuild configuration
// ------------------------------------------------------------
import {
  jsTsSourceExtensions
} from "./chunk-7LZUPCQB.js";
import {
  require_dist
} from "./chunk-FE5AV6EP.js";
import {
  __toESM
} from "./chunk-4US4PNS3.js";

// src/shared/constants/tags.ts
var Tag = {
  /** Indicates that autodocs should be generated for this component */
  AUTODOCS: "autodocs",
  /** MDX documentation attached to a component's stories file */
  ATTACHED_MDX: "attached-mdx",
  /** Standalone MDX documentation not attached to stories */
  UNATTACHED_MDX: "unattached-mdx",
  /** Story has a play function */
  PLAY_FN: "play-fn",
  /** Story has a test function */
  TEST_FN: "test-fn",
  /** Development environment tag */
  DEV: "dev",
  /** Test environment tag */
  TEST: "test",
  /** Manifest generation tag */
  MANIFEST: "manifest"
};

// src/common/utils/module-resolver.ts
import { ResolverFactory } from "oxc-resolver";
var defaultResolveConditionNames = ["storybook", "import", "module", "default"];
function createModuleResolver(options = {}) {
  let factory = new ResolverFactory({
    ...options,
    conditionNames: options.conditionNames ?? defaultResolveConditionNames
  }), unwrap = (result, specifier, from) => {
    if (result.path)
      return result.path;
    throw new Error(result.error ?? `Cannot resolve module '${specifier}' from '${from}'`);
  };
  return {
    resolveFileSync: (fromFile, specifier) => unwrap(factory.resolveFileSync(fromFile, specifier), specifier, fromFile),
    resolveSync: (fromDirectory, specifier) => unwrap(factory.sync(fromDirectory, specifier), specifier, fromDirectory)
  };
}

// src/csf-tools/story-shape/utils.ts
import { types as t } from "storybook/internal/babel";
var unwrapExpression = (node) => t.isTSAsExpression(node) || t.isTSSatisfiesExpression(node) || t.isTSNonNullExpression(node) || t.isTSTypeAssertion(node) || t.isParenthesizedExpression(node) ? unwrapExpression(node.expression) : node, isCanonicalCsf2BindCall = (node) => t.isCallExpression(node) && t.isMemberExpression(node.callee) && !node.callee.computed && t.isIdentifier(node.callee.object) && t.isIdentifier(node.callee.property, { name: "bind" }) && (node.arguments.length === 0 || node.arguments.length === 1 && t.isObjectExpression(node.arguments[0]) && node.arguments[0].properties.length === 0), isCsfFactoryCall = (node) => t.isCallExpression(node) && t.isMemberExpression(node.callee) && !node.callee.computed && t.isIdentifier(node.callee.object) && t.isIdentifier(node.callee.property) && (node.callee.property.name === "story" || node.callee.property.name === "extend"), keyOf = (p) => t.isStringLiteral(p.key) ? p.key.value : !p.computed && t.isIdentifier(p.key) ? p.key.name : null, propertyValue = (object, name) => object?.properties.find(
  (candidate) => t.isObjectProperty(candidate) && keyOf(candidate) === name
)?.value, soleReturnedExpression = (body) => {
  let [statement, ...rest] = body.body;
  return rest.length === 0 && t.isReturnStatement(statement) && t.isExpression(statement.argument) ? statement.argument : void 0;
}, returnedExpression = (fn) => {
  if (t.isFunction(fn))
    return t.isExpression(fn.body) ? fn.body : soleReturnedExpression(fn.body);
}, returnedExpressionPath = (renderFunction) => {
  if (!returnedExpression(renderFunction.node))
    return;
  let body = renderFunction.get("body");
  if (body.isExpression())
    return body;
  let [statement] = body.isBlockStatement() ? body.get("body") : [], argument = statement?.isReturnStatement() ? statement.get("argument") : void 0;
  return argument?.isExpression() ? argument : void 0;
}, resolveReturnedObjectExpression = (renderFunction) => {
  let returned = returnedExpressionPath(renderFunction);
  if (returned?.isObjectExpression())
    return returned.node;
  if (!returned?.isIdentifier())
    return;
  let resolved = resolveIdentifierInit(renderFunction, returned);
  return resolved?.isObjectExpression() ? resolved.node : void 0;
};
function resolveIdentifierInit(storyPath, identifier) {
  let programPath = storyPath.findParent((p) => p.isProgram());
  if (!programPath)
    return null;
  for (let stmt of programPath.get("body")) {
    if (stmt.isFunctionDeclaration() && stmt.node.id?.name === identifier.node.name)
      return stmt;
    if (stmt.isExportNamedDeclaration()) {
      let decl = stmt.get("declaration");
      if (decl.isFunctionDeclaration() && decl.node.id?.name === identifier.node.name)
        return decl;
    }
  }
  let match = programPath.get("body").flatMap((stmt) => {
    if (stmt.isVariableDeclaration())
      return stmt.get("declarations");
    if (stmt.isExportNamedDeclaration()) {
      let decl = stmt.get("declaration");
      if (decl && decl.isVariableDeclaration())
        return decl.get("declarations");
    }
    return [];
  }).find((d) => {
    let id = d.get("id");
    return id.isIdentifier() && id.node.name === identifier.node.name;
  });
  if (!match)
    return null;
  let init = match.get("init");
  return init && init.isExpression() ? init : null;
}
function pathForNode(program, target) {
  if (!target)
    return;
  let found;
  return program.traverse({
    enter(p) {
      p.node && p.node === target && (found = p, p.stop());
    }
  }), found;
}
function metaObjectPath(csf) {
  let metaPath = pathForNode(csf._file.path, csf._metaNode);
  return metaPath?.isObjectExpression() ? metaPath : void 0;
}

// src/csf-tools/CsfFile.ts
var import_ts_dedent = __toESM(require_dist(), 1);
import { readFile, writeFile } from "node:fs/promises";
import {
  BabelFileClass,
  babelParse,
  generate,
  recast,
  types as t3,
  traverse
} from "storybook/internal/babel";
import {
  isExportStory,
  storyNameFromExport,
  toId,
  toTestId
} from "storybook/internal/csf/csf-utils";
import { logger } from "storybook/internal/node-logger";

// src/csf-tools/findVarInitialization.ts
import { types as t2 } from "storybook/internal/babel";
var findVarInitialization = (identifier, program) => {
  let init = null, declarations = null;
  return program.body.find((node) => (t2.isVariableDeclaration(node) ? declarations = node.declarations : t2.isExportNamedDeclaration(node) && t2.isVariableDeclaration(node.declaration) && (declarations = node.declaration.declarations), declarations && declarations.find((decl) => t2.isVariableDeclarator(decl) && t2.isIdentifier(decl.id) && decl.id.name === identifier ? (init = decl.init, !0) : !1))), init;
};

// src/csf-tools/CsfFile.ts
var PREVIEW_FILE_REGEX = /\/preview(.(js|jsx|mjs|ts|tsx))?$/, isValidPreviewPath = (filepath) => PREVIEW_FILE_REGEX.test(filepath);
function parseIncludeExclude(prop) {
  if (t3.isArrayExpression(prop))
    return prop.elements.map((e) => {
      if (t3.isStringLiteral(e))
        return e.value;
      throw new Error(`Expected string literal: ${e}`);
    });
  if (t3.isStringLiteral(prop))
    return new RegExp(prop.value);
  if (t3.isRegExpLiteral(prop))
    return new RegExp(prop.pattern, prop.flags);
  throw new Error(`Unknown include/exclude: ${prop}`);
}
function parseTags(prop) {
  if (!t3.isArrayExpression(prop))
    throw new Error("CSF: Expected tags array");
  return prop.elements.map((e) => {
    if (t3.isStringLiteral(e))
      return e.value;
    throw new Error("CSF: Expected tag to be string literal");
  });
}
function parseTestTags(optionsNode, program) {
  if (!optionsNode)
    return [];
  let node = optionsNode;
  if (t3.isIdentifier(node) && (node = findVarInitialization(node.name, program)), t3.isObjectExpression(node)) {
    let tagsProp = node.properties.find(
      (property) => t3.isObjectProperty(property) && t3.isIdentifier(property.key) && property.key.name === "tags"
    );
    if (tagsProp) {
      let tagsNode = tagsProp.value;
      return t3.isIdentifier(tagsNode) && (tagsNode = findVarInitialization(tagsNode.name, program)), parseTags(tagsNode);
    }
  }
  return [];
}
var formatLocation = (node, fileName) => {
  let loc = "";
  if (node.loc) {
    let { line, column } = node.loc?.start || {};
    loc = `(line ${line}, col ${column})`;
  }
  return `${fileName || ""} ${loc}`.trim();
}, isModuleMock = (importPath) => MODULE_MOCK_REGEX.test(importPath), isArgsStory = (init, parent, csf) => {
  let storyFn = init;
  if (t3.isProgram(parent) && isCanonicalCsf2BindCall(init)) {
    let boundIdentifier = init.callee.object.name, template = findVarInitialization(boundIdentifier, parent);
    template && (csf._templates[boundIdentifier] = template, storyFn = template);
  }
  return t3.isArrowFunctionExpression(storyFn) || t3.isFunctionDeclaration(storyFn) ? storyFn.params.length > 0 : !1;
}, parseExportsOrder = (init) => {
  if (t3.isArrayExpression(init))
    return init.elements.map((item) => {
      if (t3.isStringLiteral(item))
        return item.value;
      throw new Error(`Expected string literal named export: ${item}`);
    });
  throw new Error(`Expected array of string literals: ${init}`);
}, sortExports = (exportByName, order) => order.reduce(
  (acc, name) => {
    let namedExport = exportByName[name];
    return namedExport && (acc[name] = namedExport), acc;
  },
  {}
), hasMount = (play) => {
  if (t3.isArrowFunctionExpression(play) || t3.isFunctionDeclaration(play) || t3.isObjectMethod(play)) {
    let params = play.params;
    if (params.length >= 1) {
      let [arg] = params;
      if (t3.isObjectPattern(arg))
        return !!arg.properties.find((prop) => {
          if (t3.isObjectProperty(prop) && t3.isIdentifier(prop.key))
            return prop.key.name === "mount";
        });
    }
  }
  return !1;
}, MODULE_MOCK_REGEX = /^[.\/#].*\.mock($|\.[^.]*$)/i, NoMetaError = class extends Error {
  constructor(message, ast, fileName) {
    let msg = message.trim();
    super(import_ts_dedent.dedent`
      CSF: ${msg} ${formatLocation(ast, fileName)}
      
      More info: https://storybook.js.org/docs/writing-stories?ref=error#default-export
    `), this.name = this.constructor.name;
  }
}, MultipleMetaError = class extends Error {
  constructor(message, ast, fileName) {
    let msg = `${message} ${formatLocation(ast, fileName)}`.trim();
    super(import_ts_dedent.dedent`
      CSF: ${message} ${formatLocation(ast, fileName)}
      
      More info: https://storybook.js.org/docs/writing-stories?ref=error#default-export
    `), this.name = this.constructor.name;
  }
}, MixedFactoryError = class extends Error {
  constructor(message, ast, fileName) {
    let msg = `${message} ${formatLocation(ast, fileName)}`.trim();
    super(import_ts_dedent.dedent`
      CSF: ${message} ${formatLocation(ast, fileName)}
      
      More info: https://storybook.js.org/docs/writing-stories?ref=error#default-export
    `), this.name = this.constructor.name;
  }
}, BadMetaError = class extends Error {
  constructor(message, ast, fileName) {
    let msg = "".trim();
    super(import_ts_dedent.dedent`
      CSF: ${message} ${formatLocation(ast, fileName)}
      
      More info: https://storybook.js.org/docs/writing-stories?ref=error#default-export
    `), this.name = this.constructor.name;
  }
}, CsfFile = class {
  constructor(ast, options, file) {
    this._stories = {};
    this._metaAnnotations = {};
    this._storyExports = {};
    this._storyDeclarationPath = {};
    this._storyPaths = {};
    this._storyStatements = {};
    this._storyAnnotations = {};
    this._templates = {};
    this._tests = [];
    this._ast = ast, this._file = file, this._options = options, this.imports = [];
  }
  _parseTitle(value) {
    let node = t3.isIdentifier(value) ? findVarInitialization(value.name, this._ast.program) : value;
    if (t3.isStringLiteral(node))
      return node.value;
    if (t3.isTSSatisfiesExpression(node) && t3.isStringLiteral(node.expression))
      return node.expression.value;
    throw new Error(import_ts_dedent.dedent`
      CSF: unexpected dynamic title ${formatLocation(node, this._options.fileName)}

      More info: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#string-literal-titles
    `);
  }
  _parseMeta(declaration, program) {
    if (this._metaNode)
      throw new MultipleMetaError("multiple meta objects", declaration, this._options.fileName);
    this._metaNode = declaration;
    let meta = {};
    declaration.properties.forEach((p) => {
      if (t3.isIdentifier(p.key)) {
        let value = t3.isObjectMethod(p) ? p : p.value;
        if (this._metaAnnotations[p.key.name] = value, p.key.name === "title")
          meta.title = this._parseTitle(p.value);
        else if (["includeStories", "excludeStories"].includes(p.key.name))
          meta[p.key.name] = parseIncludeExclude(p.value);
        else if (p.key.name === "component") {
          let n = p.value;
          if (t3.isIdentifier(n)) {
            let id = n.name, importStmt = program.body.find(
              (stmt) => t3.isImportDeclaration(stmt) && stmt.specifiers.find((spec) => spec.local.name === id)
            );
            if (importStmt) {
              let { source } = importStmt, specifier = importStmt.specifiers.find((spec) => spec.local.name === id);
              t3.isStringLiteral(source) && specifier && (this._rawComponentPath = source.value, (t3.isImportSpecifier(specifier) || t3.isImportDefaultSpecifier(specifier)) && (this._componentImportSpecifier = specifier));
            }
          }
          let { code } = recast.print(p.value, {});
          meta.component = code;
        } else if (p.key.name === "tags") {
          let node = p.value;
          t3.isIdentifier(node) && (node = findVarInitialization(node.name, this._ast.program)), meta.tags = parseTags(node);
        } else if (p.key.name === "id")
          if (t3.isStringLiteral(p.value))
            meta.id = p.value.value;
          else
            throw new Error(`Unexpected component id: ${p.value}`);
      }
    }), this._meta = meta;
  }
  getStoryExport(key) {
    let node = this._storyExports[key];
    return node = t3.isVariableDeclarator(node) ? node.init : node, isCanonicalCsf2BindCall(node) && (node = this._templates[node.callee.object.name]), node;
  }
  parse() {
    let self = this;
    if (traverse(this._ast, {
      ExportDefaultDeclaration: {
        enter(path) {
          let { node, parent } = path, isVariableReference = t3.isIdentifier(node.declaration) && t3.isProgram(parent);
          if (self._options.transformInlineMeta && !isVariableReference && t3.isExpression(node.declaration)) {
            let metaId = path.scope.generateUidIdentifier("meta");
            self._metaVariableName = metaId.name;
            let nodes = [
              t3.variableDeclaration("const", [t3.variableDeclarator(metaId, node.declaration)]),
              t3.exportDefaultDeclaration(metaId)
            ];
            nodes.forEach((_node) => _node.loc = path.node.loc), path.replaceWithMultiple(nodes);
            return;
          }
          let metaNode, decl;
          if (isVariableReference) {
            let variableName = node.declaration.name;
            self._metaVariableName = variableName;
            let isMetaVariable = (declaration) => t3.isIdentifier(declaration.id) && declaration.id.name === variableName;
            self._metaStatementPath = self._file.path.get("body").find(
              (path2) => path2.isVariableDeclaration() && path2.node.declarations.some(isMetaVariable)
            ), self._metaStatement = self._metaStatementPath?.node, decl = (self?._metaStatement?.declarations || []).find(
              isMetaVariable
            )?.init;
          } else
            self._metaStatement = node, self._metaStatementPath = path, decl = node.declaration;
          if (t3.isObjectExpression(decl) ? metaNode = decl : /* export default { ... } as Meta<...> */ /* export default { ... } satisfies Meta<...> */ (t3.isTSAsExpression(decl) || t3.isTSSatisfiesExpression(decl)) && t3.isObjectExpression(decl.expression) ? metaNode = decl.expression : (
            // export default { ... } satisfies Meta as Meta<...>
            t3.isTSAsExpression(decl) && t3.isTSSatisfiesExpression(decl.expression) && t3.isObjectExpression(decl.expression.expression) && (metaNode = decl.expression.expression)
          ), metaNode && t3.isProgram(parent) && self._parseMeta(metaNode, parent), self._metaStatement && !self._metaNode)
            throw new NoMetaError(
              "default export must be an object",
              self._metaStatement,
              self._options.fileName
            );
          self._metaPath = path;
        }
      },
      ExportNamedDeclaration: {
        enter(path) {
          let { node, parent } = path, declaration = path.get("declaration"), declarations;
          declaration.isVariableDeclaration() ? declarations = declaration.get("declarations").filter((d) => d.isVariableDeclarator()) : declaration.isFunctionDeclaration() && (declarations = [declaration]), declarations ? declarations.forEach((declPath) => {
            let decl = declPath.node, id = declPath.node.id;
            if (t3.isIdentifier(id)) {
              let { name: exportName } = id;
              if (exportName === "__namedExportsOrder" && declPath.isVariableDeclarator()) {
                self._namedExportsOrder = parseExportsOrder(declPath.node.init);
                return;
              }
              let storyNode;
              t3.isVariableDeclarator(decl) ? t3.isTSAsExpression(decl.init) && t3.isTSSatisfiesExpression(decl.init.expression) ? storyNode = decl.init.expression.expression : t3.isTSAsExpression(decl.init) || t3.isTSSatisfiesExpression(decl.init) ? storyNode = decl.init.expression : storyNode = decl.init : storyNode = decl;
              let storyIsFactory = !1;
              if (storyNode && isCsfFactoryCall(storyNode) && (storyIsFactory = !0, storyNode = storyNode.arguments[0]), self._metaIsFactory && !storyIsFactory)
                return;
              if (!self._metaIsFactory && storyIsFactory)
                throw self._metaNode ? new MixedFactoryError(
                  "expected non-factory story",
                  storyNode,
                  self._options.fileName
                ) : new BadMetaError(
                  "meta() factory must be imported from .storybook/preview configuration",
                  storyNode,
                  self._options.fileName
                );
              self._storyExports[exportName] = decl, self._storyDeclarationPath[exportName] = declPath, self._storyPaths[exportName] = path, self._storyStatements[exportName] = node;
              let name = storyNameFromExport(exportName);
              self._storyAnnotations[exportName] ? logger.warn(
                `Unexpected annotations for "${exportName}" before story declaration`
              ) : self._storyAnnotations[exportName] = {};
              let parameters = {};
              t3.isObjectExpression(storyNode) ? (parameters.__isArgsStory = !0, storyNode.properties.forEach((p) => {
                if (t3.isIdentifier(p.key)) {
                  let key = p.key.name;
                  if (t3.isObjectMethod(p))
                    self._storyAnnotations[exportName][key] = p;
                  else {
                    if (p.key.name === "render")
                      parameters.__isArgsStory = isArgsStory(
                        p.value,
                        parent,
                        self
                      );
                    else if (p.key.name === "name" && t3.isStringLiteral(p.value))
                      name = p.value.value;
                    else if (p.key.name === "storyName" && t3.isStringLiteral(p.value))
                      logger.warn(
                        `Unexpected usage of "storyName" in "${exportName}". Please use "name" instead.`
                      );
                    else if (p.key.name === "parameters" && t3.isObjectExpression(p.value)) {
                      let idProperty = p.value.properties.find(
                        (property) => t3.isObjectProperty(property) && t3.isIdentifier(property.key) && property.key.name === "__id"
                      );
                      idProperty && (parameters.__id = idProperty.value.value);
                    }
                    self._storyAnnotations[exportName][p.key.name] = p.value;
                  }
                }
              })) : parameters.__isArgsStory = isArgsStory(storyNode, parent, self), self._stories[exportName] = {
                id: "FIXME",
                name,
                parameters,
                __stats: {
                  factory: storyIsFactory
                }
              };
            }
          }) : node.specifiers.length > 0 && node.specifiers.forEach((specifier) => {
            if (t3.isExportSpecifier(specifier) && (t3.isIdentifier(specifier.exported) || t3.isStringLiteral(specifier.exported))) {
              let exportName = t3.isIdentifier(specifier.exported) ? specifier.exported.name : specifier.exported.value, { name: localName } = specifier.local, decl = t3.isProgram(parent) ? findVarInitialization(localName, parent) : specifier.local;
              if (exportName === "default") {
                let metaNode;
                t3.isObjectExpression(decl) ? metaNode = decl : /* export default { ... } as Meta<...> */ /* export default { ... } satisfies Meta<...> */ (t3.isTSAsExpression(decl) || t3.isTSSatisfiesExpression(decl)) && t3.isObjectExpression(decl.expression) ? metaNode = decl.expression : (
                  // export default { ... } satisfies Meta as Meta<...>
                  t3.isTSAsExpression(decl) && t3.isTSSatisfiesExpression(decl.expression) && t3.isObjectExpression(decl.expression.expression) && (metaNode = decl.expression.expression)
                ), metaNode && t3.isProgram(parent) && self._parseMeta(metaNode, parent);
              } else {
                let annotations = {}, storyNode = decl;
                t3.isObjectExpression(storyNode) && storyNode.properties.forEach((p) => {
                  t3.isIdentifier(p.key) && (annotations[p.key.name] = p.value);
                }), self._storyAnnotations[exportName] = annotations, self._storyStatements[exportName] = decl, self._storyPaths[exportName] = path, self._stories[exportName] = {
                  id: "FIXME",
                  name: exportName,
                  localName,
                  parameters: {},
                  __stats: {}
                };
              }
            }
          });
        }
      },
      ExpressionStatement: {
        enter({ node, parent }) {
          let { expression } = node;
          if (t3.isProgram(parent) && t3.isAssignmentExpression(expression) && t3.isMemberExpression(expression.left) && t3.isIdentifier(expression.left.object) && t3.isIdentifier(expression.left.property)) {
            let exportName = expression.left.object.name, annotationKey = expression.left.property.name, annotationValue = expression.right;
            if (self._storyAnnotations[exportName] && (annotationKey === "story" && t3.isObjectExpression(annotationValue) ? annotationValue.properties.forEach((prop) => {
              t3.isIdentifier(prop.key) && (self._storyAnnotations[exportName][prop.key.name] = prop.value);
            }) : self._storyAnnotations[exportName][annotationKey] = annotationValue), annotationKey === "storyName" && t3.isStringLiteral(annotationValue)) {
              let storyName = annotationValue.value, story = self._stories[exportName];
              if (!story)
                return;
              story.name = storyName;
            }
          }
          if (t3.isCallExpression(expression) && t3.isMemberExpression(expression.callee) && t3.isIdentifier(expression.callee.object) && t3.isIdentifier(expression.callee.property) && expression.callee.property.name === "test" && expression.arguments.length >= 2 && t3.isStringLiteral(expression.arguments[0])) {
            let exportName = expression.callee.object.name, testName = expression.arguments[0].value, testFunction = expression.arguments.length === 2 ? expression.arguments[1] : expression.arguments[2], testArguments = expression.arguments.length === 2 ? null : expression.arguments[1], tags = parseTestTags(testArguments, self._ast.program);
            self._tests.push({
              function: testFunction,
              name: testName,
              node: expression,
              // can't set id because meta title isn't available yet
              // so it's set later on
              id: "FIXME",
              tags,
              parent: { node: self._storyStatements[exportName] }
            }), self._stories[exportName].__stats.tests = !0;
          }
        }
      },
      CallExpression: {
        enter(path) {
          let { node } = path, { callee } = node;
          if (t3.isIdentifier(callee) && callee.name === "storiesOf")
            throw new Error(import_ts_dedent.dedent`
              Unexpected \`storiesOf\` usage: ${formatLocation(node, self._options.fileName)}.

              SB8 does not support \`storiesOf\`.
            `);
          if (t3.isMemberExpression(callee) && t3.isIdentifier(callee.property) && callee.property.name === "meta" && node.arguments.length > 0) {
            let rootObject = callee.object;
            if (t3.isCallExpression(rootObject) && t3.isMemberExpression(rootObject.callee) && (rootObject = rootObject.callee.object), t3.isIdentifier(rootObject)) {
              let configParent = path.scope.getBinding(rootObject.name)?.path?.parentPath?.node;
              if (t3.isImportDeclaration(configParent)) {
                if (isValidPreviewPath(configParent.source.value)) {
                  self._metaIsFactory = !0;
                  let metaDeclarator = path.findParent(
                    (p) => p.isVariableDeclarator()
                  );
                  self._metaVariableName = t3.isIdentifier(metaDeclarator.node.id) ? metaDeclarator.node.id.name : callee.property.name;
                  let metaNode = node.arguments[0];
                  self._parseMeta(metaNode, self._ast.program);
                } else if (rootObject.name === "preview")
                  throw new BadMetaError(
                    "meta() factory must be imported from .storybook/preview configuration",
                    configParent,
                    self._options.fileName
                  );
              }
            }
          }
        }
      },
      ImportDeclaration: {
        enter({ node }) {
          let { source } = node;
          if (t3.isStringLiteral(source))
            self.imports.push(source.value);
          else
            throw new Error("CSF: unexpected import source");
        }
      }
    }), !self._meta)
      throw new NoMetaError("missing default export", self._ast, self._options.fileName);
    let entries = Object.entries(self._stories);
    if (self._meta.title = this._options.makeTitle(self._meta?.title), self._metaAnnotations.play && (self._meta.tags = [...self._meta.tags || [], Tag.PLAY_FN]), self._stories = entries.reduce(
      (acc, [key, story]) => {
        if (!isExportStory(key, self._meta))
          return acc;
        let id = story.parameters?.__id ?? toId(self._meta?.id || self._meta?.title, storyNameFromExport(key)), parameters = { ...story.parameters, __id: id }, { includeStories } = self._meta || {};
        key === "__page" && (entries.length === 1 || Array.isArray(includeStories) && includeStories.length === 1) && (parameters.docsOnly = !0), acc[key] = { ...story, id, parameters };
        let storyAnnotations = self._storyAnnotations[key], { tags, play } = storyAnnotations;
        if (tags) {
          let node = t3.isIdentifier(tags) ? findVarInitialization(tags.name, this._ast.program) : tags;
          acc[key].tags = parseTags(node);
        }
        play && (acc[key].tags = [...acc[key].tags || [], Tag.PLAY_FN]);
        let stats = acc[key].__stats;
        ["play", "render", "loaders", "beforeEach", "globals", "tags"].forEach((annotation) => {
          stats[annotation] = !!storyAnnotations[annotation] || !!self._metaAnnotations[annotation];
        });
        let storyExport = self.getStoryExport(key);
        stats.storyFn = !!(t3.isArrowFunctionExpression(storyExport) || t3.isFunctionDeclaration(storyExport)), stats.mount = hasMount(storyAnnotations.play ?? self._metaAnnotations.play), stats.moduleMock = !!self.imports.find((fname) => isModuleMock(fname));
        let storyNode = self._storyStatements[key], storyTests = self._tests.filter((t7) => t7.parent.node === storyNode);
        return storyTests.length > 0 && (stats.tests = !0, storyTests.forEach((test) => {
          test.id = toTestId(id, test.name);
        })), acc;
      },
      {}
    ), Object.keys(self._storyExports).forEach((key) => {
      isExportStory(key, self._meta) || (delete self._storyExports[key], delete self._storyAnnotations[key], delete self._storyStatements[key]);
    }), self._namedExportsOrder) {
      let unsortedExports = Object.keys(self._storyExports);
      self._storyExports = sortExports(self._storyExports, self._namedExportsOrder), self._stories = sortExports(self._stories, self._namedExportsOrder);
      let sortedExports = Object.keys(self._storyExports);
      if (unsortedExports.length !== sortedExports.length)
        throw new Error(
          `Missing exports after sort: ${unsortedExports.filter(
            (key) => !sortedExports.includes(key)
          )}`
        );
    }
    return self;
  }
  get meta() {
    return this._meta;
  }
  get stories() {
    return Object.values(this._stories);
  }
  getStoryTests(story) {
    let storyNode = typeof story == "string" ? this._storyStatements[story] : story;
    return storyNode ? this._tests.filter((t7) => t7.parent.node === storyNode) : [];
  }
  get indexInputs() {
    let { fileName } = this._options;
    if (!fileName)
      throw new Error(
        import_ts_dedent.dedent`Cannot automatically create index inputs with CsfFile.indexInputs because the CsfFile instance was created without a the fileName option.
        Either add the fileName option when creating the CsfFile instance, or create the index inputs manually.`
      );
    let index = [];
    return Object.entries(this._stories).map(([exportName, story]) => {
      let tags = [...this._meta?.tags ?? [], ...story.tags ?? []], storyInput = {
        rawComponentPath: this._rawComponentPath,
        exportName,
        title: this.meta?.title,
        metaId: this.meta?.id,
        tags,
        __id: story.id,
        __stats: story.__stats
      }, tests = this.getStoryTests(exportName), hasTests = tests.length > 0;
      index.push({
        ...storyInput,
        type: "story",
        subtype: "story",
        name: story.name
      }), hasTests && tests.forEach((test) => {
        index.push({
          ...storyInput,
          // TODO implementent proper title => path behavior in `transformStoryIndexToStoriesHash`
          // title: `${storyInput.title}/${story.name}`,
          type: "story",
          subtype: "test",
          name: test.name,
          parent: story.id,
          parentName: story.name,
          tags: [
            ...storyInput.tags,
            // this tag comes before test tags so users can invert if they like
            `!${Tag.AUTODOCS}`,
            ...test.tags,
            // this tag comes after test tags so users can't change it
            Tag.TEST_FN
          ],
          __id: test.id
        });
      });
    }), index;
  }
}, babelParseFile = ({
  code,
  filename = "",
  ast
}) => new BabelFileClass(
  { filename, highlightCode: !1 },
  { code, ast: ast ?? babelParse(code) }
), loadCsf = (code, options) => {
  let ast = babelParse(code), file = babelParseFile({ code, filename: options.fileName, ast });
  return new CsfFile(ast, options, file);
}, formatCsf = (csf, options = { sourceMaps: !1 }, code) => {
  let result = generate(csf._ast, options, code);
  return options.sourceMaps ? result : result.code;
}, printCsf = (csf, options = {}) => recast.print(csf._ast, options), readCsf = async (fileName, options) => {
  let code = (await readFile(fileName, "utf-8")).toString();
  return loadCsf(code, { ...options, fileName });
}, writeCsf = async (csf, fileName) => {
  if (!(fileName || csf._options.fileName))
    throw new Error("Please specify a fileName for writeCsf");
  await writeFile(fileName, printCsf(csf).code);
};

// src/csf-tools/story-shape/imports.ts
import { types as t4 } from "storybook/internal/babel";
var isTypeSpecifier = (s) => t4.isImportSpecifier(s) && s.importKind === "type", importedName = (im) => t4.isIdentifier(im) ? im.name : im.value;
function collectImportBindings(program) {
  let localToImport = /* @__PURE__ */ new Map();
  for (let stmt of program.get("body")) {
    if (!stmt.isImportDeclaration())
      continue;
    let decl = stmt.node;
    if (decl.importKind !== "type")
      for (let s of decl.specifiers ?? []) {
        if (!("local" in s) || !s.local || isTypeSpecifier(s))
          continue;
        let importId = decl.source.value;
        t4.isImportDefaultSpecifier(s) ? localToImport.set(s.local.name, { importId, importName: "default" }) : t4.isImportNamespaceSpecifier(s) ? localToImport.set(s.local.name, { importId, importName: "*" }) : t4.isImportSpecifier(s) && localToImport.set(s.local.name, { importId, importName: importedName(s.imported) });
      }
  }
  return localToImport;
}

// src/csf-tools/story-shape/resolve-members.ts
import { generate as generate2, types as t5 } from "storybook/internal/babel";
var sourceOf = (node) => generate2(node, { concise: !0, comments: !1 }).code, complete = (properties = {}) => ({
  properties,
  shadowed: [],
  unresolved: []
}), resolveObjectMembers = (object, ctx) => membersOf(object, ctx, /* @__PURE__ */ new Set()), resolveArgsRecord = (node, ctx) => {
  if (node === void 0)
    return complete();
  let unwrapped = unwrapExpression(node);
  if (t5.isObjectExpression(unwrapped))
    return asArgsRecord(membersOf(unwrapped, ctx, /* @__PURE__ */ new Set()));
  let referenced = resolveReference(ctx, unwrapped, node.start ?? void 0, /* @__PURE__ */ new Set());
  return referenced ? asArgsRecord(referenced) : { properties: {}, shadowed: [], unresolved: [`args: ${sourceOf(unwrapped)}`] };
}, asArgsRecord = (members) => {
  let methods = Object.entries(members.properties).filter(([, node]) => t5.isObjectMethod(node));
  if (methods.length === 0)
    return members;
  let properties = { ...members.properties }, unresolved = [...members.unresolved];
  for (let [key, node] of methods)
    delete properties[key], unresolved.push(sourceOf(node));
  return {
    properties,
    shadowed: members.shadowed.filter((key) => key in properties),
    unresolved
  };
}, resolveBindingMembers = (ctx, name) => {
  let bound = bindingMembers(ctx, name, void 0, /* @__PURE__ */ new Set());
  return bound === void 0 || bound.kind === "namespace" ? void 0 : bound.members;
}, resolveReferencedValue = (ctx, expression) => {
  let chain = memberChain(expression);
  if (!chain || chain.path.length === 0)
    return;
  let visited = /* @__PURE__ */ new Set(), located = locate(ctx, chain, void 0, visited);
  if (!located || located.path.length === 0)
    return;
  let members = located.members, scope = located.ctx;
  for (let [index, key] of located.path.entries()) {
    if (members.shadowed.includes(key))
      return;
    let value = members.properties[key];
    if (value === void 0)
      return;
    if (index === located.path.length - 1)
      return { node: value, ctx: scope };
    let unwrapped = unwrapExpression(value);
    if (!t5.isObjectExpression(unwrapped))
      return;
    members = membersOf(unwrapped, scope, visited);
  }
}, membersOf = (object, ctx, visited) => {
  let properties = {}, unresolved = [], shadowed = /* @__PURE__ */ new Set(), shadowKnownMembers = (source) => {
    unresolved.push(source);
    for (let key of Object.keys(properties))
      shadowed.add(key);
  };
  for (let property of object.properties) {
    if (t5.isSpreadElement(property)) {
      let spread = spreadMembers(ctx, property, visited);
      if (spread === void 0 || spread.unresolved.length > 0) {
        shadowKnownMembers(sourceOf(property));
        continue;
      }
      for (let [key2, value] of Object.entries(spread.properties))
        properties[key2] = value, shadowed.delete(key2);
      continue;
    }
    let key = keyOf(property);
    if (key === null) {
      shadowKnownMembers(sourceOf(property));
      continue;
    }
    if (t5.isObjectMethod(property) && (property.kind !== "method" || property.generator)) {
      delete properties[key], shadowed.delete(key), unresolved.push(sourceOf(property));
      continue;
    }
    properties[key] = t5.isObjectMethod(property) ? property : property.value, shadowed.delete(key);
  }
  return { properties, shadowed: [...shadowed], unresolved };
}, spreadMembers = (ctx, spread, visited) => {
  let argument = unwrapExpression(spread.argument);
  return t5.isObjectExpression(argument) ? membersOf(argument, ctx, visited) : resolveReference(ctx, argument, spread.start ?? void 0, visited);
}, memberChain = (node) => {
  let path = [], current = unwrapExpression(node);
  for (; t5.isMemberExpression(current); ) {
    let key = t5.isIdentifier(current.property) && !current.computed ? current.property.name : t5.isStringLiteral(current.property) ? current.property.value : void 0;
    if (key === void 0)
      return;
    path.unshift(key), current = unwrapExpression(current.object);
  }
  return t5.isIdentifier(current) ? { root: current.name, path } : void 0;
}, resolveReference = (ctx, expression, position, visited) => {
  let chain = memberChain(expression);
  if (!chain)
    return;
  let key = `ref:${ctx.filePath}#${chain.root}.${chain.path.join(".")}`;
  if (!visited.has(key)) {
    visited.add(key);
    try {
      return unguardedResolveReference(ctx, chain, position, visited);
    } finally {
      visited.delete(key);
    }
  }
}, unguardedResolveReference = (ctx, chain, position, visited) => {
  let located = locate(ctx, chain, position, visited);
  if (!located)
    return;
  let members = located.members, scope = located.ctx;
  for (let [index, key] of located.path.entries()) {
    if (members.unresolved.length > 0)
      return;
    let value = members.properties[key];
    if (value === void 0)
      return index === located.path.length - 1 ? complete() : void 0;
    let unwrapped = unwrapExpression(value);
    if (!t5.isObjectExpression(unwrapped))
      return;
    members = membersOf(unwrapped, scope, visited);
  }
  return located.external ? externalized(members, scope) : members;
}, locate = (ctx, chain, position, visited) => {
  let binding = bindingMembers(ctx, chain.root, position, visited);
  if (!binding)
    return;
  if (binding.kind === "namespace") {
    let [exportName, ...path] = chain.path;
    if (exportName === void 0)
      return;
    let exported = bindingMembers(binding.ctx, exportName, void 0, visited);
    if (exported === void 0 || exported.kind === "namespace")
      return;
    let located2 = withAccessor(exported, path);
    return located2 === void 0 ? void 0 : { ...located2, external: !0 };
  }
  let located = withAccessor(binding, chain.path);
  return located === void 0 ? void 0 : { ...located, external: binding.external };
}, withAccessor = (binding, path) => binding.accessor === void 0 ? { members: binding.members, ctx: binding.ctx, path } : path[0] === binding.accessor ? { members: binding.members, ctx: binding.ctx, path: path.slice(1) } : void 0, externalized = (members, ctx) => {
  if (!ctx.externalize)
    return members;
  let properties = {};
  for (let [key, node] of Object.entries(members.properties)) {
    let value = ctx.externalize(node);
    if (value === void 0)
      return;
    properties[key] = value;
  }
  return {
    properties,
    shadowed: members.shadowed,
    unresolved: members.unresolved
  };
}, bindingMembers = (ctx, name, position, visited) => {
  let key = `${ctx.filePath}#${name}`;
  if (!visited.has(key)) {
    visited.add(key);
    try {
      return unguardedBindingMembers(ctx, name, position, visited);
    } finally {
      visited.delete(key);
    }
  }
}, unguardedBindingMembers = (ctx, name, position, visited) => {
  let binding = ctx.program.scope.getBinding(name);
  if (!binding)
    return;
  if (binding.kind === "module")
    return importedBinding(ctx, binding.path, visited);
  if (!binding.constant)
    return;
  let declared = declaredBindingMembers(ctx, binding.path.node, position, visited);
  if (declared === void 0)
    return;
  let assigned = assignedMembers(ctx, name, position);
  return {
    kind: "members",
    ctx,
    external: !1,
    ...declared.accessor ? { accessor: declared.accessor } : {},
    members: {
      properties: { ...declared.members.properties, ...assigned.properties },
      shadowed: declared.members.shadowed.filter((key) => !(key in assigned.properties)),
      unresolved: [...declared.members.unresolved, ...assigned.unresolved]
    }
  };
}, declaredBindingMembers = (ctx, node, position, visited) => {
  if (t5.isFunctionDeclaration(node))
    return { members: complete() };
  if (t5.isVariableDeclarator(node) && !(position !== void 0 && (node.start ?? Number.POSITIVE_INFINITY) > position))
    return node.init ? declaredMembers(ctx, node.init, position, visited) : { members: complete() };
}, declaredMembers = (ctx, init, position, visited) => {
  let unwrapped = unwrapExpression(init);
  if (t5.isObjectExpression(unwrapped))
    return { members: membersOf(unwrapped, ctx, visited) };
  let factory = factoryCall(unwrapped);
  if (factory === void 0 && (t5.isFunction(unwrapped) || isCanonicalCsf2BindCall(unwrapped)))
    return { members: complete() };
  if (factory === void 0)
    return {
      members: { properties: {}, shadowed: [], unresolved: [sourceOf(unwrapped)] }
    };
  let config = factory.config ? membersOf(factory.config, ctx, visited) : complete();
  if (factory.method === "story")
    return { members: config, accessor: "input" };
  let parent = bindingMembers(ctx, factory.parent, position, visited);
  return parent === void 0 || parent.kind === "namespace" || parent.accessor !== "input" || parent.external ? void 0 : {
    members: {
      properties: mergedAnnotations(parent.members, config).properties,
      shadowed: [
        ...parent.members.shadowed.filter((key) => !(key in config.properties)),
        ...config.shadowed
      ],
      unresolved: [...parent.members.unresolved, ...config.unresolved]
    },
    accessor: "input"
  };
}, MERGED_ANNOTATIONS = ["args", "argTypes", "parameters", "globals"], mergedAnnotations = (parent, child) => {
  let properties = { ...parent.properties, ...child.properties };
  for (let key of MERGED_ANNOTATIONS) {
    let from = parent.properties[key], over = child.properties[key];
    from === void 0 || over === void 0 || !t5.isExpression(from) || !t5.isExpression(over) || (properties[key] = t5.objectExpression([t5.spreadElement(from), t5.spreadElement(over)]));
  }
  return { properties };
}, factoryCall = (node) => {
  if (!isCsfFactoryCall(node))
    return;
  let method = node.callee.property.name;
  if (method !== "story" && method !== "extend")
    return;
  let [argument] = node.arguments, config = argument && unwrapExpression(argument);
  if (!(argument !== void 0 && (config === void 0 || !t5.isObjectExpression(config))))
    return {
      method,
      parent: node.callee.object.name,
      ...config && t5.isObjectExpression(config) ? { config } : {}
    };
}, assignedMembers = (ctx, name, position) => {
  let properties = {}, unresolved = [];
  for (let statement of ctx.program.node.body) {
    if (!t5.isExpressionStatement(statement) || !t5.isAssignmentExpression(statement.expression))
      continue;
    let assignment = statement.expression, target = assignment.left, depth = 0, outermost;
    for (; t5.isMemberExpression(target); )
      depth += 1, outermost = t5.isIdentifier(target.property) && !target.computed ? target.property.name : t5.isStringLiteral(target.property) ? target.property.value : void 0, target = target.object;
    if (!(depth === 0 || !t5.isIdentifier(target) || target.name !== name) && !(position !== void 0 && (assignment.start ?? 0) > position)) {
      if (depth > 1 || outermost === void 0 || assignment.operator !== "=") {
        unresolved.push(sourceOf(assignment));
        continue;
      }
      properties[outermost] = assignment.right;
    }
  }
  return { properties, unresolved };
}, importedBinding = (ctx, specifierPath, visited) => {
  let specifier = specifierPath.node, declaration = specifierPath.parent;
  if (!t5.isImportDeclaration(declaration) || declaration.importKind === "type" || !(t5.isImportSpecifier(specifier) || t5.isImportDefaultSpecifier(specifier) || t5.isImportNamespaceSpecifier(specifier)) || isTypeSpecifier(specifier))
    return;
  let target = resolveTargetModule(ctx, declaration.source.value);
  if (!target)
    return;
  if (t5.isImportNamespaceSpecifier(specifier))
    return { kind: "namespace", ctx: target };
  let exportName = t5.isImportDefaultSpecifier(specifier) ? "default" : importedName(specifier.imported);
  return exportedBinding(target, exportName, visited);
}, resolveTargetModule = (ctx, specifier) => {
  let target = ctx.resolveModule?.(ctx.filePath, specifier);
  return target ? { ...ctx, ...target } : void 0;
}, exportedBinding = (ctx, exportName, visited) => {
  let asExternal = (bound) => bound === void 0 || bound.kind === "namespace" ? bound : { ...bound, external: !0 };
  for (let statement of ctx.program.node.body) {
    if (t5.isExportDefaultDeclaration(statement) && exportName === "default") {
      let declaration = unwrapExpression(statement.declaration);
      return t5.isIdentifier(declaration) ? asExternal(bindingMembers(ctx, declaration.name, void 0, visited)) : t5.isObjectExpression(declaration) ? {
        kind: "members",
        ctx,
        external: !0,
        members: membersOf(declaration, ctx, visited)
      } : void 0;
    }
    if (!t5.isExportNamedDeclaration(statement) || statement.exportKind === "type")
      continue;
    let specifier = statement.specifiers.find(
      (candidate) => t5.isExportSpecifier(candidate) && candidate.exportKind !== "type" && importedName(candidate.exported) === exportName
    );
    if (!specifier)
      continue;
    if (!statement.source)
      return asExternal(bindingMembers(ctx, specifier.local.name, void 0, visited));
    let target = resolveTargetModule(ctx, statement.source.value);
    return target ? exportedBinding(target, specifier.local.name, visited) : void 0;
  }
  return exportName === "default" ? void 0 : asExternal(bindingMembers(ctx, exportName, void 0, visited));
};

// src/csf-tools/story-shape/resolve-arg-value.ts
import { traverse as traverse2, types as t6 } from "storybook/internal/babel";
var resolveArgValue = (node, ctx) => {
  let unresolved = [], resolved = inlineSpreads(
    followValue(unwrapExpression(node), ctx, /* @__PURE__ */ new Set()),
    ctx,
    unresolved
  ), bindings = importBindingsOf(ctx.program), imports = [];
  for (let name of freeNames(resolved)) {
    let imported = bindings.get(name);
    if (imported) {
      imports.push({
        localImportName: name,
        importId: imported.importId,
        importName: imported.importName,
        ...imported.importName === "*" ? { namespace: name } : {}
      });
      continue;
    }
    ctx.program.scope.getBinding(name) && unresolved.push(name);
  }
  return { node: resolved, imports, unresolved };
}, isSelfContained = (node) => freeNames(node).size === 0, importBindings = /* @__PURE__ */ new WeakMap(), importBindingsOf = (program) => {
  let bindings = importBindings.get(program.node);
  return bindings === void 0 && (bindings = collectImportBindings(program), importBindings.set(program.node, bindings)), bindings;
}, inlineSpreads = (node, ctx, unresolved) => {
  if (!hasNamedSpread(node))
    return node;
  if (t6.isArrayExpression(node))
    return t6.arrayExpression(
      node.elements.map(
        (element) => element && t6.isExpression(element) ? inlineSpreads(element, ctx, unresolved) : element
      )
    );
  if (!t6.isObjectExpression(node))
    return node;
  if (!node.properties.some((property) => t6.isSpreadElement(property)))
    return objectFrom(node.properties, ctx, unresolved) ?? node;
  let members = resolveArgsRecord(node, ctx);
  return members.unresolved.length > 0 ? (unresolved.push(...members.unresolved), node) : objectFrom(
    Object.entries(members.properties).map(
      ([key, value]) => t6.objectProperty(
        t6.isValidIdentifier(key) ? t6.identifier(key) : t6.stringLiteral(key),
        value
      )
    ),
    ctx,
    unresolved
  ) ?? node;
}, hasNamedSpread = (node) => t6.isArrayExpression(node) ? node.elements.some(
  (element) => element !== null && t6.isExpression(element) && hasNamedSpread(element)
) : t6.isObjectExpression(node) && node.properties.some(
  (property) => t6.isSpreadElement(property) ? !t6.isObjectExpression(unwrapExpression(property.argument)) : t6.isObjectProperty(property) && t6.isExpression(property.value) && hasNamedSpread(property.value)
), objectFrom = (properties, ctx, unresolved) => {
  let rebuilt = [];
  for (let property of properties) {
    if (!t6.isObjectProperty(property) || !t6.isExpression(property.value))
      return;
    let value = inlineSpreads(property.value, ctx, unresolved);
    rebuilt.push(
      t6.objectProperty(
        property.key,
        value,
        property.computed,
        property.shorthand && value === property.value
      )
    );
  }
  return t6.objectExpression(rebuilt);
}, followValue = (node, ctx, seen) => {
  if (!t6.isIdentifier(node) || seen.has(node.name))
    return node;
  let binding = ctx.program.scope.getBinding(node.name);
  return !binding || binding.kind === "module" || !binding.constant || !t6.isVariableDeclarator(binding.path.node) || !binding.path.node.init ? node : (seen.add(node.name), followValue(unwrapExpression(binding.path.node.init), ctx, seen));
}, freeNames = (node) => {
  let expression = t6.isExpression(node) ? node : t6.isObjectMethod(node) ? t6.objectExpression([node]) : void 0;
  if (expression === void 0)
    throw new Error(`Cannot read the names a ${node.type} depends on: it is not an expression`);
  let wrapped = t6.file(
    t6.program([t6.expressionStatement(t6.cloneNode(expression, !0))])
  ), names = /* @__PURE__ */ new Set();
  return traverse2(wrapped, {
    ReferencedIdentifier(path) {
      path.scope.hasBinding(path.node.name) || names.add(path.node.name);
    }
  }), names;
};

// src/csf-tools/story-shape/reference-context.ts
import { readFileSync } from "node:fs";
function createStoryReferenceResolver(options = {}) {
  let resolver = createModuleResolver({
    extensions: [...options.extensions ?? [], ...jsTsSourceExtensions],
    mainFields: ["module", "main"],
    tsconfig: "auto"
  });
  return function() {
    let parsed = /* @__PURE__ */ new Map();
    return {
      externalize: options.externalize ?? selfContained,
      resolveModule: (fromFile, specifier) => {
        let filePath;
        try {
          filePath = resolver.resolveFileSync(fromFile, specifier);
        } catch {
          return;
        }
        return parsed.has(filePath) || parsed.set(filePath, parseReferenceModule(filePath)), parsed.get(filePath);
      }
    };
  };
}
var parseReferenceModule = (filePath) => {
  try {
    let code = readFileSync(filePath, "utf8");
    return { program: babelParseFile({ code, filename: filePath }).path, filePath };
  } catch {
    return;
  }
}, selfContained = (node) => isSelfContained(node) ? node : void 0;

export {
  Tag,
  defaultResolveConditionNames,
  createModuleResolver,
  findVarInitialization,
  unwrapExpression,
  isCanonicalCsf2BindCall,
  isCsfFactoryCall,
  keyOf,
  propertyValue,
  returnedExpression,
  returnedExpressionPath,
  resolveReturnedObjectExpression,
  resolveIdentifierInit,
  pathForNode,
  metaObjectPath,
  isValidPreviewPath,
  isModuleMock,
  NoMetaError,
  MultipleMetaError,
  MixedFactoryError,
  BadMetaError,
  CsfFile,
  babelParseFile,
  loadCsf,
  formatCsf,
  printCsf,
  readCsf,
  writeCsf,
  isTypeSpecifier,
  importedName,
  collectImportBindings,
  sourceOf,
  resolveObjectMembers,
  resolveArgsRecord,
  resolveBindingMembers,
  resolveReferencedValue,
  resolveArgValue,
  isSelfContained,
  createStoryReferenceResolver,
  parseReferenceModule
};