import {
  API_BASE,
  BomTable,
  Button,
  CadViewer,
  CircuitJsonPreview,
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  FileMenuLeftHeader,
  ImportComponentDialog2,
  ImportComponentDialogForCli,
  Input,
  PCBViewer,
  PcbViewerWithContainerHeight,
  SchematicViewer,
  Tabs,
  TabsContent,
  TabsList,
  TabsTrigger,
  cn,
  debug_default,
  linkify,
  registryKy,
  toast,
  useLocalStorageState,
  useOrderDialog,
  useOrderDialogCli,
  useRunFrameStore,
  useRunnerStore,
  useStyles
} from "./chunk-P3KSZFKI.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/ui/LoadingSkeleton.tsx
import { jsx, jsxs } from "react/jsx-runtime";
var LoadingSkeleton = ({
  message = "Loading files..."
}) => {
  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: message }) }) }) })
  ] });
};

// lib/components/RunFrame/RunFrame.tsx
import { Fragment, jsx as jsx2, jsxs as jsxs2 } 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,
            projectConfig: {
              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,
        projectConfig: {
          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__ */ jsx2(LoadingSkeleton, {});
  }
  return /* @__PURE__ */ jsx2(
    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__ */ jsxs2(Fragment, { children: [
        props.showRunButton && /* @__PURE__ */ jsxs2("div", { className: "rf-relative rf-inline-flex", children: [
          /* @__PURE__ */ jsxs2(
            "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__ */ jsx2(Loader2, { className: "rf-w-3 rf-h-3 rf-animate-spin" }) : /* @__PURE__ */ jsx2(Play, { className: "rf-w-3 rf-h-3" })
              ]
            }
          ),
          isRunning && /* @__PURE__ */ jsx2("div", { className: "rf-flex rf-items-center rf-ml-1", children: /* @__PURE__ */ jsx2(
            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__ */ jsx2(
                Square,
                {
                  className: "!rf-h-2.5 !rf-w-2.5",
                  fill: "currentColor",
                  stroke: "currentColor"
                }
              )
            }
          ) })
        ] }),
        props.showFileMenu !== false && /* @__PURE__ */ jsx2(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/EnhancedFileSelectorCombobox/EnhancedFileSelectorCombobox.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 jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
var Command = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx3(
  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__ */ jsxs3(
  "div",
  {
    className: "rf-flex rf-items-center rf-border-b rf-px-3",
    "cmdk-input-wrapper": "",
    children: [
      /* @__PURE__ */ jsx3(Search, { className: "rf-mr-2 rf-h-4 rf-w-4 rf-shrink-0 rf-opacity-50" }),
      /* @__PURE__ */ jsx3(
        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__ */ jsx3(
  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__ */ jsx3(
  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__ */ jsx3(
  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__ */ jsx3(
  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__ */ jsx3(
  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__ */ jsx3(
    "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 jsx4 } from "react/jsx-runtime";
var Popover = PopoverPrimitive.Root;
var PopoverTrigger = PopoverPrimitive.Trigger;
var PopoverContent = React2.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx4(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx4(
  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/EnhancedFileSelectorCombobox/EnhancedFileSelectorCombobox.tsx
import {
  ChevronsUpDown,
  Check,
  ChevronRight,
  File,
  FileText,
  Code,
  Folder
} from "lucide-react";

// lib/components/RunFrameWithApi/EnhancedFileSelectorCombobox/parseFilesToTree.ts
function parseFilesToTree(files) {
  const root = [];
  const nodeMap = /* @__PURE__ */ new Map();
  nodeMap.set("", { name: "", path: "", type: "folder", children: root });
  for (const filePath of files) {
    const parts = filePath.split("/");
    let currentPath = "";
    for (let i = 0; i < parts.length; i++) {
      const part = parts[i];
      const parentPath = currentPath;
      currentPath = currentPath ? `${currentPath}/${part}` : part;
      if (!nodeMap.has(currentPath)) {
        const isFile = i === parts.length - 1;
        const node = {
          name: part,
          path: currentPath,
          type: isFile ? "file" : "folder",
          children: isFile ? void 0 : []
        };
        nodeMap.set(currentPath, node);
        const parent = nodeMap.get(parentPath);
        if (parent && parent.children) {
          parent.children.push(node);
        }
      }
    }
  }
  return root;
}
function findNode(nodes, path) {
  for (const node of nodes) {
    if (node.path === path) return node;
    if (node.children) {
      const found = findNode(node.children, path);
      if (found) return found;
    }
  }
  return null;
}
function getCurrentFolderContents(tree, currentFolder) {
  let targetNode;
  if (!currentFolder) {
    targetNode = { name: "", path: "", type: "folder", children: tree };
  } else {
    targetNode = findNode(tree, currentFolder);
  }
  if (!targetNode || !targetNode.children) {
    return { files: [], folders: [] };
  }
  const files = targetNode.children.filter((node) => node.type === "file");
  const folders = targetNode.children.filter((node) => node.type === "folder");
  files.sort((a, b) => a.name.localeCompare(b.name));
  folders.sort((a, b) => a.name.localeCompare(b.name));
  return { files, folders };
}

// lib/components/RunFrameWithApi/EnhancedFileSelectorCombobox/EnhancedFileSelectorCombobox.tsx
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
var defaultFileIcon = (fileName) => {
  if (fileName.endsWith(".tsx") || fileName.endsWith(".jsx")) {
    return /* @__PURE__ */ jsx5(Code, { className: "rf-h-4 rf-w-4 rf-text-blue-500" });
  }
  if (fileName.endsWith(".md") || fileName.endsWith(".txt")) {
    return /* @__PURE__ */ jsx5(FileText, { className: "rf-h-4 rf-w-4 rf-text-gray-600" });
  }
  return /* @__PURE__ */ jsx5(File, { className: "rf-h-4 rf-w-4 rf-text-gray-500" });
};
var defaultFileFilter = (filename) => {
  return filename.endsWith(".tsx") || filename.endsWith(".circuit.json") || filename.endsWith(".jsx");
};
var defaultDisplayName = (filename) => {
  return filename.split("/").pop() || "";
};
var EnhancedFileSelectorCombobox = ({
  files,
  onFileChange,
  currentFile,
  config = {}
}) => {
  const [open, setOpen] = useState3(false);
  const [file, setFile] = useState3(currentFile);
  const [currentFolder, setCurrentFolder] = useState3("");
  const [currentFileIndex, setCurrentFileIndex] = useState3(0);
  const [searchValue, setSearchValue] = useState3("");
  const {
    fileFilter = defaultFileFilter,
    getDisplayName = defaultDisplayName,
    placeholder = "Select file",
    searchPlaceholder = "Search for file",
    emptyMessage = "No files found in this directory."
  } = config;
  useEffect4(() => {
    setFile(currentFile);
  }, [currentFile]);
  const filteredFiles = files.filter(fileFilter);
  const fileTree = parseFilesToTree(filteredFiles);
  const { files: currentFiles, folders: currentFolders } = getCurrentFolderContents(fileTree, currentFolder);
  const getSearchResults = () => {
    if (!searchValue.trim()) return { currentDirResults: [], globalResults: [] };
    const searchTerm = searchValue.toLowerCase();
    const allFiles = filteredFiles.map((path) => {
      const fileName = path.split("/").pop() || "";
      return { path, fileName };
    });
    const matchingFiles = allFiles.filter(
      (file2) => file2.fileName.toLowerCase().includes(searchTerm) || file2.path.toLowerCase().includes(searchTerm)
    );
    const currentDirResults = matchingFiles.filter((file2) => {
      if (!currentFolder) {
        return !file2.path.includes("/");
      }
      const fileDir = file2.path.substring(0, file2.path.lastIndexOf("/"));
      return fileDir === currentFolder;
    });
    const globalResults = matchingFiles.filter((file2) => {
      if (!currentFolder) {
        return file2.path.includes("/");
      }
      const fileDir = file2.path.substring(0, file2.path.lastIndexOf("/"));
      return fileDir !== currentFolder;
    });
    return { currentDirResults, globalResults };
  };
  const searchResults = getSearchResults();
  const isSearching = searchValue.trim().length > 0;
  const navigateToFolder = (folderPath) => {
    setCurrentFolder(folderPath);
    setCurrentFileIndex(0);
  };
  const selectFile = (filePath, index) => {
    setFile(filePath);
    setCurrentFileIndex(index);
    setOpen(false);
    onFileChange(filePath);
  };
  useEffect4(() => {
    if (currentFiles.length > 0) {
      const fileInCurrentFolder = currentFiles.findIndex(
        (f) => f.path === currentFile
      );
      if (fileInCurrentFolder >= 0) {
        setCurrentFileIndex(fileInCurrentFolder);
      }
    }
  }, [currentFiles, currentFile]);
  const displayPath = currentFolder || "/";
  const shortDisplayPath = displayPath.length > 25 ? "..." + displayPath.slice(-22) : displayPath;
  const getDropdownWidth = () => {
    return "rf-w-[400px] rf-min-w-[400px] rf-max-w-[400px]";
  };
  return /* @__PURE__ */ jsx5("div", { className: "rf-flex rf-items-center rf-gap-1", children: /* @__PURE__ */ jsxs4(
    Popover,
    {
      open,
      onOpenChange: (newOpen) => {
        setOpen(newOpen);
        if (!newOpen) setSearchValue("");
      },
      children: [
        /* @__PURE__ */ jsx5(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs4(
          Button,
          {
            variant: "outline",
            role: "combobox",
            "aria-expanded": open,
            className: "rf-w-fit rf-min-w-32 rf-max-w-64 rf-justify-center rf-items-center rf-gap-1 !rf-font-normal",
            children: [
              /* @__PURE__ */ jsx5("span", { className: "rf-truncate rf-text-left", children: file ? getDisplayName(file) : placeholder }),
              /* @__PURE__ */ jsx5(ChevronsUpDown, { className: "rf-opacity-50 rf-flex-shrink-0" })
            ]
          }
        ) }),
        /* @__PURE__ */ jsx5(
          PopoverContent,
          {
            className: cn(
              "!rf-p-0 !rf-overflow-x-auto !rf-z-[200]",
              getDropdownWidth()
            ),
            children: /* @__PURE__ */ jsxs4(Command, { shouldFilter: false, children: [
              /* @__PURE__ */ jsx5(
                CommandInput,
                {
                  placeholder: searchPlaceholder,
                  className: "rf-h-9 rf-w-full",
                  value: searchValue,
                  onValueChange: setSearchValue
                }
              ),
              /* @__PURE__ */ jsx5("div", { className: "rf-px-3 rf-py-2 rf-border-t rf-border-b rf-border-gray-200 rf-bg-slate-50", children: /* @__PURE__ */ jsxs4("div", { className: "rf-flex rf-items-center rf-text-xs rf-text-slate-600 rf-min-w-0 rf-overflow-hidden", children: [
                /* @__PURE__ */ jsx5(
                  "button",
                  {
                    onClick: () => navigateToFolder(""),
                    className: "rf-text-blue-600 hover:rf-text-blue-800 rf-underline rf-cursor-pointer rf-bg-transparent rf-border-none rf-p-0 rf-flex-shrink-0",
                    children: "root"
                  }
                ),
                currentFolder.split("/").filter(Boolean).map((segment, index, array) => {
                  const pathToSegment = array.slice(0, index + 1).join("/");
                  return /* @__PURE__ */ jsxs4(
                    "span",
                    {
                      className: "rf-flex rf-items-center rf-min-w-0",
                      children: [
                        /* @__PURE__ */ jsx5("span", { className: "rf-mx-1 rf-flex-shrink-0", children: "/" }),
                        index === array.length - 1 ? /* @__PURE__ */ jsx5(
                          "span",
                          {
                            className: "rf-text-slate-800 rf-truncate rf-max-w-[150px]",
                            title: segment,
                            children: segment
                          }
                        ) : /* @__PURE__ */ jsx5(
                          "button",
                          {
                            onClick: () => navigateToFolder(pathToSegment),
                            className: "rf-text-blue-600 hover:rf-text-blue-800 rf-underline rf-cursor-pointer rf-bg-transparent rf-border-none rf-p-0 rf-truncate rf-max-w-[100px]",
                            title: segment,
                            children: segment
                          }
                        )
                      ]
                    },
                    pathToSegment
                  );
                })
              ] }) }),
              /* @__PURE__ */ jsx5(CommandList, { className: "rf-max-h-[70vh] rf-overflow-y-auto", children: !isSearching ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
                /* @__PURE__ */ jsx5(CommandEmpty, { children: emptyMessage }),
                currentFiles.length > 0 && /* @__PURE__ */ jsx5(
                  CommandGroup,
                  {
                    className: `rf-border-b rf-border-gray-200 rf-pb-1`,
                    children: currentFiles.map((fileNode, index) => /* @__PURE__ */ jsxs4(
                      CommandItem,
                      {
                        value: fileNode.path,
                        onSelect: () => selectFile(fileNode.path, index),
                        className: cn(
                          fileNode.path === currentFile && "rf-font-medium"
                        ),
                        children: [
                          /* @__PURE__ */ jsx5("span", { className: "rf-mr-2", children: defaultFileIcon(fileNode.name) }),
                          getDisplayName(fileNode.name),
                          /* @__PURE__ */ jsx5(
                            Check,
                            {
                              className: cn(
                                "rf-ml-auto rf-h-4 rf-w-4",
                                fileNode.path === currentFile ? "rf-opacity-100" : "rf-opacity-0"
                              )
                            }
                          )
                        ]
                      },
                      fileNode.path
                    ))
                  }
                ),
                currentFolders.length > 0 && /* @__PURE__ */ jsx5(
                  CommandGroup,
                  {
                    className: `rf-border-b rf-border-gray-200 rf-pb-1`,
                    children: currentFolders.map((folderNode) => /* @__PURE__ */ jsxs4(
                      CommandItem,
                      {
                        value: `folder-${folderNode.path}`,
                        onSelect: () => navigateToFolder(folderNode.path),
                        className: "rf-text-slate-600 hover:rf-text-slate-900",
                        children: [
                          /* @__PURE__ */ jsx5(Folder, { className: "rf-mr-2 rf-h-4 rf-w-4 rf-text-blue-600" }),
                          folderNode.name,
                          /* @__PURE__ */ jsx5(ChevronRight, { className: "rf-ml-auto rf-h-4 rf-w-4" })
                        ]
                      },
                      folderNode.path
                    ))
                  }
                ),
                currentFiles.length === 0 && currentFolders.length === 0 && /* @__PURE__ */ jsx5("div", { className: "rf-p-4 rf-text-center rf-text-slate-500 rf-text-sm", children: "No files or folders in this directory" })
              ] }) : /* @__PURE__ */ jsx5(Fragment2, { children: searchResults.currentDirResults.length === 0 && searchResults.globalResults.length === 0 ? /* @__PURE__ */ jsxs4(CommandEmpty, { children: [
                'No files found matching "',
                searchValue,
                '".'
              ] }) : /* @__PURE__ */ jsxs4(Fragment2, { children: [
                searchResults.currentDirResults.length > 0 && /* @__PURE__ */ jsx5(CommandGroup, { className: "rf-border-b rf-border-gray-200 rf-pb-1", children: searchResults.currentDirResults.map(
                  (file2, index) => /* @__PURE__ */ jsxs4(
                    CommandItem,
                    {
                      value: file2.path,
                      onSelect: () => {
                        setFile(file2.path);
                        setOpen(false);
                        onFileChange(file2.path);
                      },
                      className: cn(
                        file2.path === currentFile && "rf-font-medium"
                      ),
                      children: [
                        /* @__PURE__ */ jsx5("span", { className: "rf-mr-2", children: defaultFileIcon(file2.fileName) }),
                        /* @__PURE__ */ jsxs4("div", { className: "rf-flex rf-items-center rf-w-full rf-min-w-0", children: [
                          /* @__PURE__ */ jsx5("span", { className: "rf-truncate rf-flex-1", children: getDisplayName(file2.fileName) }),
                          /* @__PURE__ */ jsx5("span", { className: "rf-text-xs rf-text-muted-foreground rf-ml-2 rf-truncate rf-max-w-[120px]", children: currentFolder || "/" }),
                          file2.path === currentFile && /* @__PURE__ */ jsx5(Check, { className: "rf-ml-2 rf-h-4 rf-w-4 rf-flex-shrink-0" })
                        ] })
                      ]
                    },
                    file2.path
                  )
                ) }),
                searchResults.globalResults.length > 0 && /* @__PURE__ */ jsx5(CommandGroup, { className: "rf-pb-1", children: searchResults.globalResults.map((file2) => /* @__PURE__ */ jsxs4(
                  CommandItem,
                  {
                    value: file2.path,
                    onSelect: () => {
                      setFile(file2.path);
                      setOpen(false);
                      onFileChange(file2.path);
                    },
                    className: cn(
                      file2.path === currentFile && "rf-font-medium"
                    ),
                    children: [
                      /* @__PURE__ */ jsx5("span", { className: "rf-mr-2", children: defaultFileIcon(file2.fileName) }),
                      /* @__PURE__ */ jsxs4("div", { className: "rf-flex rf-items-center rf-w-full rf-min-w-0", children: [
                        /* @__PURE__ */ jsx5("span", { className: "rf-truncate rf-flex-1", children: getDisplayName(file2.fileName) }),
                        /* @__PURE__ */ jsx5("span", { className: "rf-text-xs rf-text-muted-foreground rf-ml-2 rf-truncate rf-max-w-[120px]", children: file2.path.substring(
                          0,
                          file2.path.lastIndexOf("/")
                        ) || "/" }),
                        file2.path === currentFile && /* @__PURE__ */ jsx5(Check, { className: "rf-ml-2 rf-h-4 rf-w-4 rf-flex-shrink-0" })
                      ] })
                    ]
                  },
                  file2.path
                )) })
              ] }) }) })
            ] })
          }
        )
      ]
    }
  ) });
};

// lib/utils/get-board-files-from-config.ts
import { projectConfig } from "@tscircuit/props";
import micromatch from "micromatch";
var DEFAULT_BOARD_FILE_EXTENSIONS = [
  ".tsx",
  ".ts",
  ".jsx",
  ".js",
  ".circuit.json"
];
var DEFAULT_BOARD_FILE_FILTER = (filename) => DEFAULT_BOARD_FILE_EXTENSIONS.some((ext) => filename.endsWith(ext)) && !filename.endsWith(".d.ts");
var parseProjectConfig = (configContent) => {
  if (!configContent) return null;
  try {
    const parsedJson = JSON.parse(configContent);
    return projectConfig.parse(parsedJson);
  } catch (error) {
    console.warn("Failed to parse tscircuit.config.json", error);
    return null;
  }
};
var getBoardFilesFromConfig = (files, configContent) => {
  const parsedConfig = parseProjectConfig(configContent);
  const includeBoardFiles = parsedConfig?.includeBoardFiles?.filter(Boolean);
  if (includeBoardFiles && includeBoardFiles.length > 0) {
    return micromatch(files, includeBoardFiles, {
      dot: true
    });
  }
  return files.filter(DEFAULT_BOARD_FILE_FILTER);
};

// lib/components/RunFrameWithApi/RunFrameWithApi.tsx
import { jsx as jsx6, jsxs as jsxs5 } 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 allFiles = useMemo2(() => Array.from(fsMap.keys()), [fsMap]);
  const projectConfigContent = useMemo2(() => {
    const rawConfig = fsMap.get("tscircuit.config.json");
    return typeof rawConfig === "string" ? rawConfig : void 0;
  }, [fsMap]);
  const boardFiles = useMemo2(
    () => getBoardFilesFromConfig(allFiles, projectConfigContent),
    [allFiles, projectConfigContent]
  );
  const circuitJson = useRunFrameStore((s) => s.circuitJson);
  const [componentPath, setComponentPath] = useState4(
    props.initialMainComponentPath ?? ""
  );
  const [isLoadingFiles, setIsLoadingFiles] = useState4(true);
  useEffect5(() => {
    setIsLoadingFiles(true);
    loadInitialFiles().finally(() => setIsLoadingFiles(false));
  }, []);
  useEffect5(() => {
    if (componentPath && boardFiles.includes(componentPath)) {
      return;
    }
    const defaultPath = window?.TSCIRCUIT_DEFAULT_MAIN_COMPONENT_PATH;
    const candidatePaths = [props.initialMainComponentPath, defaultPath].filter(
      (value) => Boolean(value)
    );
    for (const candidate of candidatePaths) {
      if (boardFiles.includes(candidate)) {
        setComponentPath(candidate);
        return;
      }
    }
    const firstMatch = boardFiles[0];
    if (firstMatch) {
      setComponentPath(firstMatch);
    }
  }, [boardFiles, props.initialMainComponentPath, componentPath]);
  useEffect5(() => {
    if (!componentPath) return;
    props.onMainComponentPathChange?.(componentPath);
  }, [componentPath, props.onMainComponentPathChange]);
  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__ */ jsx6(
    RunFrame,
    {
      fsMap,
      showFileMenu: props.showFileMenu,
      isLoadingFiles,
      evalVersion: props.evalVersion,
      forceLatestEvalVersion: props.forceLatestEvalVersion,
      evalWebWorkerBlobUrl: props.evalWebWorkerBlobUrl ?? props.workerBlobUrl,
      enableFetchProxy: props.enableFetchProxy,
      leftHeaderContent: /* @__PURE__ */ jsxs5("div", { className: "rf-flex rf-items-center rf-justify-between rf-w-full", children: [
        props.leftHeaderContent,
        props.showFilesSwitch && /* @__PURE__ */ jsx6("div", { className: "rf-absolute rf-left-1/2 rf-transform rf--translate-x-1/2", children: /* @__PURE__ */ jsx6(
          EnhancedFileSelectorCombobox,
          {
            currentFile: componentPath,
            files: boardFiles,
            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 { useCallback as useCallback3, useState as useState5 } from "react";
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
var RunFrameForCli = (props) => {
  const [shouldLoadLatestEval, setLoadLatestEval] = useLocalStorageState(
    "load-latest-eval",
    true
  );
  const [initialMainComponentPath] = useState5(() => {
    if (typeof window === "undefined") return void 0;
    const params = new URLSearchParams(window.location.hash.slice(1));
    return params.get("main_component") ?? void 0;
  });
  const updateMainComponentHash = useCallback3((mainComponentPath) => {
    if (typeof window === "undefined") return;
    const params = new URLSearchParams(window.location.hash.slice(1));
    if (params.get("main_component") === mainComponentPath) return;
    params.set("main_component", mainComponentPath);
    const newHash = params.toString();
    const newUrl = `${window.location.pathname}${window.location.search}` + (newHash.length > 0 ? `#${newHash}` : "");
    window.history.replaceState(null, "", newUrl);
  }, []);
  return /* @__PURE__ */ jsx7(
    RunFrameWithApi,
    {
      debug: props.debug,
      forceLatestEvalVersion: !props.workerBlobUrl && shouldLoadLatestEval,
      defaultToFullScreen: true,
      showToggleFullScreen: false,
      workerBlobUrl: props.workerBlobUrl,
      showFilesSwitch: true,
      showFileMenu: false,
      enableFetchProxy: props.enableFetchProxy,
      initialMainComponentPath,
      onMainComponentPathChange: updateMainComponentHash,
      leftHeaderContent: /* @__PURE__ */ jsxs6("div", { className: "rf-flex rf-items-center rf-justify-between", children: [
        /* @__PURE__ */ jsx7(
          FileMenuLeftHeader,
          {
            isWebEmbedded: false,
            shouldLoadLatestEval: !props.workerBlobUrl && shouldLoadLatestEval,
            onChangeShouldLoadLatestEval: (newShouldLoadLatestEval) => {
              setLoadLatestEval(newShouldLoadLatestEval);
              globalThis.runFrameWorker = null;
            }
          }
        ),
        props.scenarioSelectorContent
      ] })
    }
  );
};

// lib/components/ImportComponentDialog/ImportComponentDialog.tsx
import "react";
import { useState as useState6, useEffect as useEffect6 } from "react";
import { Loader2 as Loader22, Search as Search2, ExternalLink } from "lucide-react";

// lib/components/ImportComponentDialog/jlc-api.ts
var searchJLCComponents = async (query, limit = 10) => {
  try {
    const encodedQuery = encodeURIComponent(query);
    const response = await fetch(
      `https://jlcsearch.tscircuit.com/api/search?limit=${limit}&q=${encodedQuery}`
    );
    if (!response.ok) {
      throw new Error(
        `JLC API error: ${response.status} ${response.statusText}`
      );
    }
    const data = await response.json();
    return data.components || [];
  } catch (error) {
    console.error("Error searching JLC components:", error);
    throw error;
  }
};
var mapJLCComponentToSearchResult = (jlcComponent) => {
  return {
    id: `jlc-${jlcComponent.lcsc}`,
    name: jlcComponent.mfr,
    description: jlcComponent.description,
    source: "jlcpcb",
    partNumber: `C${jlcComponent.lcsc}`,
    package: jlcComponent.package,
    price: jlcComponent.price
  };
};

// lib/components/ImportComponentDialog/kicad-api.ts
import Fuse from "fuse.js";
var KICAD_FOOTPRINTS = null;
var KICAD_FOOTPRINTS_PROMISE = null;
var getKicadFootprints = async () => {
  if (KICAD_FOOTPRINTS) return KICAD_FOOTPRINTS;
  if (KICAD_FOOTPRINTS_PROMISE) return KICAD_FOOTPRINTS_PROMISE;
  KICAD_FOOTPRINTS_PROMISE = fetch(
    "https://kicad-mod-cache.tscircuit.com/kicad_files.json"
  ).then((r) => r.json()).then((footprints) => {
    KICAD_FOOTPRINTS = footprints;
    KICAD_FOOTPRINTS_PROMISE = null;
    return footprints;
  });
  return KICAD_FOOTPRINTS_PROMISE;
};
var fuse = null;
var searchKicadFootprints = async (query, limit = 20) => {
  const footprints = await getKicadFootprints();
  if (!fuse) {
    fuse = new Fuse(footprints);
  }
  return fuse.search(query).slice(0, limit).map((r) => r.item);
};
var mapKicadFootprintToSearchResult = (footprintPath) => {
  const cleanedFootprint = footprintPath.replace(".pretty/", ":").replace(".kicad_mod", "");
  const footprintString = `kicad:${cleanedFootprint}`;
  return {
    id: `kicad-${footprintPath}`,
    name: footprintString,
    description: cleanedFootprint,
    source: "kicad"
  };
};

// lib/components/ImportComponentDialog/tscircuit-registry-api.ts
var searchTscircuitComponents = async (query) => {
  try {
    const response = await fetch(
      "https://registry-api.tscircuit.com/packages/search",
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json"
        },
        body: JSON.stringify({ query })
      }
    );
    if (!response.ok) {
      throw new Error(
        `tscircuit Registry API error: ${response.status} ${response.statusText}`
      );
    }
    const data = await response.json();
    return data.packages || [];
  } catch (error) {
    console.error("Error searching tscircuit components:", error);
    throw error;
  }
};
var mapTscircuitSnippetToSearchResult = (tscircuitSnippet) => {
  return {
    id: `tscircuit-${tscircuitSnippet.package_id}`,
    name: tscircuitSnippet.unscoped_name,
    description: tscircuitSnippet.description || `Component by ${tscircuitSnippet.owner_github_username}`,
    source: "tscircuit.com",
    partNumber: tscircuitSnippet.name,
    owner: String(tscircuitSnippet.owner_github_username)
  };
};

// lib/optional-features/importing/import-component-from-jlcpcb.ts
import { fetchEasyEDAComponent, convertRawEasyToTsx } from "easyeda/browser";
import ky from "ky";
var importComponentFromJlcpcb = async (jlcpcbPartNumber, opts) => {
  const component = await fetchEasyEDAComponent(jlcpcbPartNumber, {
    // @ts-ignore
    fetch: (url, options) => {
      return fetch(`${API_BASE}/proxy`, {
        ...options,
        headers: {
          ...options?.headers,
          "X-Target-Url": url.toString(),
          "X-Sender-Origin": options?.headers?.origin ?? "",
          "X-Sender-Host": options?.headers?.host ?? "https://easyeda.com",
          "X-Sender-Referer": options?.headers?.referer ?? "",
          "X-Sender-User-Agent": options?.headers?.userAgent ?? "",
          "X-Sender-Cookie": options?.headers?.cookie ?? "",
          ...opts?.headers
        }
      });
    }
  });
  const tsx = await convertRawEasyToTsx(component);
  const fileName = tsx.match(/export const (\w+) = .*/)?.[1];
  if (!fileName) {
    console.error("COULD NOT DETERMINE FILE NAME OF CONVERTED COMPONENT:", tsx);
    throw new Error(`Could not determine file name of converted component`);
  }
  const filePath = `imports/${fileName}.tsx`;
  await ky.post(`${API_BASE}/files/upsert`, {
    json: {
      file_path: filePath,
      text_content: tsx
    }
  });
  return { filePath };
};

// lib/components/ImportComponentDialog/ImportComponentDialog.tsx
import Debug3 from "debug";
import { Fragment as Fragment3, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
var debug4 = Debug3("run-frame:ImportComponentDialog");
var ImportComponentDialog = ({
  isOpen,
  onClose,
  proxyRequestHeaders,
  onImport
}) => {
  const [searchQuery, setSearchQuery] = useState6("");
  const [searchResults, setSearchResults] = useState6(
    []
  );
  const [hasSearched, setHasSearched] = useState6(false);
  const [isLoading, setIsLoading] = useState6(false);
  const [selectedComponent, setSelectedComponent] = useState6(null);
  const [activeTab, setActiveTab] = useState6("tscircuit.com");
  const [detailsOpen, setDetailsOpen] = useState6(false);
  const [detailsComponent, setDetailsComponent] = useState6(null);
  const [packageDetails, setPackageDetails] = useState6(null);
  const [packageDetailsLoading, setPackageDetailsLoading] = useState6(false);
  const [previewActiveTab, setPreviewActiveTab] = useState6(
    "pcb"
  );
  const pushEvent = useRunFrameStore((s) => s.pushEvent);
  const handleImport = onImport ? (component) => onImport(component) : (component) => {
    toast.promise(
      async () => {
        if (component.source === "tscircuit.com") {
          await pushEvent({
            event_type: "INSTALL_PACKAGE",
            full_package_name: `@tsci/${component.owner}.${component.name}`
          });
          throw new Error("Not implemented");
        } else if (component.source === "jlcpcb") {
          const { filePath } = await importComponentFromJlcpcb(
            component.partNumber,
            { headers: proxyRequestHeaders }
          );
          return { filePath };
        } else if (component.source === "kicad") {
          await navigator.clipboard.writeText(component.name);
          return { footprint: component.name };
        }
      },
      {
        loading: `Importing component: "${component.name}"`,
        error: (error) => {
          console.error("IMPORT ERROR", error);
          return `Error importing component: "${component.name}": ${error.toString()}`;
        },
        success: (data) => {
          if (data?.footprint) {
            return `Copied "${data.footprint}" to clipboard`;
          }
          return data?.filePath ? `Imported to "${data.filePath}"` : "Import Successful";
        }
      }
    );
  };
  const fetchPackageDetails = async (owner, name) => {
    setPackageDetailsLoading(true);
    try {
      const response = await fetch(
        `https://registry-api.tscircuit.com/packages/get?name=${encodeURIComponent(`${owner}/${name}`)}`
      );
      if (response.ok) {
        const data = await response.json();
        setPackageDetails(data.package || null);
      }
    } catch (error) {
      console.error("Error fetching package details:", error);
      setPackageDetails(null);
    } finally {
      setPackageDetailsLoading(false);
    }
  };
  const handleSearch = async () => {
    if (!searchQuery.trim()) return;
    setIsLoading(true);
    const isJlcPartNumber = /^C\d+/.test(searchQuery);
    try {
      if (activeTab === "jlcpcb") {
        const query = isJlcPartNumber ? searchQuery.substring(1) : searchQuery;
        const jlcComponents = await searchJLCComponents(query, 10);
        const mappedResults = jlcComponents.map(mapJLCComponentToSearchResult);
        setSearchResults(mappedResults);
      } else if (activeTab === "kicad") {
        const kicadFootprints = await searchKicadFootprints(searchQuery, 20);
        const mappedResults = kicadFootprints.map(
          mapKicadFootprintToSearchResult
        );
        setSearchResults(mappedResults);
      } else {
        const tscircuitComponents = await searchTscircuitComponents(searchQuery);
        const mappedResults = tscircuitComponents.map(
          mapTscircuitSnippetToSearchResult
        );
        setSearchResults(mappedResults);
      }
    } catch (error) {
      console.error("Error searching components:", error);
      setSearchResults([]);
    } finally {
      setIsLoading(false);
      setHasSearched(true);
    }
  };
  const handleKeyDown = (e) => {
    if (e.key === "Enter") {
      handleSearch();
    }
  };
  useEffect6(() => {
    setSearchResults([]);
    setSelectedComponent(null);
  }, [activeTab]);
  const showDetails = (component) => {
    setDetailsComponent(component);
    setDetailsOpen(true);
    setPackageDetails(null);
    setPreviewActiveTab("pcb");
    if (component.source === "tscircuit.com" && component.owner) {
      const packageName = component.name.split("/").pop() || component.name;
      fetchPackageDetails(component.owner, packageName);
    }
  };
  return /* @__PURE__ */ jsxs7(Dialog, { open: isOpen, onOpenChange: () => onClose(), children: [
    /* @__PURE__ */ jsxs7(
      DialogContent,
      {
        style: {
          width: "calc(100vw - 2rem)"
        },
        className: "rf-rounded-sm rf-max-h-[90vh] rf-overflow-y-auto rf-flex rf-flex-col",
        children: [
          /* @__PURE__ */ jsxs7(DialogHeader, { children: [
            /* @__PURE__ */ jsx8(DialogTitle, { className: "rf-text-lg sm:rf-text-xl", children: "Import Component" }),
            /* @__PURE__ */ jsx8(DialogDescription, { className: "rf-text-sm", children: "Search for components from tscircuit.com or JLCPCB parts library." })
          ] }),
          /* @__PURE__ */ jsxs7(
            Tabs,
            {
              value: activeTab,
              onValueChange: (value) => setActiveTab(value),
              children: [
                /* @__PURE__ */ jsxs7(TabsList, { className: "rf-grid rf-w-full rf-grid-cols-1 sm:rf-grid-cols-3 rf-h-auto", children: [
                  /* @__PURE__ */ jsx8(
                    TabsTrigger,
                    {
                      value: "tscircuit.com",
                      className: "rf-text-xs sm:rf-text-sm",
                      children: "tscircuit.com"
                    }
                  ),
                  /* @__PURE__ */ jsx8(TabsTrigger, { value: "jlcpcb", className: "rf-text-xs sm:rf-text-sm", children: "JLCPCB Parts" }),
                  /* @__PURE__ */ jsx8(TabsTrigger, { value: "kicad", className: "rf-text-xs sm:rf-text-sm", children: "KiCad" })
                ] }),
                /* @__PURE__ */ jsxs7("div", { className: "rf-flex rf-items-center rf-gap-2 rf-mt-4", children: [
                  /* @__PURE__ */ jsxs7("div", { className: "rf-relative rf-flex-grow", children: [
                    /* @__PURE__ */ jsx8(Search2, { className: "rf-absolute rf-left-2 rf-top-2.5 rf-h-4 rf-w-4 rf-text-muted-foreground" }),
                    /* @__PURE__ */ jsx8(
                      Input,
                      {
                        placeholder: activeTab === "tscircuit.com" ? "Search components..." : activeTab === "kicad" ? "Search KiCad footprints..." : "Search JLCPCB parts (e.g. C14663)...",
                        className: "rf-pl-8",
                        spellCheck: false,
                        autoComplete: "off",
                        value: searchQuery,
                        onChange: (e) => setSearchQuery(e.target.value),
                        onKeyDown: handleKeyDown
                      }
                    )
                  ] }),
                  /* @__PURE__ */ jsx8(
                    Button,
                    {
                      onClick: handleSearch,
                      disabled: isLoading || searchQuery.trim().length < 1,
                      className: "sm:rf-px-4 rf-px-3",
                      children: isLoading ? /* @__PURE__ */ jsx8(Loader22, { className: "rf-h-4 rf-w-4 rf-animate-spin" }) : /* @__PURE__ */ jsxs7(Fragment3, { children: [
                        /* @__PURE__ */ jsx8(Search2, { className: "rf-h-4 rf-w-4 sm:rf-hidden" }),
                        /* @__PURE__ */ jsx8("span", { className: "rf-hidden sm:rf-inline", children: "Search" })
                      ] })
                    }
                  )
                ] }),
                /* @__PURE__ */ jsx8("div", { className: "rf-mt-4 rf-flex-1 rf-min-h-[200px] !rf-max-h-[40vh] !rf-overflow-y-auto rf-border rf-rounded-md", children: searchResults.length > 0 ? /* @__PURE__ */ jsx8("div", { className: "rf-divide-y", children: searchResults.map((result) => /* @__PURE__ */ jsxs7(
                  "div",
                  {
                    className: `rf-p-3 rf-flex rf-flex-col sm:rf-grid sm:rf-grid-cols-[1fr_auto] rf-items-start sm:rf-items-center rf-cursor-pointer hover:rf-bg-zinc-100 rf-gap-2 ${selectedComponent?.id === result.id ? "rf-bg-zinc-100" : ""}`,
                    onClick: () => setSelectedComponent(result),
                    children: [
                      /* @__PURE__ */ jsxs7("div", { className: "rf-min-w-0 rf-overflow-hidden", children: [
                        /* @__PURE__ */ jsx8("div", { className: "rf-font-medium rf-text-sm rf-truncate", children: result.name }),
                        /* @__PURE__ */ jsxs7("div", { className: "rf-text-xs rf-text-zinc-500 rf-truncate", children: [
                          result.partNumber && /* @__PURE__ */ jsx8("span", { className: "rf-mr-2", children: result.partNumber }),
                          result.description
                        ] })
                      ] }),
                      /* @__PURE__ */ jsx8("div", { className: "rf-flex rf-gap-2 rf-flex-shrink-0 rf-w-full sm:rf-w-auto", children: result.source === "tscircuit.com" && /* @__PURE__ */ jsx8(
                        Button,
                        {
                          variant: "outline",
                          size: "sm",
                          className: "rf-text-xs rf-w-full sm:rf-w-auto",
                          onClick: (e) => {
                            e.stopPropagation();
                            showDetails(result);
                          },
                          children: "See Details"
                        }
                      ) })
                    ]
                  },
                  result.id
                )) }) : isLoading ? /* @__PURE__ */ jsxs7("div", { className: "rf-p-8 rf-text-center rf-text-zinc-500", children: [
                  /* @__PURE__ */ jsx8(Loader22, { className: "rf-h-8 rf-w-8 rf-animate-spin rf-mx-auto rf-mb-2" }),
                  /* @__PURE__ */ jsx8("p", { children: "Searching..." })
                ] }) : /* @__PURE__ */ jsx8("div", { className: "rf-p-8 rf-text-center rf-text-zinc-500", children: hasSearched ? "No results found" : "Enter a search term to find components" }) })
              ]
            }
          ),
          /* @__PURE__ */ jsxs7(DialogFooter, { className: "rf-flex rf-flex-col sm:rf-flex-row rf-gap-2", children: [
            /* @__PURE__ */ jsx8(
              Button,
              {
                variant: "outline",
                onClick: onClose,
                className: "rf-order-2 sm:rf-order-1",
                children: "Cancel"
              }
            ),
            /* @__PURE__ */ jsx8(
              Button,
              {
                onClick: () => {
                  if (selectedComponent) {
                    handleImport(selectedComponent);
                    onClose();
                  }
                },
                disabled: !selectedComponent,
                children: selectedComponent?.source === "kicad" ? "Copy Footprint" : "Import Component"
              }
            )
          ] })
        ]
      }
    ),
    /* @__PURE__ */ jsx8(Dialog, { open: detailsOpen, onOpenChange: setDetailsOpen, children: /* @__PURE__ */ jsxs7(
      DialogContent,
      {
        showOverlay: false,
        style: {
          width: "calc(100vw - 2rem)"
        },
        className: "rf-max-w-5xl !rf-overflow-y-auto rf-max-h-[90vh] rf-overflow-hidden rf-flex rf-flex-col rf-rounded-sm",
        children: [
          /* @__PURE__ */ jsx8(DialogHeader, { className: "rf-pb-4 rf-border-b", children: /* @__PURE__ */ jsx8("div", { className: "rf-flex rf-items-start rf-justify-between rf-gap-4", children: /* @__PURE__ */ jsx8("div", { className: "rf-flex-1 rf-min-w-0", children: /* @__PURE__ */ jsx8(DialogTitle, { className: "rf-text-xl rf-font-semibold rf-truncate", children: detailsComponent?.source === "kicad" ? detailsComponent?.name : /* @__PURE__ */ jsx8(
            "a",
            {
              href: `https://tscircuit.com/${detailsComponent?.owner}/${detailsComponent?.name}`,
              target: "_blank",
              rel: "noopener noreferrer",
              className: "rf-text-black hover:rf-underline",
              children: detailsComponent?.name?.split("/").pop() || detailsComponent?.name
            }
          ) }) }) }) }),
          /* @__PURE__ */ jsx8("div", { className: "rf-flex-1 rf-overflow-y-auto rf-py-4 rf-space-y-6", children: detailsComponent?.source === "tscircuit.com" ? /* @__PURE__ */ jsxs7(Fragment3, { children: [
            /* @__PURE__ */ jsx8("div", { children: /* @__PURE__ */ jsx8("div", { className: "rf-space-y-3", children: detailsComponent?.owner && /* @__PURE__ */ jsxs7("div", { children: [
              /* @__PURE__ */ jsx8("label", { className: "rf-text-xs rf-font-medium rf-text-gray-500 rf-uppercase rf-tracking-wide", children: "Created by" }),
              /* @__PURE__ */ jsx8("div", { className: "rf-mt-1 rf-text-sm rf-font-medium", children: /* @__PURE__ */ jsx8(
                "a",
                {
                  href: `https://tscircuit.com/${detailsComponent?.owner}`,
                  target: "_blank",
                  rel: "noopener noreferrer",
                  className: "rf-text-black hover:rf-underline",
                  children: detailsComponent?.owner
                }
              ) })
            ] }) }) }),
            /* @__PURE__ */ jsxs7("div", { children: [
              /* @__PURE__ */ jsx8("h3", { className: "rf-text-lg rf-font-semibold rf-mb-4", children: "Preview" }),
              /* @__PURE__ */ jsxs7(
                Tabs,
                {
                  value: previewActiveTab,
                  onValueChange: (value) => setPreviewActiveTab(value),
                  children: [
                    /* @__PURE__ */ jsxs7(TabsList, { className: "rf-inline-flex rf-h-9 rf-items-center rf-justify-center rf-rounded-lg rf-bg-zinc-100 rf-p-1 rf-text-zinc-500 dark:rf-bg-zinc-800 dark:rf-text-zinc-400", children: [
                      /* @__PURE__ */ jsx8(
                        TabsTrigger,
                        {
                          value: "pcb",
                          className: "rf-inline-flex rf-items-center rf-justify-center rf-whitespace-nowrap rf-rounded-md rf-px-3 rf-py-1 rf-text-sm rf-font-medium rf-ring-offset-white rf-transition-all focus-visible:rf-outline-none focus-visible:rf-ring-2 focus-visible:rf-ring-zinc-950 focus-visible:rf-ring-offset-2 disabled:rf-pointer-events-none disabled:rf-opacity-50 data-[state=active]:rf-bg-white data-[state=active]:rf-text-zinc-950 data-[state=active]:rf-shadow dark:rf-ring-offset-zinc-950 dark:focus-visible:rf-ring-zinc-300 dark:data-[state=active]:rf-bg-zinc-950 dark:data-[state=active]:rf-text-zinc-50",
                          children: "PCB"
                        }
                      ),
                      /* @__PURE__ */ jsx8(
                        TabsTrigger,
                        {
                          value: "schematic",
                          className: "rf-inline-flex rf-items-center rf-justify-center rf-whitespace-nowrap rf-rounded-md rf-px-3 rf-py-1 rf-text-sm rf-font-medium rf-ring-offset-white rf-transition-all focus-visible:rf-outline-none focus-visible:rf-ring-2 focus-visible:rf-ring-zinc-950 focus-visible:rf-ring-offset-2 disabled:rf-pointer-events-none disabled:rf-opacity-50 data-[state=active]:rf-bg-white data-[state=active]:rf-text-zinc-950 data-[state=active]:rf-shadow dark:rf-ring-offset-zinc-950 dark:focus-visible:rf-ring-zinc-300 dark:data-[state=active]:rf-bg-zinc-950 dark:data-[state=active]:rf-text-zinc-50",
                          children: "Schematic"
                        }
                      )
                    ] }),
                    /* @__PURE__ */ jsxs7("div", { className: "rf-mt-4", children: [
                      /* @__PURE__ */ jsx8(
                        TabsContent,
                        {
                          value: "pcb",
                          className: "rf-border rf-rounded-lg rf-overflow-hidden rf-bg-gray-50",
                          children: detailsComponent?.owner && detailsComponent?.name ? /* @__PURE__ */ jsx8("div", { className: "rf-w-full rf-h-fit rf-min-h-[300px] rf-bg-white rf-flex rf-items-center rf-justify-center rf-p-4", children: /* @__PURE__ */ jsx8(
                            "img",
                            {
                              src: `https://registry-api.tscircuit.com/packages/images/${detailsComponent.owner}/${detailsComponent.name}/pcb.png`,
                              alt: `${detailsComponent.name} PCB preview`,
                              className: "rf-max-w-full rf-max-h-full rf-object-contain rf-rounded",
                              onError: (e) => {
                                const target = e.target;
                                target.style.display = "none";
                                const parent = target.parentElement;
                                if (parent) {
                                  parent.innerHTML = '<div class="rf-text-center rf-text-gray-500"><div class="rf-text-sm rf-font-medium">PCB preview not available</div><div class="rf-text-xs rf-mt-1">Preview cannot be generated</div></div>';
                                }
                              }
                            }
                          ) }) : /* @__PURE__ */ jsx8("div", { className: "rf-h-[400px] rf-flex rf-items-center rf-justify-center rf-text-gray-500", children: /* @__PURE__ */ jsxs7("div", { className: "rf-text-center", children: [
                            /* @__PURE__ */ jsx8("div", { className: "rf-text-sm rf-font-medium", children: "No PCB preview available" }),
                            /* @__PURE__ */ jsx8("div", { className: "rf-text-xs rf-mt-1", children: "Preview cannot be generated" })
                          ] }) })
                        }
                      ),
                      /* @__PURE__ */ jsx8(
                        TabsContent,
                        {
                          value: "schematic",
                          className: "rf-border rf-rounded-lg rf-overflow-hidden rf-bg-gray-50",
                          children: detailsComponent?.owner && detailsComponent?.name ? /* @__PURE__ */ jsx8("div", { className: "rf-w-full rf-h-fit rf-min-h-[300px] rf-bg-white rf-flex rf-items-center rf-justify-center rf-p-4", children: /* @__PURE__ */ jsx8(
                            "img",
                            {
                              src: `https://registry-api.tscircuit.com/packages/images/${detailsComponent.owner}/${detailsComponent.name}/schematic.png`,
                              alt: `${detailsComponent.name} schematic preview`,
                              className: "rf-max-w-full rf-max-h-full rf-object-contain rf-rounded",
                              onError: (e) => {
                                const target = e.target;
                                target.style.display = "none";
                                const parent = target.parentElement;
                                if (parent) {
                                  parent.innerHTML = '<div class="rf-text-center rf-text-gray-500"><div class="rf-text-sm rf-font-medium">Schematic preview not available</div><div class="rf-text-xs rf-mt-1">Preview cannot be generated</div></div>';
                                }
                              }
                            }
                          ) }) : /* @__PURE__ */ jsx8("div", { className: "rf-h-[400px] rf-flex rf-items-center rf-justify-center rf-text-gray-500", children: /* @__PURE__ */ jsxs7("div", { className: "rf-text-center", children: [
                            /* @__PURE__ */ jsx8("div", { className: "rf-text-sm rf-font-medium", children: "No schematic preview available" }),
                            /* @__PURE__ */ jsx8("div", { className: "rf-text-xs rf-mt-1", children: "Preview cannot be generated" })
                          ] }) })
                        }
                      )
                    ] })
                  ]
                }
              )
            ] }),
            packageDetails?.ai_description && /* @__PURE__ */ jsxs7("div", { children: [
              /* @__PURE__ */ jsx8("h3", { className: "rf-text-lg rf-font-semibold rf-mb-3", children: "AI Description" }),
              /* @__PURE__ */ jsx8("div", { className: "rf-bg-gray-50 rf-border rf-border-gray-200 rf-rounded-lg rf-p-4", children: /* @__PURE__ */ jsx8("p", { className: "rf-text-sm rf-text-gray-700 rf-leading-relaxed", children: packageDetails.ai_description }) })
            ] }),
            packageDetails?.ai_usage_instructions && /* @__PURE__ */ jsxs7("div", { children: [
              /* @__PURE__ */ jsx8("h3", { className: "rf-text-lg rf-font-semibold rf-mb-3", children: "Usage Instructions" }),
              /* @__PURE__ */ jsx8("div", { className: "rf-bg-gray-50 rf-border rf-border-gray-200 rf-rounded-lg rf-p-4", children: /* @__PURE__ */ jsx8("p", { className: "rf-text-sm rf-text-gray-700 rf-leading-relaxed rf-whitespace-pre-wrap", children: packageDetails.ai_usage_instructions }) })
            ] }),
            packageDetailsLoading && /* @__PURE__ */ jsxs7("div", { className: "rf-flex rf-justify-center rf-text-center rf-items-center rf-gap-2 rf-text-gray-500", children: [
              /* @__PURE__ */ jsx8(Loader22, { className: "rf-h-4 rf-w-4 rf-animate-spin" }),
              /* @__PURE__ */ jsx8("span", { className: "rf-text-sm", children: "Loading package details..." })
            ] })
          ] }) : null }),
          /* @__PURE__ */ jsxs7(DialogFooter, { className: "rf-pt-4 rf-border-t rf-flex rf-flex-col sm:rf-flex-row rf-justify-between rf-items-stretch sm:rf-items-center rf-gap-2", children: [
            /* @__PURE__ */ jsx8("div", { className: "rf-flex-1 rf-order-3 sm:rf-order-1", children: detailsComponent?.source === "tscircuit.com" && /* @__PURE__ */ jsxs7(
              Button,
              {
                variant: "outline",
                size: "sm",
                className: "rf-gap-2 rf-w-full sm:rf-w-auto",
                onClick: () => {
                  const url = `https://tscircuit.com/${detailsComponent?.owner}/${detailsComponent?.name.split("/").pop()}`;
                  window.open(url, "_blank");
                },
                children: [
                  /* @__PURE__ */ jsx8(ExternalLink, { className: "rf-h-4 rf-w-4" }),
                  "View on tscircuit.com"
                ]
              }
            ) }),
            /* @__PURE__ */ jsxs7("div", { className: "rf-flex rf-flex-col sm:rf-flex-row rf-gap-2 sm:rf-gap-3 rf-order-1 sm:rf-order-2", children: [
              /* @__PURE__ */ jsx8(
                Button,
                {
                  variant: "outline",
                  onClick: () => setDetailsOpen(false),
                  className: "rf-order-2 sm:rf-order-1",
                  children: "Close"
                }
              ),
              /* @__PURE__ */ jsx8(
                Button,
                {
                  onClick: () => {
                    setDetailsOpen(false);
                    if (detailsComponent) {
                      handleImport(detailsComponent);
                      onClose();
                    }
                  },
                  className: "rf-bg-blue-600 hover:rf-bg-blue-700 rf-order-1 sm:rf-order-2",
                  children: detailsComponent?.source === "kicad" ? "Copy Footprint" : "Import Component"
                }
              )
            ] })
          ] })
        ]
      }
    ) })
  ] });
};

// lib/components/RunFrameStaticBuildViewer/RunFrameStaticBuildViewer.tsx
import { useCallback as useCallback4, useEffect as useEffect7, useState as useState7 } from "react";

// lib/components/RunFrameStaticBuildViewer/CircuitJsonFileSelectorCombobox.tsx
import { jsx as jsx9 } from "react/jsx-runtime";
var circuitJsonConfig = {
  fileFilter: () => true,
  placeholder: "Select circuit",
  searchPlaceholder: "Search for circuit file",
  emptyMessage: "No circuit files found in this directory."
};
var CircuitJsonFileSelectorCombobox = ({
  files,
  onFileChange,
  currentFile
}) => {
  return /* @__PURE__ */ jsx9(
    EnhancedFileSelectorCombobox,
    {
      files,
      onFileChange,
      currentFile,
      config: circuitJsonConfig
    }
  );
};

// lib/components/RunFrameStaticBuildViewer/RunFrameStaticBuildViewer.tsx
import { ErrorBoundary } from "react-error-boundary";
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
var RunFrameStaticBuildViewer = (props) => {
  useStyles();
  const [currentCircuitJsonPath, setCurrentCircuitJsonPath] = useState7(
    () => {
      return props.initialCircuitPath ?? "";
    }
  );
  const [circuitJson, setCircuitJson] = useState7(null);
  const [isLoadingCurrentFile, setIsLoadingCurrentFile] = useState7(false);
  const [fileCache, setFileCache] = useState7({});
  const [loadingFiles, setLoadingFiles] = useState7(/* @__PURE__ */ new Set());
  const [failedFiles, setFailedFiles] = useState7(/* @__PURE__ */ new Set());
  const fileReferences = props.files;
  const availableFiles = fileReferences.map((f) => f.filePath);
  const defaultFetchFile = useCallback4(
    async (fileRef) => {
      if (!fileRef.fileStaticAssetUrl) {
        throw new Error(
          `No fileStaticAssetUrl provided for ${fileRef.filePath}`
        );
      }
      const response = await fetch(fileRef.fileStaticAssetUrl);
      if (!response.ok) {
        throw new Error(
          `Failed to fetch ${fileRef.filePath}: ${response.statusText}`
        );
      }
      return await response.json();
    },
    []
  );
  const loadCircuitJsonFile = useCallback4(
    async (filePath) => {
      if (fileCache[filePath]) {
        setCircuitJson(fileCache[filePath]);
        props.onCircuitJsonPathChange?.(filePath);
        return;
      }
      if (failedFiles.has(filePath)) {
        console.warn(`Skipping failed file: ${filePath}`);
        setCircuitJson(null);
        return;
      }
      if (loadingFiles.has(filePath)) {
        return;
      }
      setLoadingFiles((prev) => new Set(prev).add(filePath));
      setIsLoadingCurrentFile(true);
      setCircuitJson(null);
      try {
        const fileRef = fileReferences.find((f) => f.filePath === filePath);
        if (!fileRef) {
          throw new Error(`File reference not found for ${filePath}`);
        }
        const fetchFn = props.onFetchFile || defaultFetchFile;
        const circuitJsonData = await fetchFn(fileRef);
        setFileCache((prev) => ({ ...prev, [filePath]: circuitJsonData }));
        setCircuitJson(circuitJsonData);
        props.onCircuitJsonPathChange?.(filePath);
        setFailedFiles((prev) => {
          const newSet = new Set(prev);
          newSet.delete(filePath);
          return newSet;
        });
      } catch (error) {
        console.error(`Failed to load circuit JSON file ${filePath}:`, error);
        setFailedFiles((prev) => new Set(prev).add(filePath));
        setCircuitJson(null);
      } finally {
        setLoadingFiles((prev) => {
          const newSet = new Set(prev);
          newSet.delete(filePath);
          return newSet;
        });
        setIsLoadingCurrentFile(false);
      }
    },
    [
      fileReferences,
      fileCache,
      loadingFiles,
      failedFiles,
      props.onFetchFile,
      props.onCircuitJsonPathChange,
      defaultFetchFile
    ]
  );
  useEffect7(() => {
    if (availableFiles.length === 0) return;
    let selectedPath = currentCircuitJsonPath;
    if (!selectedPath || !availableFiles.includes(selectedPath)) {
      selectedPath = guessEntrypoint(availableFiles) ?? availableFiles[0];
      setCurrentCircuitJsonPath(selectedPath);
    }
    if (selectedPath && availableFiles.includes(selectedPath)) {
      loadCircuitJsonFile(selectedPath);
    }
  }, [currentCircuitJsonPath]);
  const handleFileChange = useCallback4((newPath) => {
    setCurrentCircuitJsonPath(newPath);
  }, []);
  const retryFailedFile = useCallback4(
    (filePath) => {
      setFailedFiles((prev) => {
        const newSet = new Set(prev);
        newSet.delete(filePath);
        return newSet;
      });
      loadCircuitJsonFile(filePath);
    },
    [loadCircuitJsonFile]
  );
  if (availableFiles.length === 0) {
    return /* @__PURE__ */ jsx10("div", { className: "rf-flex rf-flex-col rf-w-full rf-h-full rf-items-center rf-justify-center", children: /* @__PURE__ */ jsxs8("div", { className: "rf-text-center rf-p-8", children: [
      /* @__PURE__ */ jsx10("h3", { className: "rf-text-lg rf-font-semibold rf-text-gray-800 rf-mb-2", children: "No Circuit JSON Files Found" }),
      /* @__PURE__ */ jsx10("p", { className: "rf-text-sm rf-text-gray-600", children: "Please provide circuit JSON files to view." })
    ] }) });
  }
  const currentFileFailed = failedFiles.has(currentCircuitJsonPath);
  return /* @__PURE__ */ jsx10(
    ErrorBoundary,
    {
      fallbackRender: ({ error }) => /* @__PURE__ */ jsx10("div", { className: "rf-mt-4 rf-mx-4 rf-bg-red-50 rf-rounded-md rf-border rf-border-red-200", children: /* @__PURE__ */ jsxs8("div", { className: "rf-p-4", children: [
        /* @__PURE__ */ jsx10("h3", { className: "rf-text-lg rf-font-semibold rf-text-red-800 rf-mb-3", children: "Error loading Circuit JSON Preview" }),
        /* @__PURE__ */ jsx10("p", { className: "rf-text-xs rf-font-mono rf-whitespace-pre-wrap rf-text-red-600 rf-mt-2", children: error.message })
      ] }) }),
      children: currentFileFailed ? /* @__PURE__ */ jsxs8("div", { className: "rf-w-full rf-h-full rf-flex rf-flex-col", children: [
        /* @__PURE__ */ jsxs8("div", { className: "rf-flex rf-items-center rf-justify-between rf-w-full rf-p-4 rf-border-b rf-border-gray-200", children: [
          (props.showFileMenu ?? true) && /* @__PURE__ */ jsx10(
            FileMenuLeftHeader,
            {
              isWebEmbedded: true,
              circuitJson: null,
              projectName: props.projectName
            }
          ),
          availableFiles.length > 1 && /* @__PURE__ */ jsx10("div", { className: "rf-absolute rf-left-1/2 rf-transform rf--translate-x-1/2 rf-flex rf-items-center rf-gap-2", children: /* @__PURE__ */ jsx10(
            CircuitJsonFileSelectorCombobox,
            {
              currentFile: currentCircuitJsonPath,
              files: availableFiles,
              onFileChange: handleFileChange
            }
          ) })
        ] }),
        /* @__PURE__ */ jsx10("div", { className: "rf-flex-1 rf-flex rf-items-center rf-justify-center", children: /* @__PURE__ */ jsxs8("div", { className: "rf-text-center rf-p-8", children: [
          /* @__PURE__ */ jsx10("h3", { className: "rf-text-lg rf-font-semibold rf-text-red-600 rf-mb-2", children: "Failed to Load Circuit File" }),
          /* @__PURE__ */ jsxs8("p", { className: "rf-text-sm rf-text-gray-600 rf-mb-4", children: [
            "Could not load: ",
            currentCircuitJsonPath
          ] }),
          /* @__PURE__ */ jsxs8("div", { className: "rf-flex rf-flex-col rf-items-center rf-gap-2", children: [
            /* @__PURE__ */ jsx10(
              "button",
              {
                onClick: () => retryFailedFile(currentCircuitJsonPath),
                className: "rf-px-4 rf-py-2 rf-bg-blue-500 rf-text-white rf-rounded rf-hover:bg-blue-600",
                children: "Retry"
              }
            ),
            availableFiles.length > 1 && /* @__PURE__ */ jsx10("p", { className: "rf-text-xs rf-text-gray-500", children: "Or select a different file from the dropdown above" })
          ] })
        ] }) })
      ] }) : /* @__PURE__ */ jsx10(
        CircuitJsonPreview,
        {
          circuitJson,
          defaultToFullScreen: props.defaultToFullScreen,
          showToggleFullScreen: props.showToggleFullScreen,
          showFileMenu: false,
          isWebEmbedded: false,
          projectName: props.projectName,
          leftHeaderContent: /* @__PURE__ */ jsxs8("div", { className: "rf-flex rf-items-center rf-justify-between rf-w-full", children: [
            (props.showFileMenu ?? true) && /* @__PURE__ */ jsx10(
              FileMenuLeftHeader,
              {
                isWebEmbedded: true,
                circuitJson,
                projectName: props.projectName
              }
            ),
            availableFiles.length > 1 && /* @__PURE__ */ jsx10(
              "div",
              {
                className: `rf-absolute rf-left-1/2 rf-transform rf--translate-x-1/2 rf-flex rf-items-center rf-gap-2 ${isLoadingCurrentFile ? "rf-opacity-50" : ""}`,
                children: /* @__PURE__ */ jsx10(
                  CircuitJsonFileSelectorCombobox,
                  {
                    currentFile: currentCircuitJsonPath,
                    files: availableFiles,
                    onFileChange: handleFileChange
                  }
                )
              }
            )
          ] })
        }
      )
    }
  );
};
export {
  BomTable,
  CadViewer,
  CircuitJsonFileSelectorCombobox,
  CircuitJsonPreview,
  ImportComponentDialog,
  ImportComponentDialog2,
  ImportComponentDialogForCli,
  PCBViewer as PcbViewer,
  PcbViewerWithContainerHeight,
  RunFrame,
  RunFrameForCli,
  RunFrameStaticBuildViewer,
  RunFrameWithApi,
  SchematicViewer,
  guessEntrypoint,
  guessManualEditsFilePath,
  linkify,
  mapJLCComponentToSearchResult,
  mapTscircuitSnippetToSearchResult,
  searchJLCComponents,
  searchTscircuitComponents,
  useOrderDialog,
  useOrderDialogCli
};
