import {
  API_BASE,
  BomTable,
  Button,
  CadViewer,
  CircuitJsonPreview,
  FileMenuLeftHeader,
  ImportComponentDialog,
  PCBViewer,
  PcbViewerWithContainerHeight,
  SchematicViewer,
  cn,
  debug_default,
  linkify,
  mapJLCComponentToSearchResult,
  mapTscircuitSnippetToSearchResult,
  registryKy,
  searchJLCComponents,
  searchTscircuitComponents,
  useLocalStorageState,
  useOrderDialog,
  useOrderDialogCli,
  useRunFrameStore,
  useRunnerStore,
  useStyles
} from "./chunk-WT3DYXAY.js";

// lib/components/RunFrame/RunFrame.tsx
import { createCircuitWebWorker } from "@tscircuit/eval/worker";
import Debug from "debug";
import { Loader2, Play, Square } from "lucide-react";
import { useEffect, useReducer, useRef as useRef2, useState } from "react";
import {
  orderedRenderPhases as orderedRenderPhases2
} from "@tscircuit/core";

// lib/render-logging/getPhaseTimingsFromRenderEvents.ts
import { orderedRenderPhases } from "@tscircuit/core";
var getPhaseTimingsFromRenderEvents = (renderEvents) => {
  const phaseTimings = {};
  if (!renderEvents) return phaseTimings;
  for (const renderPhase of orderedRenderPhases) {
    phaseTimings[renderPhase] = 0;
  }
  const startEvents = /* @__PURE__ */ new Map();
  for (const event of renderEvents) {
    const [, , phase, eventType] = event.type.split(":");
    if (eventType === "start") {
      startEvents.set(`${phase}:${event.renderId}`, event);
      continue;
    }
    if (eventType === "end") {
      const startEvent = startEvents.get(`${phase}:${event.renderId}`);
      if (startEvent) {
        const duration = event.createdAt - startEvent.createdAt;
        phaseTimings[phase] = (phaseTimings[phase] || 0) + duration;
      }
    }
  }
  return phaseTimings;
};

// lib/utils/getChangesBetweenFsMaps.tsx
var getChangesBetweenFsMaps = (fsMap1, fsMap2) => {
  const changes = {};
  for (const [path, oldContent] of fsMap1.entries()) {
    const newContent = fsMap2.get(path);
    if (newContent !== oldContent) {
      changes[path] = {
        old: oldContent,
        new: newContent
      };
    }
  }
  for (const [path, newContent] of fsMap2.entries()) {
    if (!fsMap1.has(path)) {
      changes[path] = {
        old: void 0,
        new: newContent
      };
    }
  }
  return changes;
};

// lib/components/RunFrame/useMutex.tsx
import { useCallback, useRef } from "react";
function useMutex() {
  const lockRef = useRef(Promise.resolve());
  const isLockedRef = useRef(false);
  const currentExecutionRef = useRef(null);
  const runWithMutex = useCallback(
    async (fn) => {
      await lockRef.current;
      const executionContext = { cancelled: false };
      currentExecutionRef.current = executionContext;
      let releaseLock;
      const newLock = new Promise((resolve) => {
        releaseLock = resolve;
      });
      try {
        lockRef.current = newLock;
        isLockedRef.current = true;
        return await fn();
      } catch (error) {
        if (!executionContext.cancelled) {
          throw error;
        }
      } finally {
        isLockedRef.current = false;
        currentExecutionRef.current = null;
        releaseLock();
      }
    },
    []
  );
  const cancel = useCallback(() => {
    if (currentExecutionRef.current) {
      currentExecutionRef.current.cancelled = true;
    }
    lockRef.current = Promise.resolve();
    isLockedRef.current = false;
  }, []);
  const isLocked = useCallback(() => isLockedRef.current, []);
  return { runWithMutex, isLocked, cancel };
}

// lib/components/RunFrame/RunFrame.tsx
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
var numRenderPhases = 26;
var debug = Debug("run-frame:RunFrame");
var fetchLatestEvalVersion = async () => {
  try {
    const response = await fetch(
      "https://data.jsdelivr.com/v1/package/npm/@tscircuit/eval"
    );
    if (response.ok) {
      const data = await response.json();
      return data.tags?.latest;
    }
  } catch (err) {
    console.error("Failed to fetch latest eval version", err);
  }
  return void 0;
};
var resolveEvalVersion = async (evalVersionProp, forceLatest) => {
  if (evalVersionProp) return evalVersionProp;
  if (forceLatest || !window.TSCIRCUIT_LATEST_EVAL_VERSION) {
    const latest = await fetchLatestEvalVersion();
    if (latest) {
      window.TSCIRCUIT_LATEST_EVAL_VERSION = latest;
      return latest;
    }
  }
  if (window.TSCIRCUIT_LATEST_EVAL_VERSION) {
    return window.TSCIRCUIT_LATEST_EVAL_VERSION;
  }
  return "latest";
};
var RunFrame = (props) => {
  useStyles();
  const [circuitJson, setCircuitJson] = useRunFrameStore((s) => [
    s.circuitJson,
    s.setCircuitJson
  ]);
  const [error, setError] = useState(null);
  const cancelExecutionRef = useRef2(null);
  const [autoroutingGraphics, setAutoroutingGraphics] = useState(null);
  const [runCountTrigger, incRunCountTrigger] = useReducer(
    (acc, s) => acc + 1,
    0
  );
  const setLastRunEvalVersion = useRunnerStore((s) => s.setLastRunEvalVersion);
  const lastRunCountTriggerRef = useRef2(0);
  const runMutex = useMutex();
  const [isRunning, setIsRunning] = useState(false);
  const [dependenciesLoaded, setDependenciesLoaded] = useState(false);
  const [activeAsyncEffects, setActiveAsyncEffects] = useState({});
  const [currentDebugOption, setCurrentDebugOption] = useState("");
  const activeEffectName = Object.values(activeAsyncEffects).sort(
    (a, b) => a.startTime - b.startTime
  )[0]?.effectName;
  useEffect(() => {
    const handleKeyDown = (e) => {
      if ((e.ctrlKey || e.metaKey) && e.key === "Enter" && !isRunning) {
        incRunCountTrigger(1);
      }
    };
    window.addEventListener("keydown", handleKeyDown);
    return () => window.removeEventListener("keydown", handleKeyDown);
  }, [isRunning]);
  useEffect(() => {
    let cancelled = false;
    const load = async () => {
      try {
        if (!globalThis.runFrameWorker) {
          const evalVersion = await resolveEvalVersion(
            props.evalVersion,
            props.forceLatestEvalVersion
          );
          const worker = await createCircuitWebWorker({
            evalVersion,
            webWorkerBlobUrl: props.evalWebWorkerBlobUrl,
            platform: {
              projectBaseUrl: `${API_BASE}/files/static`
            },
            verbose: true,
            ...props.enableFetchProxy && {
              enableFetchProxy: props.enableFetchProxy
            }
          });
          if (cancelled) return;
          globalThis.runFrameWorker = worker;
          setLastRunEvalVersion(evalVersion);
        }
        if (!cancelled) setDependenciesLoaded(true);
      } catch (err) {
        console.error("Failed to preload eval worker", err);
      }
    };
    load();
    return () => {
      cancelled = true;
    };
  }, [
    props.evalVersion,
    props.evalWebWorkerBlobUrl,
    props.forceLatestEvalVersion
  ]);
  const [renderLog, setRenderLog] = useState(null);
  const [autoroutingLog, setAutoroutingLog] = useState({});
  const [activeTab, setActiveTab] = useState(
    props.defaultActiveTab ?? props.defaultTab ?? "pcb"
  );
  useEffect(() => {
    if (props.debug) Debug.enable("run-frame*");
  }, [props.debug]);
  const fsMap = props.fsMap instanceof Map ? props.fsMap : Object.entries(props.fsMap ?? {}).reduce(
    (m, [k, v]) => m.set(k, v),
    /* @__PURE__ */ new Map()
  );
  const lastFsMapRef = useRef2(null);
  const lastEntrypointRef = useRef2(null);
  useEffect(() => {
    if (props.isLoadingFiles) return;
    const fsMapObj = fsMap instanceof Map ? Object.fromEntries(fsMap.entries()) : fsMap;
    if (!fsMapObj || Object.keys(fsMapObj).length === 0) {
      setError({
        error: "No files provided. Please provide at least one file with code to execute.",
        stack: ""
      });
      setIsRunning(false);
      return;
    }
    const wasTriggeredByRunButton = runCountTrigger !== lastRunCountTriggerRef.current;
    if (lastFsMapRef.current && circuitJson) {
      const changes = getChangesBetweenFsMaps(lastFsMapRef.current, fsMap);
      if (Object.keys(changes).length > 0) {
        debug("code changes detected");
      } else if (lastEntrypointRef.current !== props.entrypoint) {
        debug("render triggered by entrypoint change");
      } else if (!wasTriggeredByRunButton) {
        debug("render triggered without changes to fsMap, skipping");
        return;
      }
    }
    if (props.showRunButton && runCountTrigger === lastRunCountTriggerRef.current) {
      return;
    }
    lastFsMapRef.current = fsMap;
    lastEntrypointRef.current = props.entrypoint ?? null;
    lastRunCountTriggerRef.current = runCountTrigger;
    setIsRunning(true);
    const runWorker = async () => {
      debug("running render worker");
      setError(null);
      setRenderLog(null);
      setActiveAsyncEffects({});
      const renderLog2 = { progress: 0, debugOutputs: [] };
      let cancelled = false;
      cancelExecutionRef.current = () => {
        cancelled = true;
      };
      const resolvedEvalVersion = await resolveEvalVersion(
        props.evalVersion,
        !globalThis.runFrameWorker && props.forceLatestEvalVersion
      );
      debug("resolvedEvalVersion", resolvedEvalVersion);
      const worker = globalThis.runFrameWorker ?? await createCircuitWebWorker({
        evalVersion: resolvedEvalVersion,
        webWorkerBlobUrl: props.evalWebWorkerBlobUrl,
        verbose: true,
        platform: {
          projectBaseUrl: `${API_BASE}/files/static`
        },
        ...props.enableFetchProxy && {
          enableFetchProxy: props.enableFetchProxy
        }
      });
      globalThis.runFrameWorker = worker;
      setLastRunEvalVersion(resolvedEvalVersion);
      if (currentDebugOption?.trim()) {
        worker.enableDebug(currentDebugOption.replace("DEBUG=", ""));
      }
      debug("Starting render...");
      props.onRenderStarted?.();
      const fsMapObj2 = fsMap instanceof Map ? Object.fromEntries(fsMap.entries()) : fsMap;
      let lastRenderLogSet = Date.now();
      worker.on("asyncEffect:start", (event) => {
        const id = `${event.phase}|${event.componentDisplayName ?? ""}|${event.effectName}`;
        setActiveAsyncEffects((effects) => ({
          ...effects,
          [id]: { ...event, startTime: Date.now() }
        }));
      });
      worker.on("asyncEffect:end", (event) => {
        const id = `${event.phase}|${event.componentDisplayName ?? ""}|${event.effectName}`;
        setActiveAsyncEffects((effects) => {
          const { [id]: _removed, ...rest } = effects;
          return rest;
        });
      });
      worker.on("autorouting:start", (event) => {
        setAutoroutingLog({
          ...autoroutingLog,
          [event.componentDisplayName]: {
            simpleRouteJson: event.simpleRouteJson
          }
        });
      });
      worker.on("board:renderPhaseStarted", (event) => {
        renderLog2.lastRenderEvent = event;
        renderLog2.eventsProcessed = (renderLog2.eventsProcessed ?? 0) + 1;
        const hasProcessedEnoughToEstimateProgress = renderLog2.eventsProcessed > 2;
        const estProgressLinear = orderedRenderPhases2.indexOf(event.phase) / numRenderPhases * 0.75 + renderLog2.eventsProcessed / 1e3 * 0.25;
        const estProgress = 1 - Math.exp(-estProgressLinear * 3);
        renderLog2.progress = estProgress;
        if (!cancelled) {
          setRenderLog({ ...renderLog2 });
        }
      });
      if (activeTab === "render_log") {
        worker.on("renderable:renderLifecycle:anyEvent", (event) => {
          renderLog2.renderEvents = renderLog2.renderEvents ?? [];
          event.createdAt = Date.now();
          renderLog2.renderEvents.push(event);
          if (Date.now() - lastRenderLogSet > 500) {
            renderLog2.phaseTimings = getPhaseTimingsFromRenderEvents(
              renderLog2.renderEvents ?? []
            );
            lastRenderLogSet = Date.now();
          }
          if (!cancelled) {
            setRenderLog({ ...renderLog2 });
          }
        });
      }
      worker.on("autorouting:progress", (event) => {
        setAutoroutingGraphics(event.debugGraphics);
      });
      worker.on("debug:logOutput", (event) => {
        renderLog2.debugOutputs = renderLog2.debugOutputs ?? [];
        renderLog2.debugOutputs.push({
          type: "debug",
          name: event.name,
          content: event.content
        });
        if (!cancelled) {
          setRenderLog({ ...renderLog2 });
        }
      });
      debug("Executing fsMap...");
      const evalResult = await worker.executeWithFsMap({
        entrypoint: props.entrypoint,
        fsMap: fsMapObj2,
        ...props.mainComponentPath ? { mainComponentPath: props.mainComponentPath } : {}
      }).then(() => {
        return { success: true };
      }).catch((e) => {
        const message = e.message.replace("Error: ", "");
        debug(`eval error: ${message}`);
        props.onError?.(e);
        setError({ error: message, stack: e.stack });
        setRenderLog(null);
        console.error(e);
        return { success: false };
      });
      debug("worker call started");
      if (!evalResult.success) {
        setIsRunning(false);
        setActiveAsyncEffects({});
        return;
      }
      const $renderResult = worker.renderUntilSettled();
      debug("waiting for initial circuit json...");
      let circuitJson2 = await worker.getCircuitJson().catch((e) => {
        debug("error getting initial circuit json", e);
        props.onError?.(e);
        setError({ error: e.message, stack: e.stack });
        setRenderLog(null);
        setIsRunning(false);
        setActiveAsyncEffects({});
        return null;
      });
      if (!circuitJson2) return;
      debug("got initial circuit json");
      setCircuitJson(circuitJson2);
      props.onCircuitJsonChange?.(circuitJson2);
      props.onInitialRender?.({ circuitJson: circuitJson2 });
      await $renderResult;
      debug("getting final circuit json");
      circuitJson2 = await worker.getCircuitJson();
      props.onCircuitJsonChange?.(circuitJson2);
      setCircuitJson(circuitJson2);
      props.onRenderFinished?.({ circuitJson: circuitJson2 });
      setAutoroutingGraphics({});
      if (activeTab === "render_log") {
        renderLog2.phaseTimings = getPhaseTimingsFromRenderEvents(
          renderLog2.renderEvents ?? []
        );
      }
      renderLog2.progress = 1;
      if (!cancelled) {
        setRenderLog({ ...renderLog2 });
      }
      setIsRunning(false);
      setActiveAsyncEffects({});
      setCurrentDebugOption("");
      cancelExecutionRef.current = null;
    };
    runMutex.runWithMutex(runWorker);
  }, [
    props.fsMap,
    props.entrypoint,
    runCountTrigger,
    props.evalVersion,
    props.mainComponentPath,
    props.isLoadingFiles,
    currentDebugOption
  ]);
  const lastEditEventRef = useRef2(null);
  const dragTimeout = useRef2(null);
  const handleEditEvent = (event) => {
    if (!event || event === null) {
      console.warn(
        "[RunFrame] handleEditEvent received null or undefined event."
      );
      return;
    }
    if (event.in_progress) {
      lastEditEventRef.current = event;
      if (dragTimeout.current) {
        clearTimeout(dragTimeout.current);
        dragTimeout.current = null;
      }
    } else {
      if (dragTimeout.current) {
        clearTimeout(dragTimeout.current);
      }
      dragTimeout.current = setTimeout(() => {
        const eventToSend = event || lastEditEventRef.current;
        props.onEditEvent?.(eventToSend);
        lastEditEventRef.current = null;
        dragTimeout.current = null;
      }, 100);
    }
  };
  const handleReportAutoroutingLog = async (name, data) => {
    let urlPath = "";
    const softwareMetadata = Array.isArray(circuitJson) && circuitJson.find(
      (el) => el.type === "software_project_metadata"
    );
    const projectUrl = props.projectUrl ?? softwareMetadata?.project_url;
    if (projectUrl) {
      try {
        urlPath = new URL(projectUrl).pathname;
      } catch {
        urlPath = projectUrl;
      }
    }
    const title = urlPath ? `${urlPath} - ${name}` : name;
    await registryKy.post("autorouting/bug_reports/create", {
      json: {
        title,
        simple_route_json: data.simpleRouteJson
      }
    }).json().then(({ autorouting_bug_report }) => {
      window.open(
        `https://api.tscircuit.com/autorouting/bug_reports/view?autorouting_bug_report_id=${autorouting_bug_report.autorouting_bug_report_id}`,
        "_blank"
      );
    }).catch((error2) => {
      console.error("Failed to report autorouting bug", error2);
      if (error2.message.includes("401")) {
        alert("You must be logged in to report autorouting bugs");
      } else {
        alert(`Failed to report autorouting bug: ${error2.message}`);
      }
    });
  };
  if (props.isLoadingFiles) {
    return /* @__PURE__ */ jsxs("div", { className: "rf-flex rf-flex-col rf-w-full rf-h-full", children: [
      /* @__PURE__ */ jsxs("div", { className: "rf-flex rf-items-center rf-gap-4 rf-p-2 rf-border-b", children: [
        /* @__PURE__ */ jsx("div", { className: "rf-w-20 rf-h-9 rf-bg-gray-200 dark:rf-bg-gray-700 rf-rounded-md rf-animate-pulse" }),
        /* @__PURE__ */ jsx("div", { className: "rf-flex rf-gap-6 rf-ml-auto", children: ["PCB", "Schematic", "3D"].map((_, i) => /* @__PURE__ */ jsx(
          "div",
          {
            className: "rf-h-6 rf-w-20 rf-bg-gray-200 dark:rf-bg-gray-700 rf-rounded rf-animate-pulse"
          },
          i
        )) })
      ] }),
      /* @__PURE__ */ jsx("div", { className: "rf-flex-1 rf-p-4", children: /* @__PURE__ */ jsx("div", { className: "rf-w-full rf-h-full rf-rounded-lg rf-bg-gray-100 dark:rf-bg-gray-800 rf-animate-pulse rf-flex rf-items-center rf-justify-center", children: /* @__PURE__ */ jsx("div", { className: "rf-flex rf-flex-col rf-items-center rf-gap-4", children: /* @__PURE__ */ jsx("div", { className: "rf-text-sm rf-text-gray-400 dark:rf-text-gray-500", children: "Loading files..." }) }) }) })
    ] });
  }
  return /* @__PURE__ */ jsx(
    CircuitJsonPreview,
    {
      code: fsMap.get(props.entrypoint ?? props.mainComponentPath),
      fsMap,
      defaultActiveTab: props.defaultActiveTab ?? props.defaultTab,
      defaultTab: props.defaultTab,
      availableTabs: props.availableTabs,
      showToggleFullScreen: props.showToggleFullScreen,
      autoroutingGraphics,
      autoroutingLog,
      onReportAutoroutingLog: props.onReportAutoroutingLog || handleReportAutoroutingLog,
      leftHeaderContent: /* @__PURE__ */ jsxs(Fragment, { children: [
        props.showRunButton && /* @__PURE__ */ jsxs("div", { className: "rf-relative rf-inline-flex", children: [
          /* @__PURE__ */ jsxs(
            "button",
            {
              type: "button",
              onClick: () => {
                incRunCountTrigger(1);
              },
              className: "rf-flex rf-items-center rf-gap-2 rf-px-4 rf-py-2 rf-bg-blue-600 hover:rf-bg-blue-700 rf-text-white rf-rounded-md disabled:rf-opacity-50 transition-colors duration-200",
              disabled: isRunning || !dependenciesLoaded,
              children: [
                "Run",
                " ",
                isRunning || !dependenciesLoaded ? /* @__PURE__ */ jsx(Loader2, { className: "rf-w-3 rf-h-3 rf-animate-spin" }) : /* @__PURE__ */ jsx(Play, { className: "rf-w-3 rf-h-3" })
              ]
            }
          ),
          isRunning && /* @__PURE__ */ jsx("div", { className: "rf-flex rf-items-center rf-ml-1", children: /* @__PURE__ */ jsx(
            Button,
            {
              onClick: (e) => {
                e.stopPropagation();
                setIsRunning(false);
                setRenderLog(null);
                setError(null);
                if (cancelExecutionRef.current) {
                  cancelExecutionRef.current();
                  cancelExecutionRef.current = null;
                }
                runMutex.cancel();
                setActiveAsyncEffects({});
                if (globalThis.runFrameWorker) {
                  globalThis.runFrameWorker.kill();
                  globalThis.runFrameWorker = null;
                }
              },
              variant: "ghost",
              size: "icon",
              className: "rf-text-red-300 hover:rf-text-red-400 hover:!rf-bg-transparent [&>svg]:rf-text-red-300 [&>svg]:hover:rf-text-red-400 rf-flex rf-items-center rf-justify-center",
              children: /* @__PURE__ */ jsx(
                Square,
                {
                  className: "!rf-h-2.5 !rf-w-2.5",
                  fill: "currentColor",
                  stroke: "currentColor"
                }
              )
            }
          ) })
        ] }),
        props.showFileMenu !== false && /* @__PURE__ */ jsx(FileMenuLeftHeader, { isWebEmbedded: props.isWebEmbedded }),
        props.leftHeaderContent
      ] }),
      onActiveTabChange: setActiveTab,
      circuitJson,
      renderLog,
      activeEffectName,
      isRunningCode: isRunning,
      errorMessage: error?.error,
      errorStack: error?.stack,
      onEditEvent: handleEditEvent,
      editEvents: props.editEvents,
      defaultToFullScreen: props.defaultToFullScreen,
      onRerunWithDebug: (debugOption) => {
        setCurrentDebugOption(debugOption || "");
        incRunCountTrigger(1);
      }
    }
  );
};

// lib/components/RunFrameWithApi/RunFrameWithApi.tsx
import Debug2 from "debug";

// lib/hooks/use-edit-event-controller.ts
import { useState as useState2, useCallback as useCallback2, useEffect as useEffect2 } from "react";
var debug2 = debug_default.extend("useEditEventController");
var useEditEventController = () => {
  const applyEditEventsAndUpdateManualEditsJson = useRunFrameStore(
    (s) => s.applyEditEventsAndUpdateManualEditsJson
  );
  const [editEvents, setEditEvents] = useState2([]);
  const [isRendering, setIsRendering] = useState2(false);
  const unappliedEditEvents = editEvents.filter((ee) => !ee._applied);
  const appliedEditEvents = editEvents.filter((ee) => ee._applied);
  const editEventsForRender = isRendering ? editEvents : unappliedEditEvents;
  const pushEditEvent = useCallback2((ee) => {
    setEditEvents((prev) => [...prev, { ...ee, _applied: false }]);
  }, []);
  const markEditEventApplied = useCallback2((ee) => {
    setEditEvents(
      (prev) => prev.map(
        (event) => event === ee ? { ...event, _applied: true } : event
      )
    );
  }, []);
  const markAllEditEventsApplied = useCallback2(() => {
    setEditEvents((prev) => prev.map((ee) => ({ ...ee, _applied: true })));
  }, []);
  const markRenderStarted = useCallback2(() => {
    setIsRendering(true);
    if (editEvents.length === 0) return;
    debug2("removing edit events that are applied");
    setEditEvents((prev) => prev.filter((ee) => !ee._applied));
  }, [editEvents]);
  const markRenderComplete = useCallback2(() => {
    setIsRendering(false);
  }, []);
  useEffect2(() => {
    if (editEvents.filter((ee) => !ee._applied).length === 0) return;
    const timeout = setTimeout(() => {
      markAllEditEventsApplied();
      applyEditEventsAndUpdateManualEditsJson(
        editEvents
        //.filter((ee) => !ee._applied),
      );
    }, 1e3);
    return () => clearTimeout(timeout);
  }, [editEvents]);
  return {
    unappliedEditEvents,
    appliedEditEvents,
    editEventsForRender,
    pushEditEvent,
    markEditEventApplied,
    markRenderStarted,
    markRenderComplete,
    markAllEditEventsApplied
  };
};

// lib/hooks/use-sync-page-title.ts
import { useEffect as useEffect3 } from "react";
var useSyncPageTitle = () => {
  const fsMap = useRunFrameStore((s) => s.fsMap);
  useEffect3(() => {
    if (!document || !fsMap) return;
    const fileKeys = Array.from(fsMap.keys());
    const entrypoint = guessEntrypoint(fileKeys);
    const packageJsonContent = fsMap.get("package.json");
    try {
      if (packageJsonContent) {
        const parsedPackageJson = JSON.parse(packageJsonContent);
        if (parsedPackageJson?.name) {
          document.title = parsedPackageJson.name;
          return;
        }
      }
    } catch (e) {
    }
    if (entrypoint) {
      document.title = entrypoint;
    }
  }, [fsMap]);
};

// lib/components/RunFrameWithApi/RunFrameWithApi.tsx
import { useEffect as useEffect5, useMemo as useMemo2, useState as useState4 } from "react";
import { applyEditEventsToManualEditsFile } from "@tscircuit/core";

// lib/components/RunFrameWithApi/file-selector-combobox.tsx
import { useEffect as useEffect4, useState as useState3 } from "react";

// lib/components/ui/command.tsx
import * as React from "react";
import "@radix-ui/react-dialog";
import { Command as CommandPrimitive } from "cmdk";
import { Search } from "lucide-react";
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
var Command = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
  CommandPrimitive,
  {
    ref,
    className: cn(
      "rf-flex rf-h-full rf-w-full rf-flex-col rf-overflow-hidden rf-rounded-md rf-bg-white rf-text-zinc-950 dark:rf-bg-zinc-950 dark:rf-text-zinc-50",
      className
    ),
    ...props
  }
));
Command.displayName = CommandPrimitive.displayName;
var CommandInput = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxs2(
  "div",
  {
    className: "rf-flex rf-items-center rf-border-b rf-px-3",
    "cmdk-input-wrapper": "",
    children: [
      /* @__PURE__ */ jsx2(Search, { className: "rf-mr-2 rf-h-4 rf-w-4 rf-shrink-0 rf-opacity-50" }),
      /* @__PURE__ */ jsx2(
        CommandPrimitive.Input,
        {
          ref,
          className: cn(
            "rf-flex rf-h-10 rf-w-full rf-rounded-md rf-bg-transparent rf-py-3 rf-text-sm rf-outline-none placeholder:rf-text-zinc-500 disabled:rf-cursor-not-allowed disabled:rf-opacity-50 dark:placeholder:rf-text-zinc-400",
            className
          ),
          ...props
        }
      )
    ]
  }
));
CommandInput.displayName = CommandPrimitive.Input.displayName;
var CommandList = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
  CommandPrimitive.List,
  {
    ref,
    className: cn(
      "rf-max-h-[300px] rf-overflow-y-auto rf-overflow-x-hidden",
      className
    ),
    ...props
  }
));
CommandList.displayName = CommandPrimitive.List.displayName;
var CommandEmpty = React.forwardRef((props, ref) => /* @__PURE__ */ jsx2(
  CommandPrimitive.Empty,
  {
    ref,
    className: "rf-py-6 rf-text-center rf-text-sm",
    ...props
  }
));
CommandEmpty.displayName = CommandPrimitive.Empty.displayName;
var CommandGroup = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
  CommandPrimitive.Group,
  {
    ref,
    className: cn(
      "rf-overflow-hidden rf-p-1 rf-text-zinc-950 [&_[cmdk-group-heading]]:rf-px-2 [&_[cmdk-group-heading]]:rf-py-1.5 [&_[cmdk-group-heading]]:rf-text-xs [&_[cmdk-group-heading]]:rf-font-medium [&_[cmdk-group-heading]]:rf-text-zinc-500 dark:rf-text-zinc-50 dark:[&_[cmdk-group-heading]]:rf-text-zinc-400",
      className
    ),
    ...props
  }
));
CommandGroup.displayName = CommandPrimitive.Group.displayName;
var CommandSeparator = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
  CommandPrimitive.Separator,
  {
    ref,
    className: cn(
      "rf--mx-1 rf-h-px rf-bg-zinc-200 dark:rf-bg-zinc-800",
      className
    ),
    ...props
  }
));
CommandSeparator.displayName = CommandPrimitive.Separator.displayName;
var CommandItem = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
  CommandPrimitive.Item,
  {
    ref,
    className: cn(
      "rf-relative rf-flex rf-cursor-default rf-gap-2 rf-select-none rf-items-center rf-rounded-sm rf-px-2 rf-py-1.5 rf-text-sm rf-outline-none data-[disabled=true]:rf-pointer-events-none data-[selected=true]:rf-bg-zinc-100 data-[selected=true]:rf-text-zinc-900 data-[disabled=true]:rf-opacity-50 [&_svg]:rf-pointer-events-none [&_svg]:rf-size-4 [&_svg]:rf-shrink-0 dark:data-[selected=true]:rf-bg-zinc-800 dark:data-[selected=true]:rf-text-zinc-50",
      className
    ),
    ...props
  }
));
CommandItem.displayName = CommandPrimitive.Item.displayName;
var CommandShortcut = ({
  className,
  ...props
}) => {
  return /* @__PURE__ */ jsx2(
    "span",
    {
      className: cn(
        "rf-ml-auto rf-text-xs rf-tracking-widest rf-text-zinc-500 dark:rf-text-zinc-400",
        className
      ),
      ...props
    }
  );
};
CommandShortcut.displayName = "CommandShortcut";

// lib/components/ui/popover.tsx
import * as React2 from "react";
import * as PopoverPrimitive from "@radix-ui/react-popover";
import { jsx as jsx3 } from "react/jsx-runtime";
var Popover = PopoverPrimitive.Root;
var PopoverTrigger = PopoverPrimitive.Trigger;
var PopoverContent = React2.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx3(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx3(
  PopoverPrimitive.Content,
  {
    ref,
    align,
    sideOffset,
    className: cn(
      "rf-z-50 rf-w-72 rf-rounded-md rf-border rf-border-zinc-200 rf-bg-white rf-p-4 rf-text-zinc-950 rf-shadow-md rf-outline-none data-[state=open]:rf-animate-in data-[state=closed]:rf-animate-out data-[state=closed]:rf-fade-out-0 data-[state=open]:rf-fade-in-0 data-[state=closed]:rf-zoom-out-95 data-[state=open]:rf-zoom-in-95 data-[side=bottom]:rf-slide-in-from-top-2 data-[side=left]:rf-slide-in-from-right-2 data-[side=right]:rf-slide-in-from-left-2 data-[side=top]:rf-slide-in-from-bottom-2 rf-origin-[--radix-popover-content-transform-origin] dark:rf-border-zinc-800 dark:rf-bg-zinc-950 dark:rf-text-zinc-50",
      className
    ),
    ...props
  }
) }));
PopoverContent.displayName = PopoverPrimitive.Content.displayName;

// lib/components/RunFrameWithApi/file-selector-combobox.tsx
import { ChevronsUpDown, Check } from "lucide-react";
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
var FileSelectorCombobox = ({
  files,
  onFileChange,
  currentFile
}) => {
  const [open, setOpen] = useState3(false);
  const [file, setFile] = useState3(currentFile);
  useEffect4(() => {
    setFile(currentFile);
  }, [currentFile]);
  return /* @__PURE__ */ jsxs3(Popover, { open, onOpenChange: setOpen, children: [
    /* @__PURE__ */ jsx4(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs3(
      Button,
      {
        variant: "outline",
        role: "combobox",
        "aria-expanded": open,
        className: "rf-w-30 rf-justify-between !rf-font-normal",
        children: [
          file ? file : "Select file",
          /* @__PURE__ */ jsx4(ChevronsUpDown, { className: "rf-opacity-50" })
        ]
      }
    ) }),
    /* @__PURE__ */ jsx4(PopoverContent, { className: "rf-w-fit !rf-p-0", children: /* @__PURE__ */ jsxs3(Command, { children: [
      /* @__PURE__ */ jsx4(CommandInput, { placeholder: "Search for file", className: "rf-h-9" }),
      /* @__PURE__ */ jsxs3(CommandList, { children: [
        /* @__PURE__ */ jsx4(CommandEmpty, { children: "No file found." }),
        /* @__PURE__ */ jsx4(CommandGroup, { children: files.filter(
          (file2) => (file2.endsWith(".tsx") || file2.endsWith(".ts") || file2.endsWith(".jsx") || file2.endsWith(".js")) && !file2.endsWith(".d.ts")
        ).map((file2, i) => /* @__PURE__ */ jsxs3(
          CommandItem,
          {
            value: file2,
            onSelect: (file3) => {
              setFile(file3);
              setOpen(false);
              onFileChange(file3);
            },
            children: [
              file2,
              /* @__PURE__ */ jsx4(
                Check,
                {
                  className: cn(
                    "rf-ml-auto",
                    file2 === currentFile ? "rf-opacity-100" : "rf-opacity-0"
                  )
                }
              )
            ]
          },
          i
        )) })
      ] })
    ] }) })
  ] });
};

// lib/components/RunFrameWithApi/RunFrameWithApi.tsx
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
var debug3 = Debug2("run-frame:RunFrameWithApi");
var guessEntrypoint = (files) => files.find((file) => file.includes("entrypoint.")) ?? files.find((file) => file.includes("index.")) ?? files.find((file) => file.includes("main.")) ?? files.find((file) => file.endsWith(".tsx"));
var guessManualEditsFilePath = (files) => files.find((file) => file.includes("manual-edits.")) ?? files.find((file) => file.includes("manual-edit.")) ?? files.find((file) => file.endsWith(".json"));
var RunFrameWithApi = (props) => {
  const { apiBaseUrl, leftHeaderContent } = props;
  useEffect5(() => {
    if (props.debug) Debug2.enable("run-frame*");
  }, [props.debug]);
  const { startPolling, stopPolling, loadInitialFiles } = useRunFrameStore(
    (s) => ({
      startPolling: s.startPolling,
      stopPolling: s.stopPolling,
      loadInitialFiles: s.loadInitialFiles
    })
  );
  const fsMap = useRunFrameStore((s) => s.fsMap);
  const circuitJson = useRunFrameStore((s) => s.circuitJson);
  const [componentPath, setComponentPath] = useState4("");
  const [isLoadingFiles, setIsLoadingFiles] = useState4(true);
  useEffect5(() => {
    setIsLoadingFiles(true);
    loadInitialFiles().finally(() => setIsLoadingFiles(false));
  }, []);
  useEffect5(() => {
    const files = Array.from(fsMap.keys());
    if (componentPath && files.includes(componentPath)) {
      return;
    }
    const defaultPath = window?.TSCIRCUIT_DEFAULT_MAIN_COMPONENT_PATH;
    if (defaultPath && files.includes(defaultPath)) {
      setComponentPath(defaultPath);
    } else {
      const firstMatch = files.find(
        (file) => (file.endsWith(".tsx") || file.endsWith(".ts") || file.endsWith(".jsx") || file.endsWith(".js")) && !file.endsWith(".d.ts")
      );
      if (firstMatch) {
        setComponentPath(firstMatch);
      }
    }
  }, [fsMap]);
  useSyncPageTitle();
  const {
    editEventsForRender,
    pushEditEvent,
    markRenderStarted,
    markRenderComplete
  } = useEditEventController();
  useEffect5(() => {
    if (apiBaseUrl) {
      window.TSCIRCUIT_FILESERVER_API_BASE_URL = apiBaseUrl;
    }
  }, [apiBaseUrl]);
  useEffect5(() => {
    startPolling();
    return () => stopPolling();
  }, [startPolling, stopPolling]);
  const componentProp = useMemo2(
    () => String(componentPath).length > 0 ? {
      mainComponentPath: componentPath
    } : {},
    [componentPath]
  );
  return /* @__PURE__ */ jsx5(
    RunFrame,
    {
      fsMap,
      showFileMenu: props.showFileMenu,
      isLoadingFiles,
      evalVersion: props.evalVersion,
      forceLatestEvalVersion: props.forceLatestEvalVersion,
      evalWebWorkerBlobUrl: props.evalWebWorkerBlobUrl ?? props.workerBlobUrl,
      enableFetchProxy: props.enableFetchProxy,
      leftHeaderContent: /* @__PURE__ */ jsxs4("div", { className: "rf-flex rf-items-center rf-justify-between rf-w-full", children: [
        props.leftHeaderContent,
        props.showFilesSwitch && /* @__PURE__ */ jsx5("div", { className: "rf-absolute rf-left-1/2 rf-transform rf--translate-x-1/2", children: /* @__PURE__ */ jsx5(
          FileSelectorCombobox,
          {
            currentFile: componentPath,
            files: Array.from(fsMap.keys()),
            onFileChange: (value) => {
              if (typeof fsMap.get(value) === "string") {
                setComponentPath(value);
              }
            }
          }
        ) })
      ] }),
      defaultToFullScreen: props.defaultToFullScreen,
      showToggleFullScreen: props.showToggleFullScreen,
      onInitialRender: () => {
        debug3("onInitialRender / markRenderStarted");
        markRenderStarted();
      },
      onRenderFinished: () => {
        debug3("onRenderFinished / markRenderComplete");
        markRenderComplete();
      },
      editEvents: editEventsForRender,
      onEditEvent: (ee) => {
        pushEditEvent(ee);
        fetch(`${API_BASE}/events/create`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            event_type: "USER_CREATED_MANUAL_EDIT",
            ...ee
          })
        });
        const manualEditsFilePath = guessManualEditsFilePath(Array.from(fsMap.keys())) ?? "manual-edits.json";
        const manualEditsFile = fsMap.get(manualEditsFilePath);
        const updatedManualEdits = JSON.parse(
          manualEditsFile ?? "{}"
        );
        applyEditEventsToManualEditsFile({
          circuitJson,
          editEvents: [ee],
          manualEditsFile: updatedManualEdits
        });
        fetch(`${API_BASE}/files/upsert`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            file_path: manualEditsFilePath,
            text_content: JSON.stringify(updatedManualEdits),
            initiator: "runframe"
          })
        });
      },
      ...componentProp
    }
  );
};

// lib/components/RunFrameForCli/RunFrameForCli.tsx
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
var RunFrameForCli = (props) => {
  const [shouldLoadLatestEval, setLoadLatestEval] = useLocalStorageState(
    "load-latest-eval",
    true
  );
  return /* @__PURE__ */ jsx6(
    RunFrameWithApi,
    {
      debug: props.debug,
      forceLatestEvalVersion: !props.workerBlobUrl && shouldLoadLatestEval,
      defaultToFullScreen: true,
      showToggleFullScreen: false,
      workerBlobUrl: props.workerBlobUrl,
      showFilesSwitch: true,
      showFileMenu: false,
      enableFetchProxy: props.enableFetchProxy,
      leftHeaderContent: /* @__PURE__ */ jsxs5("div", { className: "rf-flex rf-items-center rf-justify-between", children: [
        /* @__PURE__ */ jsx6(
          FileMenuLeftHeader,
          {
            isWebEmbedded: false,
            shouldLoadLatestEval: !props.workerBlobUrl && shouldLoadLatestEval,
            onChangeShouldLoadLatestEval: (newShouldLoadLatestEval) => {
              setLoadLatestEval(newShouldLoadLatestEval);
              globalThis.runFrameWorker = null;
            }
          }
        ),
        props.scenarioSelectorContent
      ] })
    }
  );
};
export {
  BomTable,
  CadViewer,
  CircuitJsonPreview,
  ImportComponentDialog,
  PCBViewer as PcbViewer,
  PcbViewerWithContainerHeight,
  RunFrame,
  RunFrameForCli,
  RunFrameWithApi,
  SchematicViewer,
  guessEntrypoint,
  guessManualEditsFilePath,
  linkify,
  mapJLCComponentToSearchResult,
  mapTscircuitSnippetToSearchResult,
  searchJLCComponents,
  searchTscircuitComponents,
  useOrderDialog,
  useOrderDialogCli
};
