UNPKG

storybook

Version:

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

2,970 lines • 127 kB
import {
  isTestEnvironment,
  pauseAnimations,
  waitForAnimations
} from "./chunk-IPA5A322.js";
import {
  require_main
} from "./chunk-3OXGAGBE.js";
import {
  SNIPPET_RENDERED,
  combineParameters
} from "./chunk-VYJQ7RU5.js";
import {
  isEqual
} from "./chunk-3IAH5M2U.js";
import {
  invariant
} from "./chunk-AS2HQEYC.js";
import {
  require_ansi_to_html
} from "./chunk-YKE5S47A.js";
import {
  mapValues,
  pickBy
} from "./chunk-AIOS4NGK.js";
import {
  isPlainObject
} from "./chunk-GFLS4VP3.js";
import {
  require_memoizerific
} from "./chunk-WJYERY3R.js";
import {
  dedent
} from "./chunk-JP7NCOJX.js";
import {
  __toESM
} from "./chunk-A242L54C.js";

// src/preview-api/modules/addons/main.ts
import { global } from "@storybook/global";

// src/preview-api/modules/addons/storybook-channel-mock.ts
import { Channel } from "storybook/internal/channels";
function mockChannel() {
  let transport = {
    setHandler: () => {
    },
    send: () => {
    }
  };
  return new Channel({ transport });
}

// src/preview-api/modules/addons/main.ts
var AddonStore = class {
  constructor() {
    this.getChannel = () => {
      if (!this.channel) {
        let channel = mockChannel();
        return this.setChannel(channel), channel;
      }
      return this.channel;
    };
    this.ready = () => this.promise;
    this.hasChannel = () => !!this.channel;
    this.setChannel = (channel) => {
      this.channel = channel, this.resolve();
    };
    this.promise = new Promise((res) => {
      this.resolve = () => res(this.getChannel());
    });
  }
}, KEY = "__STORYBOOK_ADDONS_PREVIEW";
function getAddonsStore() {
  return global[KEY] || (global[KEY] = new AddonStore()), global[KEY];
}
var addons = getAddonsStore();

// src/preview-api/modules/addons/hooks.ts
import { logger } from "storybook/internal/client-logger";
import {
  FORCE_RE_RENDER,
  RESET_STORY_ARGS,
  STORY_RENDERED,
  UPDATE_GLOBALS,
  UPDATE_STORY_ARGS
} from "storybook/internal/core-events";
import { global as global2 } from "@storybook/global";
var HooksContext = class {
  constructor() {
    this.hookListsMap = void 0;
    this.mountedDecorators = void 0;
    this.prevMountedDecorators = void 0;
    this.currentHooks = void 0;
    this.nextHookIndex = void 0;
    this.currentPhase = void 0;
    this.currentEffects = void 0;
    this.prevEffects = void 0;
    this.currentDecoratorName = void 0;
    this.hasUpdates = void 0;
    this.currentContext = void 0;
    this.renderListener = (storyId) => {
      storyId === this.currentContext?.id && (this.triggerEffects(), this.currentContext = null, this.removeRenderListeners());
    };
    this.init();
  }
  init() {
    this.hookListsMap = /* @__PURE__ */ new WeakMap(), this.mountedDecorators = /* @__PURE__ */ new Set(), this.prevMountedDecorators = /* @__PURE__ */ new Set(), this.currentHooks = [], this.nextHookIndex = 0, this.currentPhase = "NONE", this.currentEffects = [], this.prevEffects = [], this.currentDecoratorName = null, this.hasUpdates = !1, this.currentContext = null;
  }
  clean() {
    this.prevEffects.forEach((effect) => {
      effect.destroy && effect.destroy();
    }), this.init(), this.removeRenderListeners();
  }
  getNextHook() {
    let hook = this.currentHooks[this.nextHookIndex];
    return this.nextHookIndex += 1, hook;
  }
  triggerEffects() {
    this.prevEffects.forEach((effect) => {
      !this.currentEffects.includes(effect) && effect.destroy && effect.destroy();
    }), this.currentEffects.forEach((effect) => {
      this.prevEffects.includes(effect) || (effect.destroy = effect.create());
    }), this.prevEffects = this.currentEffects, this.currentEffects = [];
  }
  addRenderListeners() {
    this.removeRenderListeners(), addons.getChannel().on(STORY_RENDERED, this.renderListener);
  }
  removeRenderListeners() {
    addons.getChannel().removeListener(STORY_RENDERED, this.renderListener);
  }
};
function hookify(fn) {
  let hookified = (...args) => {
    let { hooks } = typeof args[0] == "function" ? args[1] : args[0], prevPhase = hooks.currentPhase, prevHooks = hooks.currentHooks, prevNextHookIndex = hooks.nextHookIndex, prevDecoratorName = hooks.currentDecoratorName;
    hooks.currentDecoratorName = fn.name, hooks.prevMountedDecorators.has(fn) ? (hooks.currentPhase = "UPDATE", hooks.currentHooks = hooks.hookListsMap.get(fn) || []) : (hooks.currentPhase = "MOUNT", hooks.currentHooks = [], hooks.hookListsMap.set(fn, hooks.currentHooks), hooks.prevMountedDecorators.add(fn)), hooks.nextHookIndex = 0;
    let prevContext = global2.STORYBOOK_HOOKS_CONTEXT;
    global2.STORYBOOK_HOOKS_CONTEXT = hooks;
    let result = fn(...args);
    if (global2.STORYBOOK_HOOKS_CONTEXT = prevContext, hooks.currentPhase === "UPDATE" && hooks.getNextHook() != null)
      throw new Error(
        "Rendered fewer hooks than expected. This may be caused by an accidental early return statement."
      );
    return hooks.currentPhase = prevPhase, hooks.currentHooks = prevHooks, hooks.nextHookIndex = prevNextHookIndex, hooks.currentDecoratorName = prevDecoratorName, result;
  };
  return hookified.originalFn = fn, hookified;
}
var numberOfRenders = 0, RENDER_LIMIT = 25, applyHooks = (applyDecorators) => (storyFn, decorators) => {
  let decorated = applyDecorators(
    hookify(storyFn),
    decorators.map((decorator) => hookify(decorator))
  );
  return (context) => {
    let { hooks } = context;
    hooks.prevMountedDecorators ??= /* @__PURE__ */ new Set(), hooks.mountedDecorators = /* @__PURE__ */ new Set([storyFn, ...decorators]), hooks.currentContext = context, hooks.hasUpdates = !1;
    let result = decorated(context);
    for (numberOfRenders = 1; hooks.hasUpdates; )
      if (hooks.hasUpdates = !1, hooks.currentEffects = [], result = decorated(context), numberOfRenders += 1, numberOfRenders > RENDER_LIMIT)
        throw new Error(
          "Too many re-renders. Storybook limits the number of renders to prevent an infinite loop."
        );
    return hooks.addRenderListeners(), result;
  };
}, areDepsEqual = (deps, nextDeps) => deps.length === nextDeps.length && deps.every((dep, i) => dep === nextDeps[i]), invalidHooksError = () => new Error("Storybook preview hooks can only be called inside decorators and story functions.");
function getHooksContextOrNull() {
  return global2.STORYBOOK_HOOKS_CONTEXT || null;
}
function getHooksContextOrThrow() {
  let hooks = getHooksContextOrNull();
  if (hooks == null)
    throw invalidHooksError();
  return hooks;
}
function useHook(name, callback, deps) {
  let hooks = getHooksContextOrThrow();
  if (hooks.currentPhase === "MOUNT") {
    deps != null && !Array.isArray(deps) && logger.warn(
      `${name} received a final argument that is not an array (instead, received ${deps}). When specified, the final argument must be an array.`
    );
    let hook = { name, deps };
    return hooks.currentHooks.push(hook), callback(hook), hook;
  }
  if (hooks.currentPhase === "UPDATE") {
    let hook = hooks.getNextHook();
    if (hook == null)
      throw new Error("Rendered more hooks than during the previous render.");
    return hook.name !== name && logger.warn(
      `Storybook has detected a change in the order of Hooks${hooks.currentDecoratorName ? ` called by ${hooks.currentDecoratorName}` : ""}. This will lead to bugs and errors if not fixed.`
    ), deps != null && hook.deps == null && logger.warn(
      `${name} received a final argument during this render, but not during the previous render. Even though the final argument is optional, its type cannot change between renders.`
    ), deps != null && hook.deps != null && deps.length !== hook.deps.length && logger.warn(`The final argument passed to ${name} changed size between renders. The order and size of this array must remain constant.
Previous: ${hook.deps}
Incoming: ${deps}`), (deps == null || hook.deps == null || !areDepsEqual(deps, hook.deps)) && (callback(hook), hook.deps = deps), hook;
  }
  throw invalidHooksError();
}
function useMemoLike(name, nextCreate, deps) {
  let { memoizedState } = useHook(
    name,
    (hook) => {
      hook.memoizedState = nextCreate();
    },
    deps
  );
  return memoizedState;
}
function useMemo(nextCreate, deps) {
  return useMemoLike("useMemo", nextCreate, deps);
}
function useCallback(callback, deps) {
  return useMemoLike("useCallback", () => callback, deps);
}
function useRefLike(name, initialValue) {
  return useMemoLike(name, () => ({ current: initialValue }), []);
}
function useRef(initialValue) {
  return useRefLike("useRef", initialValue);
}
function triggerUpdate() {
  let hooks = getHooksContextOrNull();
  if (hooks != null && hooks.currentPhase !== "NONE")
    hooks.hasUpdates = !0;
  else
    try {
      addons.getChannel().emit(FORCE_RE_RENDER);
    } catch {
      logger.warn("State updates of Storybook preview hooks work only in browser");
    }
}
function useStateLike(name, initialState) {
  let stateRef = useRefLike(
    name,
    // @ts-expect-error S type should never be function, but there's no way to tell that to TypeScript
    typeof initialState == "function" ? initialState() : initialState
  ), setState = (update) => {
    stateRef.current = typeof update == "function" ? update(stateRef.current) : update, triggerUpdate();
  };
  return [stateRef.current, setState];
}
function useState(initialState) {
  return useStateLike("useState", initialState);
}
function useReducer(reducer, initialArg, init) {
  let initialState = init != null ? () => init(initialArg) : initialArg, [state, setState] = useStateLike("useReducer", initialState);
  return [state, (action) => setState((prevState) => reducer(prevState, action))];
}
function useEffect(create, deps) {
  let hooks = getHooksContextOrThrow(), effect = useMemoLike("useEffect", () => ({ create }), deps);
  hooks.currentEffects.includes(effect) || hooks.currentEffects.push(effect);
}
function useChannel(eventMap, deps = []) {
  let channel = addons.getChannel();
  return useEffect(() => (Object.entries(eventMap).forEach(([type, listener]) => channel.on(type, listener)), () => {
    Object.entries(eventMap).forEach(
      ([type, listener]) => channel.removeListener(type, listener)
    );
  }), [...Object.keys(eventMap), ...deps]), useCallback(channel.emit.bind(channel), [channel]);
}
function useStoryContext() {
  let { currentContext } = getHooksContextOrThrow();
  if (currentContext == null)
    throw invalidHooksError();
  return currentContext;
}
function useParameter(parameterKey, defaultValue) {
  let { parameters } = useStoryContext();
  if (parameterKey)
    return parameters[parameterKey] ?? defaultValue;
}
function useArgs() {
  let channel = addons.getChannel(), { id: storyId, args } = useStoryContext(), updateArgs = useCallback(
    (updatedArgs) => channel.emit(UPDATE_STORY_ARGS, { storyId, updatedArgs }),
    [channel, storyId]
  ), resetArgs = useCallback(
    (argNames) => channel.emit(RESET_STORY_ARGS, { storyId, argNames }),
    [channel, storyId]
  );
  return [args, updateArgs, resetArgs];
}
function useGlobals() {
  let channel = addons.getChannel(), { globals } = useStoryContext(), updateGlobals = useCallback(
    (newGlobals) => channel.emit(UPDATE_GLOBALS, { globals: newGlobals }),
    [channel]
  );
  return [globals, updateGlobals];
}

// src/preview-api/modules/addons/make-decorator.ts
var makeDecorator = ({
  name,
  parameterName,
  wrapper,
  skipIfNoParametersOrOptions = !1
}) => {
  let decorator = (options) => (storyFn, context) => {
    let parameters = context.parameters && context.parameters[parameterName];
    return parameters && parameters.disable || skipIfNoParametersOrOptions && !options && !parameters ? storyFn(context) : wrapper(storyFn, context, {
      options,
      parameters
    });
  };
  return (...args) => typeof args[0] == "function" ? decorator()(...args) : (...innerArgs) => {
    if (innerArgs.length > 1)
      return args.length > 1 ? decorator(args)(...innerArgs) : decorator(...args)(...innerArgs);
    throw new Error(
      `Passing stories directly into ${name}() is not allowed,
        instead use addDecorator(${name}) and pass options with the '${parameterName}' parameter`
    );
  };
};

// src/preview-api/modules/store/StoryStore.ts
import { getCoreAnnotations as getCoreAnnotations2 } from "storybook/internal/csf";
import {
  CalledExtractOnStoreError,
  MissingStoryFromCsfFileError
} from "storybook/internal/preview-errors";
var import_memoizerific2 = __toESM(require_memoizerific(), 1);

// src/preview-api/modules/store/args.ts
import { once } from "storybook/internal/client-logger";
var INCOMPATIBLE = Symbol("incompatible"), map = (arg, argType) => {
  let type = argType.type;
  if (arg == null || !type || argType.mapping)
    return arg;
  switch (type.name) {
    case "string":
      return String(arg);
    case "enum":
      return arg;
    case "number":
      return Number(arg);
    case "boolean":
      return String(arg) === "true";
    case "array":
      return !type.value || !Array.isArray(arg) ? INCOMPATIBLE : arg.reduce((acc, item, index) => {
        let mapped = map(item, { type: type.value });
        return mapped !== INCOMPATIBLE && (acc[index] = mapped), acc;
      }, new Array(arg.length));
    case "object":
      return typeof arg == "string" || typeof arg == "number" ? arg : !type.value || typeof arg != "object" ? INCOMPATIBLE : Object.entries(arg).reduce((acc, [key, val]) => {
        let mapped = map(val, { type: type.value[key] });
        return mapped === INCOMPATIBLE ? acc : Object.assign(acc, { [key]: mapped });
      }, {});
    case "other": {
      let isPrimitiveArg = typeof arg == "string" || typeof arg == "number" || typeof arg == "boolean";
      return type.value === "ReactNode" && isPrimitiveArg ? arg : INCOMPATIBLE;
    }
    default:
      return INCOMPATIBLE;
  }
}, mapArgsToTypes = (args, argTypes) => Object.entries(args).reduce((acc, [key, value]) => {
  if (!argTypes[key])
    return acc;
  let mapped = map(value, argTypes[key]);
  return mapped === INCOMPATIBLE ? acc : Object.assign(acc, { [key]: mapped });
}, {}), combineArgs = (value, update) => Array.isArray(value) && Array.isArray(update) ? update.reduce(
  (acc, upd, index) => (acc[index] = combineArgs(value[index], update[index]), acc),
  [...value]
).filter((v) => v !== void 0) : !isPlainObject(value) || !isPlainObject(update) ? update : Object.keys({ ...value, ...update }).reduce((acc, key) => {
  if (key in update) {
    let combined = combineArgs(value[key], update[key]);
    combined !== void 0 && (acc[key] = combined);
  } else
    acc[key] = value[key];
  return acc;
}, {}), validateOptions = (args, argTypes) => Object.entries(argTypes).reduce((acc, [key, { options }]) => {
  function allowArg() {
    return key in args && (acc[key] = args[key]), acc;
  }
  if (!options)
    return allowArg();
  if (!Array.isArray(options))
    return once.error(dedent`
        Invalid argType: '${key}.options' should be an array.

        More info: https://storybook.js.org/docs/api/arg-types?ref=error
      `), allowArg();
  if (options.some((opt) => opt && ["object", "function"].includes(typeof opt)))
    return once.error(dedent`
        Invalid argType: '${key}.options' should only contain primitives. Use a 'mapping' for complex values.

        More info: https://storybook.js.org/docs/writing-stories/args?ref=error#mapping-to-complex-arg-values
      `), allowArg();
  let isArray = Array.isArray(args[key]), invalidIndex = isArray && args[key].findIndex((val) => !options.includes(val)), isValidArray = isArray && invalidIndex === -1;
  if (args[key] === void 0 || options.includes(args[key]) || isValidArray)
    return allowArg();
  let field = isArray ? `${key}[${invalidIndex}]` : key, supportedOptions = options.map((opt) => typeof opt == "string" ? `'${opt}'` : String(opt)).join(", ");
  return once.warn(`Received illegal value for '${field}'. Supported options: ${supportedOptions}`), acc;
}, {}), DEEPLY_EQUAL = Symbol("Deeply equal"), deepDiff = (value, update) => {
  if (typeof value != typeof update)
    return update;
  if (isEqual(value, update))
    return DEEPLY_EQUAL;
  if (Array.isArray(value) && Array.isArray(update)) {
    let res = update.reduce((acc, upd, index) => {
      let diff = deepDiff(value[index], upd);
      return diff !== DEEPLY_EQUAL && (acc[index] = diff), acc;
    }, new Array(update.length));
    return update.length >= value.length ? res : res.concat(new Array(value.length - update.length).fill(void 0));
  }
  return isPlainObject(value) && isPlainObject(update) ? Object.keys({ ...value, ...update }).reduce((acc, key) => {
    let diff = deepDiff(value?.[key], update?.[key]);
    return diff === DEEPLY_EQUAL ? acc : Object.assign(acc, { [key]: diff });
  }, {}) : update;
}, UNTARGETED = "UNTARGETED";
function groupArgsByTarget({
  args,
  argTypes
}) {
  let groupedArgs = {};
  return Object.entries(args).forEach(([name, value]) => {
    let { target = UNTARGETED } = argTypes[name] || {};
    groupedArgs[target] = groupedArgs[target] || {}, groupedArgs[target][name] = value;
  }), groupedArgs;
}

// src/preview-api/modules/store/ArgsStore.ts
function deleteUndefined(obj) {
  return Object.keys(obj).forEach((key) => obj[key] === void 0 && delete obj[key]), obj;
}
var ArgsStore = class {
  constructor() {
    this.initialArgsByStoryId = {};
    this.argsByStoryId = {};
  }
  get(storyId) {
    if (!(storyId in this.argsByStoryId))
      throw new Error(`No args known for ${storyId} -- has it been rendered yet?`);
    return this.argsByStoryId[storyId];
  }
  setInitial(story) {
    if (!this.initialArgsByStoryId[story.id])
      this.initialArgsByStoryId[story.id] = story.initialArgs, this.argsByStoryId[story.id] = story.initialArgs;
    else if (this.initialArgsByStoryId[story.id] !== story.initialArgs) {
      let delta = deepDiff(this.initialArgsByStoryId[story.id], this.argsByStoryId[story.id]);
      this.initialArgsByStoryId[story.id] = story.initialArgs, this.argsByStoryId[story.id] = story.initialArgs, delta !== DEEPLY_EQUAL && this.updateFromDelta(story, delta);
    }
  }
  updateFromDelta(story, delta) {
    let validatedDelta = validateOptions(delta, story.argTypes);
    this.argsByStoryId[story.id] = combineArgs(this.argsByStoryId[story.id], validatedDelta);
  }
  updateFromPersisted(story, persisted) {
    let mappedPersisted = mapArgsToTypes(persisted, story.argTypes);
    return this.updateFromDelta(story, mappedPersisted);
  }
  update(storyId, argsUpdate) {
    if (!(storyId in this.argsByStoryId))
      throw new Error(`No args known for ${storyId} -- has it been rendered yet?`);
    this.argsByStoryId[storyId] = deleteUndefined({
      ...this.argsByStoryId[storyId],
      ...argsUpdate
    });
  }
};

// src/preview-api/modules/store/GlobalsStore.ts
import { logger as logger2 } from "storybook/internal/client-logger";

// src/preview-api/modules/store/csf/getValuesFromArgTypes.ts
var getValuesFromArgTypes = (argTypes = {}) => Object.entries(argTypes).reduce((acc, [arg, { defaultValue }]) => (typeof defaultValue < "u" && (acc[arg] = defaultValue), acc), {});

// src/preview-api/modules/store/GlobalsStore.ts
var GlobalsStore = class {
  constructor({
    globals = {},
    globalTypes = {}
  }) {
    this.set({ globals, globalTypes });
  }
  set({ globals = {}, globalTypes = {} }) {
    let delta = this.initialGlobals && deepDiff(this.initialGlobals, this.globals);
    this.allowedGlobalNames = /* @__PURE__ */ new Set([...Object.keys(globals), ...Object.keys(globalTypes)]);
    let defaultGlobals = getValuesFromArgTypes(globalTypes);
    this.initialGlobals = { ...defaultGlobals, ...globals }, this.globals = this.initialGlobals, delta && delta !== DEEPLY_EQUAL && this.updateFromPersisted(delta);
  }
  filterAllowedGlobals(globals) {
    return Object.entries(globals).reduce((acc, [key, value]) => (this.allowedGlobalNames.has(key) ? acc[key] = value : logger2.warn(
      `Attempted to set a global (${key}) that is not defined in initial globals or globalTypes`
    ), acc), {});
  }
  updateFromPersisted(persisted) {
    let allowedUrlGlobals = this.filterAllowedGlobals(persisted);
    this.globals = { ...this.globals, ...allowedUrlGlobals };
  }
  get() {
    return this.globals;
  }
  update(newGlobals) {
    this.globals = { ...this.globals, ...this.filterAllowedGlobals(newGlobals) };
    for (let key in newGlobals)
      newGlobals[key] === void 0 && (this.globals[key] = this.initialGlobals[key]);
  }
};

// src/preview-api/modules/store/StoryIndexStore.ts
var import_memoizerific = __toESM(require_memoizerific(), 1);
import { MissingStoryAfterHmrError } from "storybook/internal/preview-errors";
var getImportPathMap = (0, import_memoizerific.default)(1)(
  (entries) => Object.values(entries).reduce(
    (acc, entry) => (acc[entry.importPath] = acc[entry.importPath] || entry, acc),
    {}
  )
), StoryIndexStore = class {
  constructor({ entries } = { v: 5, entries: {} }) {
    this.entries = entries;
  }
  entryFromSpecifier(specifier) {
    let entries = Object.values(this.entries);
    if (specifier === "*")
      return entries[0];
    if (typeof specifier == "string")
      return this.entries[specifier] ? this.entries[specifier] : entries.find((entry) => entry.id.startsWith(specifier));
    let { name, title } = specifier;
    return entries.find((entry) => entry.name === name && entry.title === title);
  }
  storyIdToEntry(storyId) {
    let storyEntry = this.entries[storyId];
    if (!storyEntry)
      throw new MissingStoryAfterHmrError({ storyId });
    return storyEntry;
  }
  importPathToEntry(importPath) {
    return getImportPathMap(this.entries)[importPath];
  }
};

// src/preview-api/modules/store/csf/normalizeInputTypes.ts
var normalizeType = (type) => typeof type == "string" ? { name: type } : type, normalizeControl = (control) => typeof control == "string" ? { type: control } : control, normalizeInputType = (inputType, key) => {
  let { type, control, ...rest } = inputType, normalized = {
    name: key,
    ...rest
  };
  return type && (normalized.type = normalizeType(type)), control ? normalized.control = normalizeControl(control) : control === !1 && (normalized.control = { disable: !0 }), normalized;
}, normalizeInputTypes = (inputTypes) => mapValues(inputTypes, normalizeInputType);

// src/preview-api/modules/store/csf/normalizeStory.ts
import { deprecate, logger as logger3 } from "storybook/internal/client-logger";
import { storyNameFromExport, toId } from "storybook/internal/csf";

// src/preview-api/modules/store/csf/normalizeArrays.ts
var normalizeArrays = (array) => Array.isArray(array) ? array : array ? [array] : [];

// src/preview-api/modules/store/csf/normalizeStory.ts
var deprecatedStoryAnnotation = dedent`
CSF .story annotations deprecated; annotate story functions directly:
- StoryFn.story.name => StoryFn.storyName
- StoryFn.story.(parameters|decorators) => StoryFn.(parameters|decorators)
See https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#hoisted-csf-annotations for details and codemod.
`;
function normalizeStory(key, storyAnnotations, meta) {
  let storyObject = storyAnnotations, userStoryFn = typeof storyAnnotations == "function" ? storyAnnotations : null, { story } = storyObject;
  story && (logger3.debug("deprecated story", story), deprecate(deprecatedStoryAnnotation));
  let exportName = storyNameFromExport(key), name = typeof storyObject != "function" && storyObject.name || storyObject.storyName || story?.name || exportName, decorators = [
    ...normalizeArrays(storyObject.decorators),
    ...normalizeArrays(story?.decorators)
  ], parameters = { ...story?.parameters, ...storyObject.parameters }, args = { ...story?.args, ...storyObject.args }, argTypes = { ...story?.argTypes, ...storyObject.argTypes }, loaders = [...normalizeArrays(storyObject.loaders), ...normalizeArrays(story?.loaders)], beforeEach = [
    ...normalizeArrays(storyObject.beforeEach),
    ...normalizeArrays(story?.beforeEach)
  ], afterEach = [
    ...normalizeArrays(storyObject.afterEach),
    ...normalizeArrays(story?.afterEach)
  ], { render, play, tags = [], globals = {} } = storyObject, id = parameters.__id || toId(meta.id, exportName);
  return {
    moduleExport: storyAnnotations,
    id,
    name,
    tags,
    decorators,
    parameters,
    args,
    argTypes: normalizeInputTypes(argTypes),
    loaders,
    beforeEach,
    afterEach,
    globals,
    ...render && { render },
    ...userStoryFn && { userStoryFn },
    ...play && { play }
  };
}

// src/preview-api/modules/store/csf/processCSFFile.ts
import { logger as logger4 } from "storybook/internal/client-logger";
import { getStoryChildren, isExportStory, isStory, toTestId } from "storybook/internal/csf";

// src/preview-api/modules/store/csf/normalizeComponentAnnotations.ts
import { sanitize } from "storybook/internal/csf";
function normalizeComponentAnnotations(defaultExport, title = defaultExport.title, importPath) {
  let { id, argTypes } = defaultExport;
  return {
    id: sanitize(id || title),
    ...defaultExport,
    title,
    ...argTypes && { argTypes: normalizeInputTypes(argTypes) },
    parameters: {
      fileName: importPath,
      ...defaultExport.parameters
    }
  };
}

// src/preview-api/modules/store/csf/processCSFFile.ts
var checkGlobals = (parameters) => {
  let { globals, globalTypes } = parameters;
  (globals || globalTypes) && logger4.error(
    "Global args/argTypes can only be set globally",
    JSON.stringify({
      globals,
      globalTypes
    })
  );
}, checkStorySort = (parameters) => {
  let { options } = parameters;
  options?.storySort && logger4.error("The storySort option parameter can only be set globally");
}, checkDisallowedParameters = (parameters) => {
  parameters && (checkGlobals(parameters), checkStorySort(parameters));
};
function processCSFFile(moduleExports, importPath, title) {
  let { default: defaultExport, __namedExportsOrder, ...namedExports } = moduleExports, factoryStory = Object.values(namedExports).find((it) => isStory(it));
  if (factoryStory) {
    let meta2 = normalizeComponentAnnotations(factoryStory.meta.input, title, importPath);
    checkDisallowedParameters(meta2.parameters);
    let csfFile2 = { meta: meta2, stories: {}, moduleExports };
    return Object.keys(namedExports).forEach((key) => {
      if (isExportStory(key, meta2) && isStory(namedExports[key])) {
        let story = namedExports[key], storyMeta = normalizeStory(key, story.input, meta2);
        checkDisallowedParameters(storyMeta.parameters), csfFile2.stories[storyMeta.id] = storyMeta, getStoryChildren(story).forEach((child) => {
          let name = child.input.name, childId = toTestId(storyMeta.id, name);
          child.input.parameters ??= {}, child.input.parameters.__id = childId, csfFile2.stories[childId] = normalizeStory(name, child.input, meta2);
        });
      }
    }), csfFile2.projectAnnotations = factoryStory.meta.preview.composed, csfFile2;
  }
  let meta = normalizeComponentAnnotations(
    defaultExport,
    title,
    importPath
  );
  checkDisallowedParameters(meta.parameters);
  let csfFile = { meta, stories: {}, moduleExports };
  return Object.keys(namedExports).forEach((key) => {
    if (isExportStory(key, meta)) {
      let storyMeta = normalizeStory(key, namedExports[key], meta);
      checkDisallowedParameters(storyMeta.parameters), csfFile.stories[storyMeta.id] = storyMeta;
    }
  }), csfFile;
}

// src/preview-api/modules/store/csf/prepareStory.ts
import { combineTags, includeConditionalArg } from "storybook/internal/csf";
import { NoRenderFunctionError } from "storybook/internal/preview-errors";
import { global as global3 } from "@storybook/global";
import { global as globalThis2 } from "@storybook/global";

// src/preview-api/modules/preview-web/render/mount-utils.ts
function mountDestructured(playFunction) {
  return playFunction != null && getUsedProps(playFunction).includes("mount");
}
function getUsedProps(fn) {
  let match = fn.toString().match(/[^(]*\(([^)]*)/);
  if (!match)
    return [];
  let args = splitByComma(match[1]);
  if (!args.length)
    return [];
  let first = args[0];
  return first.startsWith("{") && first.endsWith("}") ? splitByComma(first.slice(1, -1).replace(/\s/g, "")).map((prop) => prop.replace(/:.*|=.*/g, "")) : [];
}
function splitByComma(s) {
  let result = [], stack = [], start = 0;
  for (let i = 0; i < s.length; i++)
    if (s[i] === "{" || s[i] === "[")
      stack.push(s[i] === "{" ? "}" : "]");
    else if (s[i] === stack[stack.length - 1])
      stack.pop();
    else if (!stack.length && s[i] === ",") {
      let token = s.substring(start, i).trim();
      token && result.push(token), start = i + 1;
    }
  let lastToken = s.substring(start).trim();
  return lastToken && result.push(lastToken), result;
}

// src/preview-api/modules/store/decorators.ts
function decorateStory(storyFn, decorator, bindWithContext) {
  let boundStoryFunction = bindWithContext(storyFn);
  return (context) => decorator(boundStoryFunction, context);
}
function sanitizeStoryContextUpdate({
  componentId,
  title,
  kind,
  id,
  name,
  story,
  parameters,
  initialArgs,
  argTypes,
  ...update
} = {}) {
  return update;
}
function defaultDecorateStory(storyFn, decorators) {
  let contextStore = {}, bindWithContext = (decoratedStoryFn) => (update) => {
    if (!contextStore.value)
      throw new Error("Decorated function called without init");
    return contextStore.value = {
      ...contextStore.value,
      ...sanitizeStoryContextUpdate(update)
    }, decoratedStoryFn(contextStore.value);
  }, decoratedWithContextStore = decorators.reduce(
    (story, decorator) => decorateStory(story, decorator, bindWithContext),
    storyFn
  );
  return (context) => (contextStore.value = context, decoratedWithContextStore(context));
}

// src/preview-api/modules/store/csf/prepareStory.ts
function prepareStory(storyAnnotations, componentAnnotations, projectAnnotations) {
  let { moduleExport, id, name } = storyAnnotations || {}, partialAnnotations = preparePartialAnnotations(
    storyAnnotations,
    componentAnnotations,
    projectAnnotations
  ), applyLoaders = async (context) => {
    let loaded = {};
    for (let loaders of [
      normalizeArrays(projectAnnotations.loaders),
      normalizeArrays(componentAnnotations.loaders),
      normalizeArrays(storyAnnotations.loaders)
    ]) {
      if (context.abortSignal.aborted)
        return loaded;
      let loadResults = await Promise.all(loaders.map((loader) => loader(context)));
      Object.assign(loaded, ...loadResults);
    }
    return loaded;
  }, applyBeforeEach = async (context) => {
    let cleanupCallbacks = new Array();
    for (let beforeEach of [
      ...normalizeArrays(projectAnnotations.beforeEach),
      ...normalizeArrays(componentAnnotations.beforeEach),
      ...normalizeArrays(storyAnnotations.beforeEach)
    ]) {
      if (context.abortSignal.aborted)
        return cleanupCallbacks;
      let cleanup = await beforeEach(context);
      cleanup && cleanupCallbacks.push(cleanup);
    }
    return cleanupCallbacks;
  }, applyAfterEach = async (context) => {
    let reversedFinalizers = [
      ...normalizeArrays(projectAnnotations.afterEach),
      ...normalizeArrays(componentAnnotations.afterEach),
      ...normalizeArrays(storyAnnotations.afterEach)
    ].reverse();
    for (let finalizer of reversedFinalizers) {
      if (context.abortSignal.aborted)
        return;
      await finalizer(context);
    }
  }, undecoratedStoryFn = (context) => context.originalStoryFn(context.args, context), { applyDecorators = defaultDecorateStory, runStep } = projectAnnotations, decorators = [
    ...normalizeArrays(storyAnnotations?.decorators),
    ...normalizeArrays(componentAnnotations?.decorators),
    ...normalizeArrays(projectAnnotations?.decorators)
  ], render = storyAnnotations?.userStoryFn || storyAnnotations?.render || componentAnnotations.render || projectAnnotations.render, decoratedStoryFn = applyHooks(applyDecorators)(undecoratedStoryFn, decorators), unboundStoryFn = (context) => decoratedStoryFn(context), playFunction = storyAnnotations?.play ?? componentAnnotations?.play, usesMount = mountDestructured(playFunction);
  if (!render && !usesMount)
    throw new NoRenderFunctionError({ id });
  let defaultMount = (context) => async () => (await context.renderToCanvas(), context.canvas), mount = storyAnnotations.mount ?? componentAnnotations.mount ?? projectAnnotations.mount ?? defaultMount, testingLibraryRender = projectAnnotations.testingLibraryRender;
  return {
    storyGlobals: {},
    ...partialAnnotations,
    moduleExport,
    id,
    name,
    story: name,
    originalStoryFn: render,
    undecoratedStoryFn,
    unboundStoryFn,
    applyLoaders,
    applyBeforeEach,
    applyAfterEach,
    playFunction,
    runStep,
    mount,
    testingLibraryRender,
    renderToCanvas: projectAnnotations.renderToCanvas,
    usesMount
  };
}
function prepareMeta(componentAnnotations, projectAnnotations, moduleExport) {
  return {
    ...preparePartialAnnotations(void 0, componentAnnotations, projectAnnotations),
    moduleExport
  };
}
function preparePartialAnnotations(storyAnnotations, componentAnnotations, projectAnnotations) {
  let defaultTags = ["dev", "test"], extraTags = globalThis2.DOCS_OPTIONS?.autodocs === !0 ? ["autodocs"] : [], overrideTags = storyAnnotations?.tags?.includes("test-fn") ? ["!autodocs"] : [], tags = combineTags(
    ...defaultTags,
    ...extraTags,
    ...projectAnnotations.tags ?? [],
    ...componentAnnotations.tags ?? [],
    ...overrideTags,
    ...storyAnnotations?.tags ?? []
  ), parameters = combineParameters(
    projectAnnotations.parameters,
    componentAnnotations.parameters,
    storyAnnotations?.parameters
  ), { argTypesEnhancers = [], argsEnhancers = [] } = projectAnnotations, passedArgTypes = combineParameters(
    projectAnnotations.argTypes,
    componentAnnotations.argTypes,
    storyAnnotations?.argTypes
  );
  if (storyAnnotations) {
    let render = storyAnnotations?.userStoryFn || storyAnnotations?.render || componentAnnotations.render || projectAnnotations.render;
    parameters.__isArgsStory = render && render.length > 0;
  }
  let passedArgs = {
    ...projectAnnotations.args,
    ...componentAnnotations.args,
    ...storyAnnotations?.args
  }, storyGlobals = {
    ...componentAnnotations.globals,
    ...storyAnnotations?.globals
  }, contextForEnhancers = {
    componentId: componentAnnotations.id,
    title: componentAnnotations.title,
    kind: componentAnnotations.title,
    // Back compat
    id: storyAnnotations?.id || componentAnnotations.id,
    // if there's no story name, we create a fake one since enhancers expect a name
    name: storyAnnotations?.name || "__meta",
    story: storyAnnotations?.name || "__meta",
    // Back compat
    component: componentAnnotations.component,
    subcomponents: componentAnnotations.subcomponents,
    tags,
    parameters,
    initialArgs: passedArgs,
    argTypes: passedArgTypes,
    storyGlobals
  };
  contextForEnhancers.argTypes = argTypesEnhancers.reduce(
    (accumulatedArgTypes, enhancer) => enhancer({ ...contextForEnhancers, argTypes: accumulatedArgTypes }),
    contextForEnhancers.argTypes
  );
  let initialArgsBeforeEnhancers = { ...passedArgs };
  contextForEnhancers.initialArgs = [...argsEnhancers].reduce(
    (accumulatedArgs, enhancer) => ({
      ...accumulatedArgs,
      ...enhancer({
        ...contextForEnhancers,
        initialArgs: accumulatedArgs
      })
    }),
    initialArgsBeforeEnhancers
  );
  let { name, story, ...withoutStoryIdentifiers } = contextForEnhancers;
  return withoutStoryIdentifiers;
}
function prepareContext(context) {
  let { args: unmappedArgs } = context, targetedContext = {
    ...context,
    allArgs: void 0,
    argsByTarget: void 0
  };
  if (global3.FEATURES?.argTypeTargetsV7) {
    let argsByTarget = groupArgsByTarget(context);
    targetedContext = {
      ...context,
      allArgs: context.args,
      argsByTarget,
      args: argsByTarget[UNTARGETED] || {}
    };
  }
  let mappedArgs = Object.entries(targetedContext.args).reduce((acc, [key, val]) => {
    if (!targetedContext.argTypes[key]?.mapping)
      return acc[key] = val, acc;
    let mappingFn = (originalValue) => {
      let mapping = targetedContext.argTypes[key].mapping;
      return mapping && originalValue in mapping ? mapping[originalValue] : originalValue;
    };
    return acc[key] = Array.isArray(val) ? val.map(mappingFn) : mappingFn(val), acc;
  }, {}), includedArgs = Object.entries(mappedArgs).reduce((acc, [key, val]) => {
    let argType = targetedContext.argTypes[key] || {};
    return includeConditionalArg(argType, mappedArgs, targetedContext.globals) && (acc[key] = val), acc;
  }, {});
  return { ...targetedContext, unmappedArgs, args: includedArgs };
}

// src/preview-api/modules/store/inferArgTypes.ts
import { logger as logger5 } from "storybook/internal/client-logger";
var inferType = (value, name, visited) => {
  let type = typeof value;
  switch (type) {
    case "boolean":
    case "string":
    case "number":
    case "function":
    case "symbol":
      return { name: type };
    default:
      break;
  }
  return value ? visited.has(value) ? (logger5.warn(dedent`
        We've detected a cycle in arg '${name}'. Args should be JSON-serializable.

        Consider using the mapping feature or fully custom args:
        - Mapping: https://storybook.js.org/docs/writing-stories/args#mapping-to-complex-arg-values
        - Custom args: https://storybook.js.org/docs/essentials/controls#fully-custom-args
      `), { name: "other", value: "cyclic object" }) : (visited.add(value), Array.isArray(value) ? { name: "array", value: value.length > 0 ? inferType(value[0], name, new Set(visited)) : { name: "other", value: "unknown" } } : { name: "object", value: mapValues(value, (field) => inferType(field, name, new Set(visited))) }) : { name: "object", value: {} };
}, inferArgTypes = (context) => {
  let { id, argTypes: userArgTypes = {}, initialArgs = {} } = context, argTypes = mapValues(initialArgs, (arg, key) => ({
    name: key,
    type: inferType(arg, `${id}.${key}`, /* @__PURE__ */ new Set())
  })), userArgTypesNames = mapValues(userArgTypes, (argType, key) => ({
    name: key
  }));
  return combineParameters(argTypes, userArgTypesNames, userArgTypes);
};
inferArgTypes.secondPass = !0;

// src/preview-api/modules/store/inferControls.ts
import { logger as logger6 } from "storybook/internal/client-logger";

// src/preview-api/modules/store/filterArgTypes.ts
var matches = (name, descriptor) => Array.isArray(descriptor) ? descriptor.includes(name) : name.match(descriptor), filterArgTypes = (argTypes, include, exclude) => !include && !exclude ? argTypes : argTypes && pickBy(argTypes, (argType, key) => {
  let name = argType.name || key.toString();
  return !!(!include || matches(name, include)) && (!exclude || !matches(name, exclude));
});

// src/preview-api/modules/store/inferControls.ts
var inferControl = (argType, name, matchers) => {
  let { type, options } = argType;
  if (type) {
    if (matchers.color && matchers.color.test(name)) {
      let controlType = type.name;
      if (controlType === "string")
        return { control: { type: "color" } };
      controlType !== "enum" && logger6.warn(
        `Addon controls: Control of type color only supports string, received "${controlType}" instead`
      );
    }
    if (matchers.date && matchers.date.test(name))
      return { control: { type: "date" } };
    switch (type.name) {
      case "array":
        return { control: { type: "object" } };
      case "boolean":
        return { control: { type: "boolean" } };
      case "string":
        return { control: { type: "text" } };
      case "number":
        return { control: { type: "number" } };
      case "enum": {
        let { value } = type;
        return { control: { type: value?.length <= 5 ? "radio" : "select" }, options: value };
      }
      case "function":
      case "symbol":
        return null;
      default:
        return { control: { type: options ? "select" : "object" } };
    }
  }
}, inferControls = (context) => {
  let {
    argTypes,
    parameters: { __isArgsStory, controls: { include = null, exclude = null, matchers = {} } = {} }
  } = context;
  if (!__isArgsStory)
    return argTypes;
  let filteredArgTypes = filterArgTypes(argTypes, include, exclude), withControls = mapValues(filteredArgTypes, (argType, name) => argType?.type && inferControl(argType, name.toString(), matchers));
  return combineParameters(withControls, filteredArgTypes);
};
inferControls.secondPass = !0;

// src/preview-api/modules/store/csf/normalizeProjectAnnotations.ts
function normalizeProjectAnnotations({
  argTypes,
  globalTypes,
  argTypesEnhancers,
  decorators,
  loaders,
  beforeEach,
  afterEach,
  initialGlobals,
  ...annotations
}) {
  return {
    ...argTypes && { argTypes: normalizeInputTypes(argTypes) },
    ...globalTypes && { globalTypes: normalizeInputTypes(globalTypes) },
    decorators: normalizeArrays(decorators),
    loaders: normalizeArrays(loaders),
    beforeEach: normalizeArrays(beforeEach),
    afterEach: normalizeArrays(afterEach),
    argTypesEnhancers: [
      ...argTypesEnhancers || [],
      inferArgTypes,
      // There's an architectural decision to be made regarding embedded addons in core:
      //
      // Option 1: Keep embedded addons but ensure consistency by moving addon-specific code
      // (like inferControls) to live alongside the addon code itself. This maintains the
      // concept of core addons while improving code organization.
      //
      // Option 2: Fully integrate these addons into core, potentially moving UI components
      // into the manager and treating them as core features rather than addons. This is a
      // bigger architectural change requiring careful consideration.
      //
      // For now, we're keeping inferControls here as we need time to properly evaluate
      // these options and their implications. Some features (like Angular's cleanArgsDecorator)
      // currently rely on this behavior.
      //
      // TODO: Make an architectural decision on the handling of core addons
      inferControls
    ],
    initialGlobals,
    ...annotations
  };
}

// src/preview-api/modules/store/csf/composeConfigs.ts
import { global as global4 } from "@storybook/global";

// src/preview-api/modules/store/csf/beforeAll.ts
var composeBeforeAllHooks = (hooks) => async () => {
  let cleanups2 = [];
  for (let hook of hooks) {
    let cleanup = await hook();
    cleanup && cleanups2.unshift(cleanup);
  }
  return async () => {
    for (let cleanup of cleanups2)
      await cleanup();
  };
};

// src/preview-api/modules/store/csf/stepRunners.ts
function composeStepRunners(stepRunners) {
  return async (label, play, playContext) => {
    await stepRunners.reduceRight(
      (innerPlay, stepRunner) => async () => stepRunner(label, innerPlay, playContext),
      async () => play(playContext)
    )();
  };
}

// src/preview-api/modules/store/csf/composeConfigs.ts
function getField(moduleExportList, field) {
  return moduleExportList.map((xs) => xs.default?.[field] ?? xs[field]).filter(Boolean);
}
function getArrayField(moduleExportList, field, options = {}) {
  return getField(moduleExportList, field).reduce((prev, cur) => {
    let normalized = normalizeArrays(cur);
    return options.reverseFileOrder ? [...normalized, ...prev] : [...prev, ...normalized];
  }, []);
}
function getObjectField(moduleExportList, field) {
  return Object.assign({}, ...getField(moduleExportList, field));
}
function getSingletonField(moduleExportList, field) {
  return getField(moduleExportList, field).pop();
}
function composeConfigs(moduleExportList) {
  let allArgTypeEnhancers = getArrayField(moduleExportList, "argTypesEnhancers"), stepRunners = getField(moduleExportList, "runStep"), beforeAllHooks = getArrayField(moduleExportList, "beforeAll");
  return {
    parameters: combineParameters(...getField(moduleExportList, "parameters")),
    decorators: getArrayField(moduleExportList, "decorators", {
      reverseFileOrder: !(global4.FEATURES?.legacyDecoratorFileOrder ?? !1)
    }),
    args: getObjectField(moduleExportList, "args"),
    argsEnhancers: getArrayField(moduleExportList, "argsEnhancers"),
    argTypes: getObjectField(moduleExportList, "argTypes"),
    argTypesEnhancers: [
      ...allArgTypeEnhancers.filter((e) => !e.secondPass),
      ...allArgTypeEnhancers.filter((e) => e.secondPass)
    ],
    initialGlobals: getObjectField(moduleExportList, "initialGlobals"),
    globalTypes: getObjectField(moduleExportList, "globalTypes"),
    loaders: getArrayField(moduleExportList, "loaders"),
    beforeAll: composeBeforeAllHooks(beforeAllHooks),
    beforeEach: getArrayField(moduleExportList, "beforeEach"),
    afterEach: getArrayField(moduleExportList, "afterEach"),
    render: getSingletonField(moduleExportList, "render"),
    renderToCanvas: getSingletonField(moduleExportList, "renderToCanvas"),
    applyDecorators: getSingletonField(moduleExportList, "applyDecorators"),
    runStep: composeStepRunners(stepRunners),
    tags: getArrayField(moduleExportList, "tags"),
    mount: getSingletonField(moduleExportList, "mount"),
    testingLibraryRender: getSingletonField(moduleExportList, "testingLibraryRender")
  };
}

// src/preview-api/modules/store/csf/portable-stories.ts
import { isExportStory as isExportStory2 } from "storybook/internal/csf";
import { getCoreAnnotations } from "storybook/internal/csf";
import { MountMustBeDestructuredError } from "storybook/internal/preview-errors";

// src/preview-api/modules/store/reporter-api.ts
var ReporterAPI = class {
  constructor() {
    this.reports = [];
  }
  async addReport(report) {
    this.reports.push(report);
  }
};

// src/preview-api/modules/store/csf/csf-factory-utils.ts
import { isMeta, isStory as isStory2 } from "storybook/internal/csf";
function getCsfFactoryAnnotations(story, meta, projectAnnotations) {
  return isStory2(story) ? {
    story: story.input,
    meta: story.meta.input,
    preview: story.meta.preview.composed
  } : { story, meta: isMeta(meta) ? meta.input : meta, preview: projectAnnotations };
}

// src/preview-api/modules/store/csf/portable-stories.ts
function setDefaultProjectAnnotations(_defaultProjectAnnotations) {
  globalThis.defaultProjectAnnotations = _defaultProjectAnnotations;
}
var DEFAULT_STORY_TITLE = "ComposedStory", DEFAULT_STORY_NAME = "Unnamed Story";
function extractAnnotation(annotation) {
  return annotation ? composeConfigs([annotation]) : {};
}
function setProjectAnnotations(projectAnnotations) {
  let annotations = Array.isArray(projectAnnotations) ? projectAnnotations : [projectAnnotations];
  return globalThis.globalProjectAnnotations = composeConfigs([
    ...getCoreAnnotations(),
    globalThis.defaultProjectAnnotations ?? {},
    composeConfigs(annotations.map(extractAnnotation))
  ]), globalThis.globalProjectAnnotations ?? {};
}
var cleanups = [];
function composeStory(storyAnnotations, componentAnnotations, projectAnnotations, defaultConfig, exportsName) {
  if (storyAnnotations === void 0)
    throw new Error("Expected a story but received undefined.");
  componentAnnotations.title = componentAnnotations.title ?? DEFAULT_STORY_TITLE;
  let normalizedComponentAnnotations = normalizeComponentAnnotations(componentAnnotations), storyName = exportsName || storyAnnotations.storyName || storyAnnotations.story?.name || storyAnnotations.name || DEFAULT_STORY_NAME, normalizedStory = normalizeStory(
    storyName,
    storyAnnotations,
    normalizedComponentAnnotations
  ), normalizedProjectAnnotations = normalizeProjectAnnotations(
    composeConfigs([
      defaultConfig ?? globalThis.globalProjectAnnotations ?? {},
      projectAnnotations ?? {}
    ])
  ), story = prepareStory(
    normalizedStory,
    normalizedComponentAnnotations,
    normalizedProjectAnnotations
  ), globals = {
    ...getValuesFromArgTypes(normalizedProjectAnnotations.globalTypes),
    ...normalizedProjectAnnotations.initialGlobals,
    ...story.storyGlobals
  }, reporting = new ReporterAPI(), initializeContext = () => {
    let context = prepareContext({
      hooks: new HooksContext(),
      globals,
      args: { ...story.initialArgs },
      viewMode: "story",
      reporting,
      loaded: {},
      abortSignal: new AbortController().signal,
      step: (label, play2) => story.runStep(label, play2, context),
      canvasElement: null,
      canvas: {},
      userEvent: {},
      globalTypes: normalizedProjectAnnotations.globalTypes,
      ...story,
      context: null,
      mount: null
    });
    return context.parameters.__isPortableStory = !0, context.context = context, story.renderToCanvas && (context.renderToCanvas = async () => {
      let unmount = await story.renderToCanvas?.(
        {
          componentId: story.componentId,
          title: story.title,
          id: story.id,
          name: story.name,
          tags: story.tags,
          showMain: () => {
          },
          showError: (error) => {
            throw new Error(`${error.title}
${error.description}`);
          },
          showException: (error) => {
            throw error;
          },
          forceRemount: !0,
          storyContext: context,
          storyFn: () => story.unboundStoryFn(context),
          unboundStoryFn: story.unboundStoryFn
        },
        context.canvasElement
      );
      unmount && cleanups.push(unmount);
    }), context.mount = story.mount(context), context;
  }, loadedContext, play = async (extraContext) => {
    let context = initializeContext();
    return context.canvasElement ??= globalThis?.document?.body, loadedContext && (context.loaded = loadedContext.loaded), Object.assign(context, extraContext), story.playFunction(context);
  }, run = (extraContext) => {
    let context = initializeContext();
    return Object.assign(context, extraContext), runStory(story, context);
  }, playFunction = story.playFunction ? play : void 0;
  return Object.assign(
    function(extraArgs) {
      let context = initializeContext();
      return loadedContext && (context.loaded = loadedContext.loaded), context.args = {
        ...context.initialArgs,
        ...extraArgs
      }, story.unboundStoryFn(context);
    },
    {
      id: story.id,
      storyName,
      load: async () => {
        for (let callback of [...cleanups].reverse())
          await callback();
        cleanups.length = 0;
        let context = initializeContext();
        context.loaded = await story.applyLoaders(context), cleanups.push(...(await story.applyBeforeEach(context)).filter(Boolean)), loadedContext = context;
      },
      globals,
      args: story.initialArgs,
      parameters: story.parameters,
      argTypes: story.argTypes,
      play: playFunction,
      run,
      reporting,
      tags: story.tags
    }
  );
}
var defaultComposeStory = (story, component, project, exportsName) => composeStory(story, component, project, {}, exportsName);
function composeStories(storiesImport, globalConfig, composeStoryFn = defaultComposeStory) {
  let { default: metaExport, __esModule, __namedExportsOrder, ...stories } = storiesImport, meta = metaExport;
  return Object.entries(stories).reduce(
    (storiesMap, [exportsName, story]) => {
      let { story: storyAnnotations, meta: componentAnnotations } = getCsfFactoryAnnotations(story);
      return !meta && componentAnnotations && (meta = componentAnnotations), isExportStory2(exportsName, meta) ? Object.assign(storiesMap, {
        [exportsName]: composeStoryFn(storyAnnotations, meta, globalConfig, exportsName)
      }) : storiesMap;
    },
    {}
  );
}
function createPlaywrightTest(baseTest) {
  return baseTest.extend({
    mount: async ({ mount, page }, use) => {
      await use(async (storyRef, ...restArgs) => {
        if (!("__pw_type" in storyRef) || "__pw_type" in storyRef && storyRef.__pw_type !== "jsx")
          throw new Error(dedent`
              Portable stories in Playwright CT only work when referencing JSX elements.
              Please use JSX format for your components such as:

              instead of:
              await mount(MyComponent, { props: { foo: 'bar' } })

              do:
              await mount(<MyComponent foo="bar"/>)

              More info: https://storybook.js.org/docs/api/portable-stories/portable-stories-playwright?ref=error
            `);
        let { props, ...storyRefWithoutProps } = storyRef;
        await page.evaluate(async (wrappedStoryRef) => {
          let unwrappedStoryRef = await globalThis.__pwUnwrapObject?.(wrappedStoryRef);
          return ("__pw_type" in unwrappedStoryRef ? unwrappedStoryRef.type : unwrappedStoryRef)?.load?.();
        }, storyRefWithoutProps);
        let mountResult = await mount(storyRef, ...restArgs);
        return await page.evaluate(async (wrappedStoryRef) => {
          let unwrappedStoryRef = await globalThis.__pwUnwrapObject?.(wrappedStoryRef), story = "__pw_type" in unwrappedStoryRef ? unwrappedStoryRef.type : unwrappedStoryRef, canvasElement = document.querySelector("#root");
          return story?.play?.({ canvasElement });
        }, storyRefWithoutProps), mountResult;
      });
    }
  });
}
async function runStory(story, context) {
  for (let callback of [...cleanups].reverse())
    await callback();
  if (cleanups.length = 0, !context.canvasElement) {
    let container = document.createElement("div");
    globalThis?.document?.body?.appendChild(container), context.canvasElement = container, cleanups.push(() => {
      globalThis?.document?.body?.contains(container) && globalThis?.document?.body?.removeChild(container);
    });
  }
  if (context.loaded = await story.applyLoaders(context), context.abortSignal.aborted)
    return;
  cleanups.push(...(await story.applyBeforeEach(context)).filter(Boolean));
  let playFunction = story.playFunction, isMountDestructured = story.usesMount;
  if (isMountDestructured || await context.mount(), context.abortSignal.aborted)
    return;
  playFunction && (isMountDestructured || (context.mount = async () => {
    throw new MountMustBeDestructuredError({ playFunction: playFunction.toString() });
  }), await playFunction(context));
  let cleanUp;
  isTestEnvironment() ? cleanUp = pauseAnimations() : await waitForAnimations(context.abortSignal), await story.applyAfterEach(context), await cleanUp?.();
}

// src/preview-api/modules/store/StoryStore.ts
var CSF_CACHE_SIZE = 1e3, STORY_CACHE_SIZE = 1e4, StoryStore = class {
  constructor(storyIndex, importFn, projectAnnotations) {
    this.importFn = importFn;
    this.storyIndex = new StoryIndexStore(storyIndex), this.projectAnnotations = normalizeProjectAnnotations(
      composeConfigs([...getCoreAnnotations2(), projectAnnotations])
    );
    let { initialGlobals, globalTypes } = this.projectAnnotations;
    this.args = new ArgsStore(), this.userGlobals = new GlobalsStore({ globals: initialGlobals, globalTypes }), this.hooks = {}, this.cleanupCallbacks = {}, this.processCSFFileWithCache = (0, import_memoizerific2.default)(CSF_CACHE_SIZE)(processCSFFile), this.prepareMetaWithCache = (0, import_memoizerific2.default)(CSF_CACHE_SIZE)(prepareMeta), this.prepareStoryWithCache = (0, import_memoizerific2.default)(STORY_CACHE_SIZE)(prepareStory);
  }
  setProjectAnnotations(projectAnnotations) {
    this.projectAnnotations = normalizeProjectAnnotations(projectAnnotations);
    let { initialGlobals, globalTypes } = projectAnnotations;
    this.userGlobals.set({ globals: initialGlobals, globalTypes });
  }
  // This means that one of the CSF files has changed.
  // If the `importFn` has changed, we will invalidate both caches.
  // If the `storyIndex` data has changed, we may or may not invalidate the caches, depending
  // on whether we've loaded the relevant files yet.
  async onStoriesChanged({
    importFn,
    storyIndex
  }) {
    importFn && (this.importFn = importFn), storyIndex && (this.storyIndex.entries = storyIndex.entries), this.cachedCSFFiles && await this.cacheAllCSFFiles();
  }
  // Get an entry from the index, waiting on initialization if necessary
  async storyIdToEntry(storyId) {
    return this.storyIndex.storyIdToEntry(storyId);
  }
  // To load a single CSF file to service a story we need to look up the importPath in the index
  async loadCSFFileByStoryId(storyId) {
    let { importPath, title } = this.storyIndex.storyIdToEntry(storyId), moduleExports = await this.importFn(importPath);
    return this.processCSFFileWithCache(moduleExports, importPath, title);
  }
  async loadAllCSFFiles() {
    let importPaths = {};
    return Object.entries(this.storyIndex.entries).forEach(([storyId, { importPath }]) => {
      importPaths[importPath] = storyId;
    }), (await Promise.all(
      Object.entries(importPaths).map(async ([importPath, storyId]) => ({
        importPath,
        csfFile: await this.loadCSFFileByStoryId(storyId)
      }))
    )).reduce(
      (acc, { importPath, csfFile }) => (acc[importPath] = csfFile, acc),
      {}
    );
  }
  async cacheAllCSFFiles() {
    this.cachedCSFFiles = await this.loadAllCSFFiles();
  }
  preparedMetaFromCSFFile({ csfFile }) {
    let componentAnnotations = csfFile.meta;
    return this.prepareMetaWithCache(
      componentAnnotations,
      this.projectAnnotations,
      csfFile.moduleExports.default
    );
  }
  // Load the CSF file for a story and prepare the story from it and the project annotations.
  async loadStory({ storyId }) {
    let csfFile = await this.loadCSFFileByStoryId(storyId);
    return this.storyFromCSFFile({ storyId, csfFile });
  }
  // This function is synchronous for convenience -- often times if you have a CSF file already
  // it is easier not to have to await `loadStory`.
  storyFromCSFFile({
    storyId,
    csfFile
  }) {
    let storyAnnotations = csfFile.stories[storyId];
    if (!storyAnnotations)
      throw new MissingStoryFromCsfFileError({ storyId });
    let componentAnnotations = csfFile.meta, story = this.prepareStoryWithCache(
      storyAnnotations,
      componentAnnotations,
      csfFile.projectAnnotations ?? this.projectAnnotations
    );
    return this.args.setInitial(story), this.hooks[story.id] = this.hooks[story.id] || new HooksContext(), story;
  }
  // If we have a CSF file we can get all the stories from it synchronously
  componentStoriesFromCSFFile({
    csfFile
  }) {
    return Object.keys(this.storyIndex.entries).filter((storyId) => !!csfFile.stories[storyId]).map((storyId) => this.storyFromCSFFile({ storyId, csfFile }));
  }
  async loadEntry(id) {
    let entry = await this.storyIdToEntry(id), storyImports = entry.type === "docs" ? entry.storiesImports : [], [entryExports, ...csfFiles] = await Promise.all([
      this.importFn(entry.importPath),
      ...storyImports.map((storyImportPath) => {
        let firstStoryEntry = this.storyIndex.importPathToEntry(storyImportPath);
        return this.loadCSFFileByStoryId(firstStoryEntry.id);
      })
    ]);
    return { entryExports, csfFiles };
  }
  // A prepared story does not include args, globals or hooks. These are stored in the story store
  // and updated separately to the (immutable) story.
  getStoryContext(story, { forceInitialArgs = !1 } = {}) {
    let userGlobals = this.userGlobals.get(), { initialGlobals } = this.userGlobals, reporting = new ReporterAPI();
    return prepareContext({
      ...story,
      args: forceInitialArgs ? story.initialArgs : this.args.get(story.id),
      initialGlobals,
      globalTypes: this.projectAnnotations.globalTypes,
      userGlobals,
      reporting,
      globals: {
        ...userGlobals,
        ...story.storyGlobals
      },
      hooks: this.hooks[story.id]
    });
  }
  addCleanupCallbacks(story, ...callbacks) {
    this.cleanupCallbacks[story.id] = (this.cleanupCallbacks[story.id] || []).concat(callbacks);
  }
  async cleanupStory(story) {
    this.hooks[story.id].clean();
    let callbacks = this.cleanupCallbacks[story.id];
    if (callbacks)
      for (let callback of [...callbacks].reverse())
        await callback();
    delete this.cleanupCallbacks[story.id];
  }
  extract(options = { includeDocsOnly: !1 }) {
    let { cachedCSFFiles } = this;
    if (console.log("extract: extracting stories", cachedCSFFiles), !cachedCSFFiles)
      throw new CalledExtractOnStoreError();
    let stories = Object.entries(this.storyIndex.entries).reduce(
      (acc, [storyId, entry]) => {
        if (entry.type === "docs")
          return acc;
        let csfFile = cachedCSFFiles[entry.importPath], story = this.storyFromCSFFile({ storyId, csfFile });
        return !options.includeDocsOnly && story.parameters.docsOnly || (acc[storyId] = Object.entries(story).reduce(
          (storyAcc, [key, value]) => key === "story" && entry.subtype === "test" ? { ...storyAcc, story: entry.parentName } : key === "moduleExport" || typeof value == "function" ? storyAcc : Array.isArray(value) ? Object.assign(storyAcc, { [key]: value.slice().sort() }) : Object.assign(storyAcc, { [key]: value }),
          {
            args: story.initialArgs,
            globals: {
              ...this.userGlobals.initialGlobals,
              ...this.userGlobals.globals,
              ...story.storyGlobals
            },
            storyId: entry.parent ? entry.parent : storyId
          }
        )), acc;
      },
      {}
    );
    return console.log("extract: stories", stories), stories;
  }
};

// src/preview-api/modules/store/autoTitle.ts
import { once as once2 } from "storybook/internal/client-logger";

// ../node_modules/slash/index.js
function slash(path) {
  return path.startsWith("\\\\?\\") ? path : path.replace(/\\/g, "/");
}

// src/preview-api/modules/store/autoTitle.ts
var sanitize2 = (parts) => {
  if (parts.length === 0)
    return parts;
  let last = parts[parts.length - 1], lastStripped = last?.replace(/(?:[.](?:story|stories))?([.][^.]+)$/i, "");
  if (parts.length === 1)
    return [lastStripped];
  let nextToLast = parts[parts.length - 2];
  return lastStripped && nextToLast && lastStripped.toLowerCase() === nextToLast.toLowerCase() ? [...parts.slice(0, -2), lastStripped] : lastStripped && (/^(story|stories)([.][^.]+)$/i.test(last) || /^index$/i.test(lastStripped)) ? parts.slice(0, -1) : [...parts.slice(0, -1), lastStripped];
};
function pathJoin(paths) {
  return paths.flatMap((p) => p.split("/")).filter(Boolean).join("/");
}
var userOrAutoTitleFromSpecifier = (fileName, entry, userTitle) => {
  let { directory, importPathMatcher, titlePrefix = "" } = entry || {};
  typeof fileName == "number" && once2.warn(dedent`
      CSF Auto-title received a numeric fileName. This typically happens when
      webpack is mis-configured in production mode. To force webpack to produce
      filenames, set optimization.moduleIds = "named" in your webpack config.
    `);
  let normalizedFileName = slash(String(fileName));
  if (importPathMatcher.exec(normalizedFileName)) {
    if (!userTitle) {
      let suffix = normalizedFileName.replace(directory, ""), parts = pathJoin([titlePrefix, suffix]).split("/");
      return parts = sanitize2(parts), parts.join("/");
    }
    return titlePrefix ? pathJoin([titlePrefix, userTitle]) : userTitle;
  }
}, userOrAutoTitle = (fileName, storiesEntries, userTitle) => {
  for (let i = 0; i < storiesEntries.length; i += 1) {
    let title = userOrAutoTitleFromSpecifier(fileName, storiesEntries[i], userTitle);
    if (title)
      return title;
  }
  return userTitle || void 0;
};

// src/preview-api/modules/store/storySort.ts
var STORY_KIND_PATH_SEPARATOR = /\s*\/\s*/, storySort = (options = {}) => (a, b) => {
  if (a.title === b.title && !options.includeNames)
    return 0;
  let method = options.method || "configure", order = options.order || [], storyTitleA = a.title.trim().split(STORY_KIND_PATH_SEPARATOR), storyTitleB = b.title.trim().split(STORY_KIND_PATH_SEPARATOR);
  options.includeNames && (storyTitleA.push(a.name), storyTitleB.push(b.name));
  let depth = 0;
  for (; storyTitleA[depth] || storyTitleB[depth]; ) {
    if (!storyTitleA[depth])
      return -1;
    if (!storyTitleB[depth])
      return 1;
    let nameA = storyTitleA[depth], nameB = storyTitleB[depth];
    if (nameA !== nameB) {
      let indexA = order.indexOf(nameA), indexB = order.indexOf(nameB), indexWildcard = order.indexOf("*");
      return indexA !== -1 || indexB !== -1 ? (indexA === -1 && (indexWildcard !== -1 ? indexA = indexWildcard : indexA = order.length), indexB === -1 && (indexWildcard !== -1 ? indexB = indexWildcard : indexB = order.length), indexA - indexB) : method === "configure" ? 0 : nameA.localeCompare(nameB, options.locales ? options.locales : void 0, {
        numeric: !0,
        sensitivity: "accent"
      });
    }
    let index = order.indexOf(nameA);
    index === -1 && (index = order.indexOf("*")), order = index !== -1 && Array.isArray(order[index + 1]) ? order[index + 1] : [], depth += 1;
  }
  return 0;
};

// src/preview-api/modules/store/sortStories.ts
var sortStoriesCommon = (stories, storySortParameter, fileNameOrder) => {
  if (storySortParameter) {
    let sortFn;
    typeof storySortParameter == "function" ? sortFn = storySortParameter : sortFn = storySort(storySortParameter), stories.sort(sortFn);
  } else
    stories.sort(
      (s1, s2) => fileNameOrder.indexOf(s1.importPath) - fileNameOrder.indexOf(s2.importPath)
    );
  return stories;
}, sortStoriesV7 = (stories, storySortParameter, fileNameOrder) => {
  try {
    return sortStoriesCommon(stories, storySortParameter, fileNameOrder);
  } catch (err) {
    throw new Error(dedent`
    Error sorting stories with sort parameter ${storySortParameter}:

    > ${err.message}

    Are you using a V6-style sort function in V7 mode?

    More info: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#v7-style-story-sort
  `);
  }
};

// src/preview-api/modules/preview-web/Preview.tsx
import { deprecate as deprecate2, logger as logger7 } from "storybook/internal/client-logger";
import {
  ARGTYPES_INFO_REQUEST,
  ARGTYPES_INFO_RESPONSE,
  CONFIG_ERROR,
  FORCE_REMOUNT,
  FORCE_RE_RENDER as FORCE_RE_RENDER2,
  GLOBALS_UPDATED,
  PREVIEW_INITIALIZED,
  RESET_STORY_ARGS as RESET_STORY_ARGS2,
  SET_GLOBALS,
  STORY_ARGS_UPDATED,
  STORY_HOT_UPDATED,
  STORY_INDEX_INVALIDATED,
  UPDATE_GLOBALS as UPDATE_GLOBALS2,
  UPDATE_STORY_ARGS as UPDATE_STORY_ARGS2
} from "storybook/internal/core-events";
import {
  CalledPreviewMethodBeforeInitializationError,
  MissingRenderToCanvasError,
  StoryIndexFetchError,
  StoryStoreAccessedBeforeInitializationError
} from "storybook/internal/preview-errors";
import { global as global5 } from "@storybook/global";

// src/preview-api/modules/preview-web/render/StoryRender.ts
import {
  PLAY_FUNCTION_THREW_EXCEPTION,
  STORY_FINISHED,
  STORY_RENDERED as STORY_RENDERED2,
  STORY_RENDER_PHASE_CHANGED,
  UNHANDLED_ERRORS_WHILE_PLAYING
} from "storybook/internal/core-events";
import {
  MountMustBeDestructuredError as MountMustBeDestructuredError2,
  NoStoryMountedError
} from "storybook/internal/preview-errors";

// src/preview-api/modules/preview-web/render/Render.ts
var PREPARE_ABORTED = new Error("prepareAborted");

// src/preview-api/modules/preview-web/render/StoryRender.ts
var { AbortController: AbortController2 } = globalThis;
function serializeError(error) {
  try {
    let { name = "Error", message = String(error), stack } = error;
    return { name, message, stack };
  } catch {
    return { name: "Error", message: String(error) };
  }
}
var StoryRender = class {
  constructor(channel, store, renderToScreen, callbacks, id, viewMode, renderOptions = { autoplay: !0, forceInitialArgs: !1 }, story) {
    this.channel = channel;
    this.store = store;
    this.renderToScreen = renderToScreen;
    this.callbacks = callbacks;
    this.id = id;
    this.viewMode = viewMode;
    this.renderOptions = renderOptions;
    this.type = "story";
    this.notYetRendered = !0;
    this.rerenderEnqueued = !1;
    this.disableKeyListeners = !1;
    this.teardownRender = () => {
    };
    this.torndown = !1;
    this.abortController = new AbortController2(), this.renderId = Date.now(), story && (this.story = story, this.phase = "preparing");
  }
  async runPhase(signal, phase, phaseFn) {
    this.phase = phase, this.channel.emit(STORY_RENDER_PHASE_CHANGED, {
      newPhase: this.phase,
      renderId: this.renderId,
      storyId: this.id
    }), phaseFn && (await phaseFn(), this.checkIfAborted(signal));
  }
  checkIfAborted(signal) {
    return signal.aborted && !["finished", "aborted", "errored"].includes(this.phase) && (this.phase = "aborted", this.channel.emit(STORY_RENDER_PHASE_CHANGED, {
      newPhase: this.phase,
      renderId: this.renderId,
      storyId: this.id
    })), signal.aborted;
  }
  async prepare() {
    if (await this.runPhase(this.abortController.signal, "preparing", async () => {
      this.story = await this.store.loadStory({ storyId: this.id });
    }), this.abortController.signal.aborted)
      throw await this.store.cleanupStory(this.story), PREPARE_ABORTED;
  }
  // The two story "renders" are equal and have both loaded the same story
  isEqual(other) {
    return !!(this.id === other.id && this.story && this.story === other.story);
  }
  isPreparing() {
    return ["preparing"].includes(this.phase);
  }
  isPending() {
    return ["loading", "beforeEach", "rendering", "playing", "afterEach"].includes(
      this.phase
    );
  }
  async renderToElement(canvasElement) {
    return this.canvasElement = canvasElement, this.render({ initial: !0, forceRemount: !0 });
  }
  storyContext() {
    if (!this.story)
      throw new Error("Cannot call storyContext before preparing");
    let { forceInitialArgs } = this.renderOptions;
    return this.store.getStoryContext(this.story, { forceInitialArgs });
  }
  async render({
    initial = !1,
    forceRemount = !1
  } = {}) {
    let { canvasElement } = this;
    if (!this.story)
      throw new Error("cannot render when not prepared");
    let story = this.story;
    if (!canvasElement)
      throw new Error("cannot render when canvasElement is unset");
    let {
      id,
      componentId,
      title,
      name,
      tags,
      applyLoaders,
      applyBeforeEach,
      applyAfterEach,
      unboundStoryFn,
      playFunction,
      runStep
    } = story;
    forceRemount && !initial && (this.cancelRender(), this.abortController = new AbortController2());
    let abortSignal = this.abortController.signal, mounted = !1, isMountDestructured = story.usesMount;
    try {
      let context = {
        ...this.storyContext(),
        viewMode: this.viewMode,
        abortSignal,
        canvasElement,
        loaded: {},
        step: (label, play) => runStep(label, play, context),
        context: null,
        canvas: {},
        userEvent: {},
        renderToCanvas: async () => {
          let teardown = await this.renderToScreen(renderContext, canvasElement);
          this.teardownRender = teardown || (() => {
          }), mounted = !0;
        },
        // The story provides (set in a renderer) a mount function that is a higher order function
        // (context) => (...args) => Canvas
        //
        // Before assigning it to the context, we resolve the context dependency,
        // so that a user can just call it as await mount(...args) in their play function.
        mount: async (...args) => {
          this.callbacks.showStoryDuringRender?.();
          let mountReturn = null;
          return await this.runPhase(abortSignal, "rendering", async () => {
            mountReturn = await story.mount(context)(...args);
          }), isMountDestructured && await this.runPhase(abortSignal, "playing"), mountReturn;
        }
      };
      context.context = context;
      let renderContext = {
        componentId,
        title,
        kind: title,
        id,
        name,
        story: name,
        tags,
        ...this.callbacks,
        showError: (error) => (this.phase = "errored", this.callbacks.showError(error)),
        showException: (error) => (this.phase = "errored", this.callbacks.showException(error)),
        forceRemount: forceRemount || this.notYetRendered,
        storyContext: context,
        storyFn: () => unboundStoryFn(context),
        unboundStoryFn
      };
      if (await this.runPhase(abortSignal, "loading", async () => {
        context.loaded = await applyLoaders(context);
      }), abortSignal.aborted)
        return;
      let cleanupCallbacks = await applyBeforeEach(context);
      if (this.store.addCleanupCallbacks(story, ...cleanupCallbacks), this.checkIfAborted(abortSignal) || (!mounted && !isMountDestructured && await context.mount(), this.notYetRendered = !1, abortSignal.aborted))
        return;
      let ignoreUnhandledErrors = this.story.parameters?.test?.dangerouslyIgnoreUnhandledErrors === !0, unhandledErrors = /* @__PURE__ */ new Set(), onError = (event) => {
        event.error && unhandledErrors.add(event.error);
      }, onUnhandledRejection = (event) => {
        event.reason && unhandledErrors.add(event.reason);
      };
      if (this.renderOptions.autoplay && forceRemount && playFunction && this.phase !== "errored") {
        window?.addEventListener?.("error", onError), window?.addEventListener?.("unhandledrejection", onUnhandledRejection), this.disableKeyListeners = !0;
        try {
          if (isMountDestructured ? await playFunction(context) : (context.mount = async () => {
            throw new MountMustBeDestructuredError2({ playFunction: playFunction.toString() });
          }, await this.runPhase(abortSignal, "playing", async () => playFunction(context))), !mounted)
            throw new NoStoryMountedError();
          this.checkIfAborted(abortSignal), !ignoreUnhandledErrors && unhandledErrors.size > 0 ? await this.runPhase(abortSignal, "errored") : await this.runPhase(abortSignal, "played");
        } catch (error) {
          if (this.callbacks.showStoryDuringRender?.(), await this.runPhase(abortSignal, "errored", async () => {
            this.channel.emit(PLAY_FUNCTION_THREW_EXCEPTION, serializeError(error));
          }), this.story.parameters.throwPlayFunctionExceptions !== !1)
            throw error;
          console.error(error);
        }
        if (!ignoreUnhandledErrors && unhandledErrors.size > 0 && this.channel.emit(
          UNHANDLED_ERRORS_WHILE_PLAYING,
          Array.from(unhandledErrors).map(serializeError)
        ), this.disableKeyListeners = !1, window?.removeEventListener?.("unhandledrejection", onUnhandledRejection), window?.removeEventListener?.("error", onError), abortSignal.aborted)
          return;
      }
      await this.runPhase(abortSignal, "completing", async () => {
        isTestEnvironment() ? this.store.addCleanupCallbacks(story, pauseAnimations()) : await waitForAnimations(abortSignal);
      }), await this.runPhase(abortSignal, "completed", async () => {
        this.channel.emit(STORY_RENDERED2, id);
      }), this.phase !== "errored" && await this.runPhase(abortSignal, "afterEach", async () => {
        await applyAfterEach(context);
      });
      let hasUnhandledErrors = !ignoreUnhandledErrors && unhandledErrors.size > 0, hasSomeReportsFailed = context.reporting.reports.some(
        (report) => report.status === "failed"
      ), hasStoryErrored = hasUnhandledErrors || hasSomeReportsFailed;
      await this.runPhase(
        abortSignal,
        "finished",
        async () => this.channel.emit(STORY_FINISHED, {
          storyId: id,
          status: hasStoryErrored ? "error" : "success",
          reporters: context.reporting.reports
        })
      );
    } catch (err) {
      this.phase = "errored", this.callbacks.showException(err), await this.runPhase(
        abortSignal,
        "finished",
        async () => this.channel.emit(STORY_FINISHED, {
          storyId: id,
          status: "error",
          reporters: []
        })
      );
    }
    this.rerenderEnqueued && (this.rerenderEnqueued = !1, this.render());
  }
  /**
   * Rerender the story. If the story is currently pending (loading/rendering), the rerender will be
   * enqueued, and will be executed after the current render is completed. Rerendering while playing
   * will not be enqueued, and will be executed immediately, to support rendering args changes while
   * playing.
   */
  async rerender() {
    if (this.isPending() && this.phase !== "playing")
      this.rerenderEnqueued = !0;
    else
      return this.render();
  }
  async remount() {
    return await this.teardown(), this.render({ forceRemount: !0 });
  }
  // If the story is torn down (either a new story is rendered or the docs page removes it)
  // we need to consider the fact that the initial render may not be finished
  // (possibly the loaders or the play function are still running). We use the controller
  // as a method to abort them, ASAP, but this is not foolproof as we cannot control what
  // happens inside the user's code.
  cancelRender() {
    this.abortController.abort();
  }
  cancelPlayFunction() {
    this.phase === "playing" && (this.abortController.abort(), this.runPhase(this.abortController.signal, "aborted"));
  }
  async teardown() {
    this.torndown = !0, this.cancelRender(), this.story && await this.store.cleanupStory(this.story);
    for (let i = 0; i < 3; i += 1) {
      if (!this.isPending()) {
        await this.teardownRender();
        return;
      }
      await new Promise((resolve) => setTimeout(resolve, 0));
    }
    window?.location?.reload?.(), await new Promise(() => {
    });
  }
};

// src/preview-api/modules/preview-web/Preview.tsx
var { fetch } = global5, STORY_INDEX_PATH = "./index.json", Preview = class {
  constructor(importFn, getProjectAnnotations, channel = addons.getChannel(), shouldInitialize = !0) {
    this.importFn = importFn;
    this.getProjectAnnotations = getProjectAnnotations;
    this.channel = channel;
    this.storyRenders = [];
    this.storeInitializationPromise = new Promise((resolve, reject) => {
      this.resolveStoreInitializationPromise = resolve, this.rejectStoreInitializationPromise = reject;
    }), shouldInitialize && this.initialize();
  }
  // Create a proxy object for `__STORYBOOK_STORY_STORE__` and `__STORYBOOK_PREVIEW__.storyStore`
  // That proxies through to the store once ready, and errors beforehand. This means we can set
  // `__STORYBOOK_STORY_STORE__ = __STORYBOOK_PREVIEW__.storyStore` without having to wait, and
  // similarly integrators can access the `storyStore` on the preview at any time, although
  // it is considered deprecated and we will no longer allow access in 9.0
  get storyStore() {
    return new Proxy(
      {},
      {
        get: (_, method) => {
          if (this.storyStoreValue)
            return deprecate2("Accessing the Story Store is deprecated and will be removed in 9.0"), this.storyStoreValue[method];
          throw new StoryStoreAccessedBeforeInitializationError();
        }
      }
    );
  }
  // INITIALIZATION
  async initialize() {
    this.setupListeners();
    try {
      let projectAnnotations = await this.getProjectAnnotationsOrRenderError();
      await this.runBeforeAllHook(projectAnnotations), await this.initializeWithProjectAnnotations(projectAnnotations);
      let userAgent = globalThis?.navigator?.userAgent;
      await this.channel.emit(PREVIEW_INITIALIZED, { userAgent });
    } catch (err) {
      this.rejectStoreInitializationPromise(err);
    }
  }
  ready() {
    return this.storeInitializationPromise;
  }
  setupListeners() {
    this.channel.on(STORY_INDEX_INVALIDATED, this.onStoryIndexChanged.bind(this)), this.channel.on(UPDATE_GLOBALS2, this.onUpdateGlobals.bind(this)), this.channel.on(UPDATE_STORY_ARGS2, this.onUpdateArgs.bind(this)), this.channel.on(ARGTYPES_INFO_REQUEST, this.onRequestArgTypesInfo.bind(this)), this.channel.on(RESET_STORY_ARGS2, this.onResetArgs.bind(this)), this.channel.on(FORCE_RE_RENDER2, this.onForceReRender.bind(this)), this.channel.on(FORCE_REMOUNT, this.onForceRemount.bind(this)), this.channel.on(STORY_HOT_UPDATED, this.onStoryHotUpdated.bind(this));
  }
  async getProjectAnnotationsOrRenderError() {
    try {
      let projectAnnotations = await this.getProjectAnnotations();
      if (this.renderToCanvas = projectAnnotations.renderToCanvas, !this.renderToCanvas)
        throw new MissingRenderToCanvasError();
      return projectAnnotations;
    } catch (err) {
      throw this.renderPreviewEntryError("Error reading preview.js:", err), err;
    }
  }
  // If initialization gets as far as project annotations, this function runs.
  async initializeWithProjectAnnotations(projectAnnotations) {
    this.projectAnnotationsBeforeInitialization = projectAnnotations;
    try {
      let storyIndex = await this.getStoryIndexFromServer();
      return this.initializeWithStoryIndex(storyIndex);
    } catch (err) {
      throw this.renderPreviewEntryError("Error loading story index:", err), err;
    }
  }
  async runBeforeAllHook(projectAnnotations) {
    try {
      await this.beforeAllCleanup?.(), this.beforeAllCleanup = await projectAnnotations.beforeAll?.();
    } catch (err) {
      throw this.renderPreviewEntryError("Error in beforeAll hook:", err), err;
    }
  }
  async getStoryIndexFromServer() {
    let result = await fetch(STORY_INDEX_PATH);
    if (result.status === 200)
      return result.json();
    throw new StoryIndexFetchError({ text: await result.text() });
  }
  // If initialization gets as far as the story index, this function runs.
  initializeWithStoryIndex(storyIndex) {
    if (!this.projectAnnotationsBeforeInitialization)
      throw new Error("Cannot call initializeWithStoryIndex until project annotations resolve");
    this.storyStoreValue = new StoryStore(
      storyIndex,
      this.importFn,
      this.projectAnnotationsBeforeInitialization
    ), delete this.projectAnnotationsBeforeInitialization, this.setInitialGlobals(), this.resolveStoreInitializationPromise();
  }
  async setInitialGlobals() {
    this.emitGlobals();
  }
  emitGlobals() {
    if (!this.storyStoreValue)
      throw new CalledPreviewMethodBeforeInitializationError({ methodName: "emitGlobals" });
    let payload = {
      globals: this.storyStoreValue.userGlobals.get() || {},
      globalTypes: this.storyStoreValue.projectAnnotations.globalTypes || {}
    };
    this.channel.emit(SET_GLOBALS, payload);
  }
  // EVENT HANDLERS
  // This happens when a config file gets reloaded
  async onGetProjectAnnotationsChanged({
    getProjectAnnotations
  }) {
    delete this.previewEntryError, this.getProjectAnnotations = getProjectAnnotations;
    let projectAnnotations = await this.getProjectAnnotationsOrRenderError();
    if (await this.runBeforeAllHook(projectAnnotations), !this.storyStoreValue) {
      await this.initializeWithProjectAnnotations(projectAnnotations);
      return;
    }
    this.storyStoreValue.setProjectAnnotations(projectAnnotations), this.emitGlobals();
  }
  async onStoryIndexChanged() {
    if (delete this.previewEntryError, !(!this.storyStoreValue && !this.projectAnnotationsBeforeInitialization))
      try {
        let storyIndex = await this.getStoryIndexFromServer();
        if (this.projectAnnotationsBeforeInitialization) {
          this.initializeWithStoryIndex(storyIndex);
          return;
        }
        await this.onStoriesChanged({ storyIndex });
      } catch (err) {
        throw this.renderPreviewEntryError("Error loading story index:", err), err;
      }
  }
  // This happens when a glob gets HMR-ed
  async onStoriesChanged({
    importFn,
    storyIndex
  }) {
    if (!this.storyStoreValue)
      throw new CalledPreviewMethodBeforeInitializationError({ methodName: "onStoriesChanged" });
    await this.storyStoreValue.onStoriesChanged({ importFn, storyIndex });
  }
  async onUpdateGlobals({
    globals: updatedGlobals,
    currentStory
  }) {
    if (this.storyStoreValue || await this.storeInitializationPromise, !this.storyStoreValue)
      throw new CalledPreviewMethodBeforeInitializationError({ methodName: "onUpdateGlobals" });
    if (this.storyStoreValue.userGlobals.update(updatedGlobals), currentStory) {
      let { initialGlobals, storyGlobals, userGlobals, globals } = this.storyStoreValue.getStoryContext(currentStory);
      this.channel.emit(GLOBALS_UPDATED, {
        initialGlobals,
        userGlobals,
        storyGlobals,
        globals
      });
    } else {
      let { initialGlobals, globals } = this.storyStoreValue.userGlobals;
      this.channel.emit(GLOBALS_UPDATED, {
        initialGlobals,
        userGlobals: globals,
        storyGlobals: {},
        globals
      });
    }
    await Promise.all(this.storyRenders.map((r) => r.rerender()));
  }
  async onUpdateArgs({ storyId, updatedArgs }) {
    if (!this.storyStoreValue)
      throw new CalledPreviewMethodBeforeInitializationError({ methodName: "onUpdateArgs" });
    this.storyStoreValue.args.update(storyId, updatedArgs), await Promise.all(
      this.storyRenders.filter((r) => r.id === storyId && !r.renderOptions.forceInitialArgs).map(
        (r) => (
          // We only run the play function, with in a force remount.
          // But when mount is destructured, the rendering happens inside of the play function.
          r.story && r.story.usesMount ? r.remount() : r.rerender()
        )
      )
    ), this.channel.emit(STORY_ARGS_UPDATED, {
      storyId,
      args: this.storyStoreValue.args.get(storyId)
    });
  }
  async onRequestArgTypesInfo({ id, payload }) {
    try {
      await this.storeInitializationPromise;
      let story = await this.storyStoreValue?.loadStory(payload);
      this.channel.emit(ARGTYPES_INFO_RESPONSE, {
        id,
        success: !0,
        payload: { argTypes: story?.argTypes || {} },
        error: null
      });
    } catch (e) {
      this.channel.emit(ARGTYPES_INFO_RESPONSE, {
        id,
        success: !1,
        error: e?.message
      });
    }
  }
  async onResetArgs({ storyId, argNames }) {
    if (!this.storyStoreValue)
      throw new CalledPreviewMethodBeforeInitializationError({ methodName: "onResetArgs" });
    let story = this.storyRenders.find((r) => r.id === storyId)?.story || await this.storyStoreValue.loadStory({ storyId }), updatedArgs = (argNames || [
      .../* @__PURE__ */ new Set([
        ...Object.keys(story.initialArgs),
        ...Object.keys(this.storyStoreValue.args.get(storyId))
      ])
    ]).reduce((acc, argName) => (acc[argName] = story.initialArgs[argName], acc), {});
    await this.onUpdateArgs({ storyId, updatedArgs });
  }
  // ForceReRender does not include a story id, so we simply must
  // re-render all stories in case they are relevant
  async onForceReRender() {
    await Promise.all(this.storyRenders.map((r) => r.rerender()));
  }
  async onForceRemount({ storyId }) {
    await Promise.all(this.storyRenders.filter((r) => r.id === storyId).map((r) => r.remount()));
  }
  async onStoryHotUpdated() {
    await Promise.all(this.storyRenders.map((r) => r.cancelPlayFunction()));
  }
  // Used by docs to render a story to a given element
  // Note this short-circuits the `prepare()` phase of the StoryRender,
  // main to be consistent with the previous behaviour. In the future,
  // we will change it to go ahead and load the story, which will end up being
  // "instant", although async.
  renderStoryToElement(story, element, callbacks, options) {
    if (!this.renderToCanvas || !this.storyStoreValue)
      throw new CalledPreviewMethodBeforeInitializationError({
        methodName: "renderStoryToElement"
      });
    let render = new StoryRender(
      this.channel,
      this.storyStoreValue,
      this.renderToCanvas,
      callbacks,
      story.id,
      "docs",
      options,
      story
    );
    return render.renderToElement(element), this.storyRenders.push(render), async () => {
      await this.teardownRender(render);
    };
  }
  async teardownRender(render, { viewModeChanged } = {}) {
    this.storyRenders = this.storyRenders.filter((r) => r !== render), await render?.teardown?.({ viewModeChanged });
  }
  // API
  async loadStory({ storyId }) {
    if (!this.storyStoreValue)
      throw new CalledPreviewMethodBeforeInitializationError({ methodName: "loadStory" });
    return this.storyStoreValue.loadStory({ storyId });
  }
  getStoryContext(story, { forceInitialArgs = !1 } = {}) {
    if (!this.storyStoreValue)
      throw new CalledPreviewMethodBeforeInitializationError({ methodName: "getStoryContext" });
    return this.storyStoreValue.getStoryContext(story, { forceInitialArgs });
  }
  async extract(options) {
    if (!this.storyStoreValue)
      throw new CalledPreviewMethodBeforeInitializationError({ methodName: "extract" });
    if (this.previewEntryError)
      throw this.previewEntryError;
    return await this.storyStoreValue.cacheAllCSFFiles(), this.storyStoreValue.extract(options);
  }
  // UTILITIES
  renderPreviewEntryError(reason, err) {
    this.previewEntryError = err, logger7.error(reason), logger7.error(err), this.channel.emit(CONFIG_ERROR, err);
  }
};

// src/preview-api/modules/preview-web/PreviewWeb.tsx
import { global as global8 } from "@storybook/global";

// src/preview-api/modules/preview-web/PreviewWithSelection.tsx
import { logger as logger8 } from "storybook/internal/client-logger";
import {
  CURRENT_STORY_WAS_SET,
  DOCS_PREPARED,
  GLOBALS_UPDATED as GLOBALS_UPDATED2,
  PRELOAD_ENTRIES,
  PREVIEW_KEYDOWN,
  SET_CURRENT_STORY,
  STORY_CHANGED,
  STORY_ERRORED,
  STORY_MISSING,
  STORY_PREPARED,
  STORY_RENDER_PHASE_CHANGED as STORY_RENDER_PHASE_CHANGED2,
  STORY_SPECIFIED,
  STORY_THREW_EXCEPTION,
  STORY_UNCHANGED,
  UPDATE_QUERY_PARAMS
} from "storybook/internal/core-events";
import {
  CalledPreviewMethodBeforeInitializationError as CalledPreviewMethodBeforeInitializationError2,
  EmptyIndexError,
  MdxFileWithNoCsfReferencesError,
  NoStoryMatchError
} from "storybook/internal/preview-errors";

// src/preview-api/modules/preview-web/render/CsfDocsRender.ts
import { DOCS_RENDERED } from "storybook/internal/core-events";

// src/preview-api/modules/preview-web/docs-context/DocsContext.ts
import { isStory as isStory3 } from "storybook/internal/csf";
var DocsContext = class {
  constructor(channel, store, renderStoryToElement, csfFiles) {
    this.channel = channel;
    this.store = store;
    this.renderStoryToElement = renderStoryToElement;
    this.storyIdByName = (storyName) => {
      let storyId = this.nameToStoryId.get(storyName);
      if (storyId)
        return storyId;
      throw new Error(`No story found with that name: ${storyName}`);
    };
    this.componentStories = () => this.componentStoriesValue;
    this.componentStoriesFromCSFFile = (csfFile) => this.store.componentStoriesFromCSFFile({ csfFile });
    this.storyById = (storyId) => {
      if (!storyId) {
        if (!this.primaryStory)
          throw new Error(
            "No primary story defined for docs entry. Did you forget to use `<Meta>`?"
          );
        return this.primaryStory;
      }
      let csfFile = this.storyIdToCSFFile.get(storyId);
      if (!csfFile)
        throw new Error(`Called \`storyById\` for story that was never loaded: ${storyId}`);
      return this.store.storyFromCSFFile({ storyId, csfFile });
    };
    this.getStoryContext = (story) => ({
      ...this.store.getStoryContext(story),
      loaded: {},
      viewMode: "docs"
    });
    this.loadStory = (id) => this.store.loadStory({ storyId: id });
    this.componentStoriesValue = [], this.storyIdToCSFFile = /* @__PURE__ */ new Map(), this.exportToStory = /* @__PURE__ */ new Map(), this.exportsToCSFFile = /* @__PURE__ */ new Map(), this.nameToStoryId = /* @__PURE__ */ new Map(), this.attachedCSFFiles = /* @__PURE__ */ new Set(), csfFiles.forEach((csfFile, index) => {
      this.referenceCSFFile(csfFile);
    });
  }
  // This docs entry references this CSF file and can synchronously load the stories, as well
  // as reference them by module export. If the CSF is part of the "component" stories, they
  // can also be referenced by name and are in the componentStories list.
  referenceCSFFile(csfFile) {
    this.exportsToCSFFile.set(csfFile.moduleExports, csfFile), this.exportsToCSFFile.set(csfFile.moduleExports.default, csfFile), this.store.componentStoriesFromCSFFile({ csfFile }).forEach((story) => {
      let annotation = csfFile.stories[story.id];
      this.storyIdToCSFFile.set(annotation.id, csfFile), this.exportToStory.set(annotation.moduleExport, story);
    });
  }
  attachCSFFile(csfFile) {
    if (!this.exportsToCSFFile.has(csfFile.moduleExports))
      throw new Error("Cannot attach a CSF file that has not been referenced");
    if (this.attachedCSFFiles.has(csfFile))
      return;
    this.attachedCSFFiles.add(csfFile), this.store.componentStoriesFromCSFFile({ csfFile }).forEach((story) => {
      this.nameToStoryId.set(story.name, story.id), this.componentStoriesValue.push(story), this.primaryStory || (this.primaryStory = story);
    });
  }
  referenceMeta(metaExports, attach) {
    let resolved = this.resolveModuleExport(metaExports);
    if (resolved.type !== "meta")
      throw new Error(
        "<Meta of={} /> must reference a CSF file module export or meta export. Did you mistakenly reference your component instead of your CSF file?"
      );
    attach && this.attachCSFFile(resolved.csfFile);
  }
  get projectAnnotations() {
    let { projectAnnotations } = this.store;
    if (!projectAnnotations)
      throw new Error("Can't get projectAnnotations from DocsContext before they are initialized");
    return projectAnnotations;
  }
  resolveAttachedModuleExportType(moduleExportType) {
    if (moduleExportType === "story") {
      if (!this.primaryStory)
        throw new Error(
          "No primary story attached to this docs file, did you forget to use <Meta of={} />?"
        );
      return { type: "story", story: this.primaryStory };
    }
    if (this.attachedCSFFiles.size === 0)
      throw new Error(
        "No CSF file attached to this docs file, did you forget to use <Meta of={} />?"
      );
    let firstAttachedCSFFile = Array.from(this.attachedCSFFiles)[0];
    if (moduleExportType === "meta")
      return { type: "meta", csfFile: firstAttachedCSFFile };
    let { component } = firstAttachedCSFFile.meta;
    if (!component)
      throw new Error(
        "Attached CSF file does not defined a component, did you forget to export one?"
      );
    return { type: "component", component };
  }
  resolveModuleExport(moduleExportOrType) {
    let csfFile = this.exportsToCSFFile.get(moduleExportOrType);
    if (!csfFile && moduleExportOrType && typeof moduleExportOrType == "object" && "default" in moduleExportOrType && (csfFile = this.exportsToCSFFile.get(moduleExportOrType.default)), csfFile)
      return { type: "meta", csfFile };
    let story = this.exportToStory.get(
      isStory3(moduleExportOrType) ? moduleExportOrType.input : moduleExportOrType
    );
    return story ? { type: "story", story } : { type: "component", component: moduleExportOrType };
  }
  resolveOf(moduleExportOrType, validTypes = []) {
    let resolved;
    if (["component", "meta", "story"].includes(moduleExportOrType)) {
      let type = moduleExportOrType;
      resolved = this.resolveAttachedModuleExportType(type);
    } else
      resolved = this.resolveModuleExport(moduleExportOrType);
    if (validTypes.length && !validTypes.includes(resolved.type)) {
      let prettyType = resolved.type === "component" ? "component or unknown" : resolved.type;
      throw new Error(dedent`Invalid value passed to the 'of' prop. The value was resolved to a '${prettyType}' type but the only types for this block are: ${validTypes.join(
        ", "
      )}.
        - Did you pass a component to the 'of' prop when the block only supports a story or a meta?
        - ... or vice versa?
        - Did you pass a story, CSF file or meta to the 'of' prop that is not indexed, ie. is not targeted by the 'stories' globs in the main configuration?`);
    }
    switch (resolved.type) {
      case "component":
        return {
          ...resolved,
          projectAnnotations: this.projectAnnotations
        };
      case "meta":
        return {
          ...resolved,
          preparedMeta: this.store.preparedMetaFromCSFFile({ csfFile: resolved.csfFile })
        };
      case "story":
      default:
        return resolved;
    }
  }
};

// src/preview-api/modules/preview-web/render/CsfDocsRender.ts
var CsfDocsRender = class {
  constructor(channel, store, entry, callbacks) {
    this.channel = channel;
    this.store = store;
    this.entry = entry;
    this.callbacks = callbacks;
    this.type = "docs";
    this.subtype = "csf";
    this.torndown = !1;
    this.disableKeyListeners = !1;
    this.preparing = !1;
    this.id = entry.id, this.renderId = Date.now();
  }
  isPreparing() {
    return this.preparing;
  }
  async prepare() {
    this.preparing = !0;
    let { entryExports, csfFiles = [] } = await this.store.loadEntry(this.id);
    if (this.torndown)
      throw PREPARE_ABORTED;
    let { importPath, title } = this.entry, primaryCsfFile = this.store.processCSFFileWithCache(
      entryExports,
      importPath,
      title
    ), primaryStoryId = Object.keys(primaryCsfFile.stories)[0];
    this.story = this.store.storyFromCSFFile({ storyId: primaryStoryId, csfFile: primaryCsfFile }), this.csfFiles = [primaryCsfFile, ...csfFiles], this.preparing = !1;
  }
  isEqual(other) {
    return !!(this.id === other.id && this.story && this.story === other.story);
  }
  docsContext(renderStoryToElement) {
    if (!this.csfFiles)
      throw new Error("Cannot render docs before preparing");
    let docsContext = new DocsContext(
      this.channel,
      this.store,
      renderStoryToElement,
      this.csfFiles
    );
    return this.csfFiles.forEach((csfFile) => docsContext.attachCSFFile(csfFile)), docsContext;
  }
  async renderToElement(canvasElement, renderStoryToElement) {
    if (!this.story || !this.csfFiles)
      throw new Error("Cannot render docs before preparing");
    let docsContext = this.docsContext(renderStoryToElement), { docs: docsParameter } = this.story.parameters || {};
    if (!docsParameter)
      throw new Error(
        "Cannot render a story in viewMode=docs if `@storybook/addon-docs` is not installed"
      );
    let renderer = await docsParameter.renderer(), { render } = renderer, renderDocs = async () => {
      try {
        await render(docsContext, docsParameter, canvasElement), this.channel.emit(DOCS_RENDERED, this.id);
      } catch (err) {
        this.callbacks.showException(err);
      }
    };
    return this.rerender = async () => renderDocs(), this.teardownRender = async ({ viewModeChanged }) => {
      !viewModeChanged || !canvasElement || renderer.unmount(canvasElement);
    }, renderDocs();
  }
  async teardown({ viewModeChanged } = {}) {
    this.teardownRender?.({ viewModeChanged }), this.torndown = !0;
  }
};

// src/preview-api/modules/preview-web/render/MdxDocsRender.ts
import { DOCS_RENDERED as DOCS_RENDERED2 } from "storybook/internal/core-events";
var MdxDocsRender = class {
  constructor(channel, store, entry, callbacks) {
    this.channel = channel;
    this.store = store;
    this.entry = entry;
    this.callbacks = callbacks;
    this.type = "docs";
    this.subtype = "mdx";
    this.torndown = !1;
    this.disableKeyListeners = !1;
    this.preparing = !1;
    this.id = entry.id, this.renderId = Date.now();
  }
  isPreparing() {
    return this.preparing;
  }
  async prepare() {
    this.preparing = !0;
    let { entryExports, csfFiles = [] } = await this.store.loadEntry(this.id);
    if (this.torndown)
      throw PREPARE_ABORTED;
    this.csfFiles = csfFiles, this.exports = entryExports, this.preparing = !1;
  }
  isEqual(other) {
    return !!(this.id === other.id && this.exports && this.exports === other.exports);
  }
  docsContext(renderStoryToElement) {
    if (!this.csfFiles)
      throw new Error("Cannot render docs before preparing");
    return new DocsContext(
      this.channel,
      this.store,
      renderStoryToElement,
      this.csfFiles
    );
  }
  async renderToElement(canvasElement, renderStoryToElement) {
    if (!this.exports || !this.csfFiles || !this.store.projectAnnotations)
      throw new Error("Cannot render docs before preparing");
    let docsContext = this.docsContext(renderStoryToElement), { docs } = this.store.projectAnnotations.parameters ?? {};
    if (!docs)
      throw new Error(
        "Cannot render a story in viewMode=docs if `@storybook/addon-docs` is not installed"
      );
    let docsParameter = { ...docs, page: this.exports.default }, renderer = await docs.renderer(), { render } = renderer, renderDocs = async () => {
      try {
        await render(docsContext, docsParameter, canvasElement), this.channel.emit(DOCS_RENDERED2, this.id);
      } catch (err) {
        this.callbacks.showException(err);
      }
    };
    return this.rerender = async () => renderDocs(), this.teardownRender = async ({ viewModeChanged } = {}) => {
      !viewModeChanged || !canvasElement || (renderer.unmount(canvasElement), this.torndown = !0);
    }, renderDocs();
  }
  async teardown({ viewModeChanged } = {}) {
    this.teardownRender?.({ viewModeChanged }), this.torndown = !0;
  }
};

// src/preview-api/modules/preview-web/PreviewWithSelection.tsx
var globalWindow = globalThis;
function focusInInput(event) {
  let target = event.composedPath && event.composedPath()[0] || event.target;
  return /input|textarea/i.test(target.tagName) || target.getAttribute("contenteditable") !== null;
}
var ATTACHED_MDX_TAG = "attached-mdx", UNATTACHED_MDX_TAG = "unattached-mdx";
function isMdxEntry({ tags }) {
  return tags?.includes(UNATTACHED_MDX_TAG) || tags?.includes(ATTACHED_MDX_TAG);
}
function isStoryRender(r) {
  return r.type === "story";
}
function isDocsRender(r) {
  return r.type === "docs";
}
function isCsfDocsRender(r) {
  return isDocsRender(r) && r.subtype === "csf";
}
var PreviewWithSelection = class extends Preview {
  constructor(importFn, getProjectAnnotations, selectionStore, view) {
    super(importFn, getProjectAnnotations, void 0, !1);
    this.importFn = importFn;
    this.getProjectAnnotations = getProjectAnnotations;
    this.selectionStore = selectionStore;
    this.view = view;
    this.initialize();
  }
  setupListeners() {
    super.setupListeners(), globalWindow.onkeydown = this.onKeydown.bind(this), this.channel.on(SET_CURRENT_STORY, this.onSetCurrentStory.bind(this)), this.channel.on(UPDATE_QUERY_PARAMS, this.onUpdateQueryParams.bind(this)), this.channel.on(PRELOAD_ENTRIES, this.onPreloadStories.bind(this));
  }
  async setInitialGlobals() {
    if (!this.storyStoreValue)
      throw new CalledPreviewMethodBeforeInitializationError2({ methodName: "setInitialGlobals" });
    let { globals } = this.selectionStore.selectionSpecifier || {};
    globals && this.storyStoreValue.userGlobals.updateFromPersisted(globals), this.emitGlobals();
  }
  // If initialization gets as far as the story index, this function runs.
  async initializeWithStoryIndex(storyIndex) {
    return await super.initializeWithStoryIndex(storyIndex), this.selectSpecifiedStory();
  }
  // Use the selection specifier to choose a story, then render it
  async selectSpecifiedStory() {
    if (!this.storyStoreValue)
      throw new CalledPreviewMethodBeforeInitializationError2({
        methodName: "selectSpecifiedStory"
      });
    if (this.selectionStore.selection) {
      await this.renderSelection();
      return;
    }
    if (!this.selectionStore.selectionSpecifier) {
      this.renderMissingStory();
      return;
    }
    let { storySpecifier, args } = this.selectionStore.selectionSpecifier, entry = this.storyStoreValue.storyIndex.entryFromSpecifier(storySpecifier);
    if (!entry) {
      storySpecifier === "*" ? this.renderStoryLoadingException(storySpecifier, new EmptyIndexError()) : this.renderStoryLoadingException(
        storySpecifier,
        new NoStoryMatchError({ storySpecifier: storySpecifier.toString() })
      );
      return;
    }
    let { id: storyId, type: viewMode } = entry;
    this.selectionStore.setSelection({ storyId, viewMode }), this.channel.emit(STORY_SPECIFIED, this.selectionStore.selection), this.channel.emit(CURRENT_STORY_WAS_SET, this.selectionStore.selection), await this.renderSelection({ persistedArgs: args });
  }
  // EVENT HANDLERS
  // This happens when a config file gets reloaded
  async onGetProjectAnnotationsChanged({
    getProjectAnnotations
  }) {
    await super.onGetProjectAnnotationsChanged({ getProjectAnnotations }), this.selectionStore.selection && this.renderSelection();
  }
  // This happens when a glob gets HMR-ed
  async onStoriesChanged({
    importFn,
    storyIndex
  }) {
    await super.onStoriesChanged({ importFn, storyIndex }), this.selectionStore.selection ? await this.renderSelection() : await this.selectSpecifiedStory();
  }
  onKeydown(event) {
    if (!this.storyRenders.find((r) => r.disableKeyListeners) && !focusInInput(event)) {
      let { altKey, ctrlKey, metaKey, shiftKey, key, code, keyCode } = event;
      this.channel.emit(PREVIEW_KEYDOWN, {
        event: { altKey, ctrlKey, metaKey, shiftKey, key, code, keyCode }
      });
    }
  }
  async onSetCurrentStory(selection) {
    this.selectionStore.setSelection({ viewMode: "story", ...selection }), await this.storeInitializationPromise, this.channel.emit(CURRENT_STORY_WAS_SET, this.selectionStore.selection), this.renderSelection();
  }
  onUpdateQueryParams(queryParams) {
    this.selectionStore.setQueryParams(queryParams);
  }
  async onUpdateGlobals({ globals }) {
    let currentStory = this.currentRender instanceof StoryRender && this.currentRender.story || void 0;
    super.onUpdateGlobals({ globals, currentStory }), (this.currentRender instanceof MdxDocsRender || this.currentRender instanceof CsfDocsRender) && await this.currentRender.rerender?.();
  }
  async onUpdateArgs({ storyId, updatedArgs }) {
    super.onUpdateArgs({ storyId, updatedArgs });
  }
  async onPreloadStories({ ids }) {
    await this.storeInitializationPromise, this.storyStoreValue && await Promise.allSettled(ids.map((id) => this.storyStoreValue?.loadEntry(id)));
  }
  // RENDERING
  // We can either have:
  // - a story selected in "story" viewMode,
  //     in which case we render it to the root element, OR
  // - a story selected in "docs" viewMode,
  //     in which case we render the docsPage for that story
  async renderSelection({ persistedArgs } = {}) {
    let { renderToCanvas } = this;
    if (!this.storyStoreValue || !renderToCanvas)
      throw new CalledPreviewMethodBeforeInitializationError2({ methodName: "renderSelection" });
    let { selection } = this.selectionStore;
    if (!selection)
      throw new Error("Cannot call renderSelection as no selection was made");
    let { storyId } = selection, entry;
    try {
      entry = await this.storyStoreValue.storyIdToEntry(storyId);
    } catch (err) {
      this.currentRender && await this.teardownRender(this.currentRender), this.renderStoryLoadingException(storyId, err);
      return;
    }
    let storyIdChanged = this.currentSelection?.storyId !== storyId, viewModeChanged = this.currentRender?.type !== entry.type;
    entry.type === "story" ? this.view.showPreparingStory({ immediate: viewModeChanged }) : this.view.showPreparingDocs({ immediate: viewModeChanged }), this.currentRender?.isPreparing() && await this.teardownRender(this.currentRender);
    let render;
    entry.type === "story" ? render = new StoryRender(
      this.channel,
      this.storyStoreValue,
      renderToCanvas,
      this.mainStoryCallbacks(storyId),
      storyId,
      "story"
    ) : isMdxEntry(entry) ? render = new MdxDocsRender(
      this.channel,
      this.storyStoreValue,
      entry,
      this.mainStoryCallbacks(storyId)
    ) : render = new CsfDocsRender(
      this.channel,
      this.storyStoreValue,
      entry,
      this.mainStoryCallbacks(storyId)
    );
    let lastSelection = this.currentSelection;
    this.currentSelection = selection;
    let lastRender = this.currentRender;
    this.currentRender = render;
    try {
      await render.prepare();
    } catch (err) {
      lastRender && await this.teardownRender(lastRender), err !== PREPARE_ABORTED && this.renderStoryLoadingException(storyId, err);
      return;
    }
    let implementationChanged = !storyIdChanged && lastRender && !render.isEqual(lastRender);
    if (persistedArgs && isStoryRender(render) && (invariant(!!render.story), this.storyStoreValue.args.updateFromPersisted(render.story, persistedArgs)), lastRender && !lastRender.torndown && !storyIdChanged && !implementationChanged && !viewModeChanged) {
      this.currentRender = lastRender, this.channel.emit(STORY_UNCHANGED, storyId), this.view.showMain();
      return;
    }
    if (lastRender && await this.teardownRender(lastRender, { viewModeChanged }), lastSelection && (storyIdChanged || viewModeChanged) && this.channel.emit(STORY_CHANGED, storyId), isStoryRender(render)) {
      invariant(!!render.story);
      let {
        parameters,
        initialArgs,
        argTypes,
        unmappedArgs,
        initialGlobals,
        userGlobals,
        storyGlobals,
        globals
      } = this.storyStoreValue.getStoryContext(render.story);
      this.channel.emit(STORY_PREPARED, {
        id: storyId,
        parameters,
        initialArgs,
        argTypes,
        args: unmappedArgs
      }), this.channel.emit(GLOBALS_UPDATED2, { userGlobals, storyGlobals, globals, initialGlobals });
    } else {
      let { parameters } = this.storyStoreValue.projectAnnotations, { initialGlobals, globals } = this.storyStoreValue.userGlobals;
      if (this.channel.emit(GLOBALS_UPDATED2, {
        globals,
        initialGlobals,
        storyGlobals: {},
        userGlobals: globals
      }), isCsfDocsRender(render) || render.entry.tags?.includes(ATTACHED_MDX_TAG)) {
        if (!render.csfFiles)
          throw new MdxFileWithNoCsfReferencesError({ storyId });
        ({ parameters } = this.storyStoreValue.preparedMetaFromCSFFile({
          csfFile: render.csfFiles[0]
        }));
      }
      this.channel.emit(DOCS_PREPARED, {
        id: storyId,
        parameters
      });
    }
    isStoryRender(render) ? (invariant(!!render.story), this.storyRenders.push(render), this.currentRender.renderToElement(
      this.view.prepareForStory(render.story)
    )) : this.currentRender.renderToElement(
      this.view.prepareForDocs(),
      // This argument is used for docs, which is currently only compatible with HTMLElements
      this.renderStoryToElement.bind(this)
    );
  }
  async teardownRender(render, { viewModeChanged = !1 } = {}) {
    this.storyRenders = this.storyRenders.filter((r) => r !== render), await render?.teardown?.({ viewModeChanged });
  }
  // UTILITIES
  mainStoryCallbacks(storyId) {
    return {
      showStoryDuringRender: () => this.view.showStoryDuringRender(),
      showMain: () => this.view.showMain(),
      showError: (err) => this.renderError(storyId, err),
      showException: (err) => this.renderException(storyId, err)
    };
  }
  renderPreviewEntryError(reason, err) {
    super.renderPreviewEntryError(reason, err), this.view.showErrorDisplay(err);
  }
  renderMissingStory() {
    this.view.showNoPreview(), this.channel.emit(STORY_MISSING);
  }
  renderStoryLoadingException(storySpecifier, err) {
    logger8.error(err), this.view.showErrorDisplay(err), this.channel.emit(STORY_MISSING, storySpecifier);
  }
  // renderException is used if we fail to render the story and it is uncaught by the app layer
  renderException(storyId, error) {
    let { name = "Error", message = String(error), stack } = error, renderId = this.currentRender?.renderId;
    this.channel.emit(STORY_THREW_EXCEPTION, { name, message, stack }), this.channel.emit(STORY_RENDER_PHASE_CHANGED2, { newPhase: "errored", renderId, storyId }), this.view.showErrorDisplay(error), logger8.error(`Error rendering story '${storyId}':`), logger8.error(error);
  }
  // renderError is used by the various app layers to inform the user they have done something
  // wrong -- for instance returned the wrong thing from a story
  renderError(storyId, { title, description }) {
    let renderId = this.currentRender?.renderId;
    this.channel.emit(STORY_ERRORED, { title, description }), this.channel.emit(STORY_RENDER_PHASE_CHANGED2, { newPhase: "errored", renderId, storyId }), this.view.showErrorDisplay({ message: title, stack: description }), logger8.error(`Error rendering story ${title}: ${description}`);
  }
};

// src/preview-api/modules/preview-web/UrlStore.ts
var import_picoquery2 = __toESM(require_main(), 1);
import { global as global6 } from "@storybook/global";

// src/preview-api/modules/preview-web/parseArgsParam.ts
import { once as once3 } from "storybook/internal/client-logger";
var import_picoquery = __toESM(require_main(), 1);
var VALIDATION_REGEXP = /^[a-zA-Z0-9 _-]*$/, NUMBER_REGEXP = /^-?[0-9]+(\.[0-9]+)?$/, HEX_REGEXP = /^#([a-f0-9]{3,4}|[a-f0-9]{6}|[a-f0-9]{8})$/i, COLOR_REGEXP = /^(rgba?|hsla?)\(([0-9]{1,3}),\s?([0-9]{1,3})%?,\s?([0-9]{1,3})%?,?\s?([0-9](\.[0-9]{1,2})?)?\)$/i, validateArgs = (key = "", value) => key === null || key === "" || !VALIDATION_REGEXP.test(key) ? !1 : value == null || value instanceof Date || typeof value == "number" || typeof value == "boolean" ? !0 : typeof value == "string" ? VALIDATION_REGEXP.test(value) || NUMBER_REGEXP.test(value) || HEX_REGEXP.test(value) || COLOR_REGEXP.test(value) : Array.isArray(value) ? value.every((v) => validateArgs(key, v)) : isPlainObject(value) ? Object.entries(value).every(([k, v]) => validateArgs(k, v)) : !1, QUERY_OPTIONS = {
  delimiter: ";",
  // we're parsing a single query param
  nesting: !0,
  arrayRepeat: !0,
  arrayRepeatSyntax: "bracket",
  nestingSyntax: "js",
  // objects are encoded using dot notation
  valueDeserializer(str) {
    if (str.startsWith("!")) {
      if (str === "!undefined")
        return;
      if (str === "!null")
        return null;
      if (str === "!true")
        return !0;
      if (str === "!false")
        return !1;
      if (str.startsWith("!date(") && str.endsWith(")"))
        return new Date(str.replaceAll(" ", "+").slice(6, -1));
      if (str.startsWith("!hex(") && str.endsWith(")"))
        return `#${str.slice(5, -1)}`;
      let color = str.slice(1).match(COLOR_REGEXP);
      if (color)
        return str.startsWith("!rgba") || str.startsWith("!RGBA") ? `${color[1]}(${color[2]}, ${color[3]}, ${color[4]}, ${color[5]})` : str.startsWith("!hsla") || str.startsWith("!HSLA") ? `${color[1]}(${color[2]}, ${color[3]}%, ${color[4]}%, ${color[5]})` : str.startsWith("!rgb") || str.startsWith("!RGB") ? `${color[1]}(${color[2]}, ${color[3]}, ${color[4]})` : `${color[1]}(${color[2]}, ${color[3]}%, ${color[4]}%)`;
    }
    return NUMBER_REGEXP.test(str) ? Number(str) : str;
  }
}, parseArgsParam = (argsString) => {
  let parts = argsString.split(";").map((part) => part.replace("=", "~").replace(":", "="));
  return Object.entries((0, import_picoquery.parse)(parts.join(";"), QUERY_OPTIONS)).reduce((acc, [key, value]) => validateArgs(key, value) ? Object.assign(acc, { [key]: value }) : (once3.warn(dedent`
      Omitted potentially unsafe URL args.

      More info: https://storybook.js.org/docs/writing-stories/args#setting-args-through-the-url?ref=error
    `), acc), {});
};

// src/preview-api/modules/preview-web/UrlStore.ts
var { history, document: document2 } = global6;
function pathToId(path) {
  let match = (path || "").match(/^\/story\/(.+)/);
  if (!match)
    throw new Error(`Invalid path '${path}',  must start with '/story/'`);
  return match[1];
}
var getQueryString = ({
  selection,
  extraParams
}) => {
  let search = document2?.location.search.slice(1), { path, selectedKind, selectedStory, ...rest } = (0, import_picoquery2.parse)(search);
  return `?${(0, import_picoquery2.stringify)({
    ...rest,
    ...extraParams,
    ...selection && { id: selection.storyId, viewMode: selection.viewMode }
  })}`;
}, setPath = (selection) => {
  if (!selection)
    return;
  let query = getQueryString({ selection }), { hash = "" } = document2.location;
  document2.title = selection.storyId, history.replaceState({}, "", `${document2.location.pathname}${query}${hash}`);
}, isObject = (val) => val != null && typeof val == "object" && Array.isArray(val) === !1, getFirstString = (v) => {
  if (v !== void 0) {
    if (typeof v == "string")
      return v;
    if (Array.isArray(v))
      return getFirstString(v[0]);
    if (isObject(v))
      return getFirstString(
        Object.values(v).filter(Boolean)
      );
  }
}, getSelectionSpecifierFromPath = () => {
  if (typeof document2 < "u") {
    let queryStr = document2.location.search.slice(1), query = (0, import_picoquery2.parse)(queryStr), args = typeof query.args == "string" ? parseArgsParam(query.args) : void 0, globals = typeof query.globals == "string" ? parseArgsParam(query.globals) : void 0, viewMode = getFirstString(query.viewMode);
    if (typeof viewMode != "string" || !viewMode)
      viewMode = "story";
    else if (!viewMode.match(/docs|story/))
      return null;
    let path = getFirstString(query.path), storyId = path ? pathToId(path) : getFirstString(query.id);
    if (storyId)
      return { storySpecifier: storyId, args, globals, viewMode };
  }
  return null;
}, UrlStore = class {
  constructor() {
    this.selectionSpecifier = getSelectionSpecifierFromPath();
  }
  setSelection(selection) {
    this.selection = selection, setPath(this.selection);
  }
  setQueryParams(queryParams) {
    let query = getQueryString({ extraParams: queryParams }), { hash = "" } = document2.location;
    history.replaceState({}, "", `${document2.location.pathname}${query}${hash}`);
  }
};

// src/preview-api/modules/preview-web/WebView.ts
var import_ansi_to_html = __toESM(require_ansi_to_html(), 1), import_picoquery3 = __toESM(require_main(), 1);
import { logger as logger9 } from "storybook/internal/client-logger";
import { global as global7 } from "@storybook/global";
var { document: document3 } = global7, PREPARING_DELAY = 100, Mode = /* @__PURE__ */ ((Mode2) => (Mode2.MAIN = "MAIN", Mode2.NOPREVIEW = "NOPREVIEW", Mode2.PREPARING_STORY = "PREPARING_STORY", Mode2.PREPARING_DOCS = "PREPARING_DOCS", Mode2.ERROR = "ERROR", Mode2))(Mode || {}), classes = {
  PREPARING_STORY: "sb-show-preparing-story",
  PREPARING_DOCS: "sb-show-preparing-docs",
  MAIN: "sb-show-main",
  NOPREVIEW: "sb-show-nopreview",
  ERROR: "sb-show-errordisplay"
}, layoutClassMap = {
  centered: "sb-main-centered",
  fullscreen: "sb-main-fullscreen",
  padded: "sb-main-padded"
}, ansiConverter = new import_ansi_to_html.default({
  escapeXML: !0
}), WebView = class {
  constructor() {
    this.testing = !1;
    if (typeof document3 < "u") {
      let { __SPECIAL_TEST_PARAMETER__ } = (0, import_picoquery3.parse)(document3.location.search.slice(1));
      switch (__SPECIAL_TEST_PARAMETER__) {
        case "preparing-story": {
          this.showPreparingStory(), this.testing = !0;
          break;
        }
        case "preparing-docs": {
          this.showPreparingDocs(), this.testing = !0;
          break;
        }
        default:
      }
    }
  }
  // Get ready to render a story, returning the element to render to
  prepareForStory(story) {
    return this.showStory(), this.applyLayout(story.parameters.layout), document3.documentElement.scrollTop = 0, document3.documentElement.scrollLeft = 0, this.storyRoot();
  }
  storyRoot() {
    return document3.getElementById("storybook-root");
  }
  prepareForDocs() {
    return this.showMain(), this.showDocs(), this.applyLayout("fullscreen"), document3.documentElement.scrollTop = 0, document3.documentElement.scrollLeft = 0, this.docsRoot();
  }
  docsRoot() {
    return document3.getElementById("storybook-docs");
  }
  applyLayout(layout = "padded") {
    if (layout === "none") {
      document3.body.classList.remove(this.currentLayoutClass), this.currentLayoutClass = null;
      return;
    }
    this.checkIfLayoutExists(layout);
    let layoutClass = layoutClassMap[layout];
    document3.body.classList.remove(this.currentLayoutClass), document3.body.classList.add(layoutClass), this.currentLayoutClass = layoutClass;
  }
  checkIfLayoutExists(layout) {
    layoutClassMap[layout] || logger9.warn(
      dedent`
          The desired layout: ${layout} is not a valid option.
          The possible options are: ${Object.keys(layoutClassMap).join(", ")}, none.
        `
    );
  }
  showMode(mode) {
    clearTimeout(this.preparingTimeout), Object.keys(Mode).forEach((otherMode) => {
      otherMode === mode ? document3.body.classList.add(classes[otherMode]) : document3.body.classList.remove(classes[otherMode]);
    });
  }
  showErrorDisplay({ message = "", stack = "" }) {
    let header = message, detail = stack, parts = message.split(`
`);
    parts.length > 1 && ([header] = parts, detail = parts.slice(1).join(`
`).replace(/^\n/, "")), document3.getElementById("error-message").innerHTML = ansiConverter.toHtml(header), document3.getElementById("error-stack").innerHTML = ansiConverter.toHtml(detail), this.showMode("ERROR" /* ERROR */);
  }
  showNoPreview() {
    this.testing || (this.showMode("NOPREVIEW" /* NOPREVIEW */), this.storyRoot()?.setAttribute("hidden", "true"), this.docsRoot()?.setAttribute("hidden", "true"));
  }
  showPreparingStory({ immediate = !1 } = {}) {
    clearTimeout(this.preparingTimeout), immediate ? this.showMode("PREPARING_STORY" /* PREPARING_STORY */) : this.preparingTimeout = setTimeout(
      () => this.showMode("PREPARING_STORY" /* PREPARING_STORY */),
      PREPARING_DELAY
    );
  }
  showPreparingDocs({ immediate = !1 } = {}) {
    clearTimeout(this.preparingTimeout), immediate ? this.showMode("PREPARING_DOCS" /* PREPARING_DOCS */) : this.preparingTimeout = setTimeout(() => this.showMode("PREPARING_DOCS" /* PREPARING_DOCS */), PREPARING_DELAY);
  }
  showMain() {
    this.showMode("MAIN" /* MAIN */);
  }
  showDocs() {
    this.storyRoot().setAttribute("hidden", "true"), this.docsRoot().removeAttribute("hidden");
  }
  showStory() {
    this.docsRoot().setAttribute("hidden", "true"), this.storyRoot().removeAttribute("hidden");
  }
  showStoryDuringRender() {
    document3.body.classList.add(classes.MAIN);
  }
};

// src/preview-api/modules/preview-web/PreviewWeb.tsx
var PreviewWeb = class extends PreviewWithSelection {
  constructor(importFn, getProjectAnnotations) {
    super(importFn, getProjectAnnotations, new UrlStore(), new WebView());
    this.importFn = importFn;
    this.getProjectAnnotations = getProjectAnnotations;
    global8.__STORYBOOK_PREVIEW__ = this;
  }
};

// src/preview-api/modules/preview-web/simulate-pageload.ts
import { global as global9 } from "@storybook/global";
var { document: document4 } = global9, runScriptTypes = [
  "application/javascript",
  "application/ecmascript",
  "application/x-ecmascript",
  "application/x-javascript",
  "text/ecmascript",
  "text/javascript",
  "text/javascript1.0",
  "text/javascript1.1",
  "text/javascript1.2",
  "text/javascript1.3",
  "text/javascript1.4",
  "text/javascript1.5",
  "text/jscript",
  "text/livescript",
  "text/x-ecmascript",
  "text/x-javascript",
  // Support modern javascript
  "module"
], SCRIPT = "script", SCRIPTS_ROOT_ID = "scripts-root";
function simulateDOMContentLoaded() {
  let DOMContentLoadedEvent = document4.createEvent("Event");
  DOMContentLoadedEvent.initEvent("DOMContentLoaded", !0, !0), document4.dispatchEvent(DOMContentLoadedEvent);
}
function insertScript($script, callback, $scriptRoot) {
  let scriptEl = document4.createElement("script");
  scriptEl.type = $script.type === "module" ? "module" : "text/javascript", $script.src ? (scriptEl.onload = callback, scriptEl.onerror = callback, scriptEl.src = $script.src) : scriptEl.textContent = $script.innerText, $scriptRoot ? $scriptRoot.appendChild(scriptEl) : document4.head.appendChild(scriptEl), $script.parentNode.removeChild($script), $script.src || callback();
}
function insertScriptsSequentially(scriptsToExecute, callback, index = 0) {
  scriptsToExecute[index](() => {
    index++, index === scriptsToExecute.length ? callback() : insertScriptsSequentially(scriptsToExecute, callback, index);
  });
}
function simulatePageLoad($container) {
  let $scriptsRoot = document4.getElementById(SCRIPTS_ROOT_ID);
  $scriptsRoot ? $scriptsRoot.innerHTML = "" : ($scriptsRoot = document4.createElement("div"), $scriptsRoot.id = SCRIPTS_ROOT_ID, document4.body.appendChild($scriptsRoot));
  let $scripts = Array.from($container.querySelectorAll(SCRIPT));
  if ($scripts.length) {
    let scriptsToExecute = [];
    $scripts.forEach(($script) => {
      let typeAttr = $script.getAttribute("type");
      (!typeAttr || runScriptTypes.includes(typeAttr)) && scriptsToExecute.push((callback) => insertScript($script, callback, $scriptsRoot));
    }), scriptsToExecute.length && insertScriptsSequentially(scriptsToExecute, simulateDOMContentLoaded, void 0);
  } else
    simulateDOMContentLoaded();
}

// src/preview-api/modules/preview-web/emitTransformCode.ts
async function emitTransformCode(source, context) {
  let transform = context.parameters?.docs?.source?.transform, { id, unmappedArgs } = context, transformed = transform && source ? transform?.(source, context) : source, result = transformed ? await transformed : void 0;
  addons.getChannel().emit(SNIPPET_RENDERED, {
    id,
    source: result,
    args: unmappedArgs
  });
}

export {
  mockChannel,
  addons,
  HooksContext,
  applyHooks,
  useMemo,
  useCallback,
  useRef,
  useState,
  useReducer,
  useEffect,
  useChannel,
  useStoryContext,
  useParameter,
  useArgs,
  useGlobals,
  makeDecorator,
  combineArgs,
  normalizeArrays,
  normalizeStory,
  mountDestructured,
  decorateStory,
  sanitizeStoryContextUpdate,
  defaultDecorateStory,
  prepareStory,
  prepareMeta,
  filterArgTypes,
  inferControls,
  normalizeProjectAnnotations,
  composeStepRunners,
  composeConfigs,
  ReporterAPI,
  getCsfFactoryAnnotations,
  setDefaultProjectAnnotations,
  setProjectAnnotations,
  composeStory,
  composeStories,
  createPlaywrightTest,
  StoryStore,
  userOrAutoTitleFromSpecifier,
  userOrAutoTitle,
  sortStoriesV7,
  Preview,
  DocsContext,
  PreviewWithSelection,
  UrlStore,
  WebView,
  PreviewWeb,
  simulateDOMContentLoaded,
  simulatePageLoad,
  emitTransformCode
};