import {
  API_BASE,
  BomTable,
  Button,
  CadViewer,
  CircuitJsonPreview,
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuPortal,
  DropdownMenuSub,
  DropdownMenuSubContent,
  DropdownMenuSubTrigger,
  DropdownMenuTrigger,
  Input,
  PCBViewer,
  PcbViewerWithContainerHeight,
  SchematicViewer,
  Tabs,
  TabsContent,
  TabsList,
  TabsTrigger,
  buttonVariants,
  cn,
  debug_default,
  getRegistryKy,
  hasRegistryToken,
  linkify,
  registryKy,
  toast,
  useLocalStorageState,
  useOrderDialog,
  useOrderDialogCli,
  useRunFrameStore,
  useRunnerStore
} from "./chunk-5DFPDYHY.js";

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

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

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

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

// lib/components/RunFrame/RunFrame.tsx
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
var numRenderPhases = 26;
var debug = Debug("run-frame:RunFrame");
var fetchLatestEvalVersion = async () => {
  try {
    const response = await fetch(
      "https://data.jsdelivr.com/v1/package/npm/@tscircuit/eval"
    );
    if (response.ok) {
      const data = await response.json();
      return data.tags?.latest;
    }
  } catch (err) {
    console.error("Failed to fetch latest eval version", err);
  }
  return void 0;
};
var resolveEvalVersion = async (evalVersionProp, forceLatest) => {
  if (evalVersionProp) return evalVersionProp;
  if (forceLatest || !window.TSCIRCUIT_LATEST_EVAL_VERSION) {
    const latest = await fetchLatestEvalVersion();
    if (latest) {
      window.TSCIRCUIT_LATEST_EVAL_VERSION = latest;
      return latest;
    }
  }
  if (window.TSCIRCUIT_LATEST_EVAL_VERSION) {
    return window.TSCIRCUIT_LATEST_EVAL_VERSION;
  }
  return "latest";
};
var RunFrame = (props) => {
  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 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,
            verbose: true
          });
          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(() => {
    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 = props.showRunButton && 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 };
      let cancelled = false;
      cancelExecutionRef.current = () => {
        cancelled = true;
      };
      const evalVersion = await resolveEvalVersion(
        props.evalVersion,
        !globalThis.runFrameWorker && props.forceLatestEvalVersion
      );
      const worker = globalThis.runFrameWorker ?? await createCircuitWebWorker({
        evalVersion,
        webWorkerBlobUrl: props.evalWebWorkerBlobUrl,
        verbose: true
      });
      globalThis.runFrameWorker = worker;
      setLastRunEvalVersion(evalVersion);
      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);
      });
      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: ", "");
        props.onError?.(e);
        setError({ error: message, stack: e.stack });
        setRenderLog(null);
        console.error(e);
        return { success: false };
      });
      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({});
      cancelExecutionRef.current = null;
    };
    runMutex.runWithMutex(runWorker);
  }, [
    props.fsMap,
    props.entrypoint,
    runCountTrigger,
    props.evalVersion,
    props.mainComponentPath
  ]);
  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}`);
      }
    });
  };
  return /* @__PURE__ */ jsx(
    CircuitJsonPreview,
    {
      code: fsMap.get(props.entrypoint ?? props.mainComponentPath),
      fsMap,
      defaultActiveTab: props.defaultActiveTab ?? props.defaultTab,
      defaultTab: props.defaultTab,
      availableTabs: props.availableTabs,
      showToggleFullScreen: props.showToggleFullScreen,
      autoroutingGraphics,
      autoroutingLog,
      onReportAutoroutingLog: props.onReportAutoroutingLog || handleReportAutoroutingLog,
      leftHeaderContent: /* @__PURE__ */ jsxs(Fragment, { children: [
        props.showRunButton && /* @__PURE__ */ jsxs("div", { className: "rf-relative rf-inline-flex", children: [
          /* @__PURE__ */ jsxs(
            "button",
            {
              type: "button",
              onClick: () => {
                incRunCountTrigger(1);
              },
              className: "rf-flex rf-items-center rf-gap-2 rf-px-4 rf-py-2 rf-bg-blue-600 hover:rf-bg-blue-700 rf-text-white rf-rounded-md disabled:rf-opacity-50 transition-colors duration-200",
              disabled: isRunning || !dependenciesLoaded,
              children: [
                "Run",
                " ",
                isRunning || !dependenciesLoaded ? /* @__PURE__ */ jsx(Loader2, { className: "rf-w-3 rf-h-3 rf-animate-spin" }) : /* @__PURE__ */ jsx(Play, { className: "rf-w-3 rf-h-3" })
              ]
            }
          ),
          isRunning && /* @__PURE__ */ jsx("div", { className: "rf-flex rf-items-center rf-ml-1", children: /* @__PURE__ */ jsx(
            Button,
            {
              onClick: (e) => {
                e.stopPropagation();
                setIsRunning(false);
                setRenderLog(null);
                setError(null);
                if (cancelExecutionRef.current) {
                  cancelExecutionRef.current();
                  cancelExecutionRef.current = null;
                }
                runMutex.cancel();
                setActiveAsyncEffects({});
                if (globalThis.runFrameWorker) {
                  globalThis.runFrameWorker.kill();
                  globalThis.runFrameWorker = null;
                }
              },
              variant: "ghost",
              size: "icon",
              className: "rf-text-red-300 hover:rf-text-red-400 hover:!rf-bg-transparent [&>svg]:rf-text-red-300 [&>svg]:hover:rf-text-red-400 rf-flex rf-items-center rf-justify-center",
              children: /* @__PURE__ */ jsx(
                Square,
                {
                  className: "!rf-h-2.5 !rf-w-2.5",
                  fill: "currentColor",
                  stroke: "currentColor"
                }
              )
            }
          ) })
        ] }),
        props.leftHeaderContent
      ] }),
      onActiveTabChange: setActiveTab,
      circuitJson,
      renderLog,
      activeEffectName,
      isRunningCode: isRunning,
      errorMessage: error?.error,
      errorStack: error?.stack,
      onEditEvent: handleEditEvent,
      editEvents: props.editEvents,
      defaultToFullScreen: props.defaultToFullScreen
    }
  );
};

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

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

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

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

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

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

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

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

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

// lib/components/RunFrameForCli/LeftHeader.tsx
import { useEffect as useEffect10, useMemo as useMemo4, useState as useState10 } from "react";

// lib/components/RunFrameForCli/SelectSnippetDialog.tsx
import { useState as useState5 } from "react";
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
var SelectSnippetDialog = ({
  snippetNames,
  onSelect,
  onCancel,
  isOpen
}) => {
  const [selectedName, setSelectedName] = useState5("");
  const [searchInput, setSearchInput] = useState5("");
  if (!isOpen) return null;
  const filteredSnippets = snippetNames.filter(
    (name) => name.toLowerCase().includes(searchInput.toLowerCase())
  );
  const showCreateNew = searchInput && !snippetNames.includes(searchInput);
  const handleKeyDown = (e) => {
    if (e.key === "Enter") {
      if (filteredSnippets.length === 1) {
        setSelectedName(filteredSnippets[0]);
      } else if (showCreateNew) {
        setSelectedName(searchInput);
      }
    }
  };
  return /* @__PURE__ */ jsx6("div", { className: "rf-fixed rf-inset-0 rf-bg-black rf-bg-opacity-50 rf-flex rf-items-center rf-justify-center rf-z-[100]", children: /* @__PURE__ */ jsxs5("div", { className: "rf-bg-white rf-rounded-lg rf-p-6 rf-w-96", children: [
    /* @__PURE__ */ jsx6("h2", { className: "rf-text-lg rf-font-semibold rf-mb-4", children: "Select Snippet" }),
    /* @__PURE__ */ jsx6(
      "input",
      {
        type: "text",
        className: "rf-w-full rf-px-4 rf-py-2 rf-border rf-rounded rf-mb-4",
        placeholder: "Search snippets or new snippet name...",
        value: searchInput,
        onChange: (e) => setSearchInput(e.target.value),
        onKeyDown: handleKeyDown
      }
    ),
    /* @__PURE__ */ jsxs5("div", { className: "rf-h-60 rf-overflow-y-auto", children: [
      filteredSnippets.map((name) => /* @__PURE__ */ jsx6(
        "button",
        {
          type: "button",
          className: `w-full text-left px-4 py-2 rounded hover:bg-gray-100 ${selectedName === name ? "bg-blue-50" : ""}`,
          onClick: () => setSelectedName(name),
          children: name
        },
        name
      )),
      showCreateNew && /* @__PURE__ */ jsxs5(
        "button",
        {
          type: "button",
          className: `w-full text-left px-4 py-2 rounded hover:bg-gray-100 text-blue-500 ${selectedName === searchInput ? "bg-blue-50" : ""}`,
          onClick: () => setSelectedName(searchInput),
          children: [
            'Create new "',
            searchInput,
            '"'
          ]
        }
      )
    ] }),
    /* @__PURE__ */ jsxs5("div", { className: "rf-mt-4 rf-flex rf-justify-end rf-gap-2", children: [
      /* @__PURE__ */ jsx6(
        "button",
        {
          type: "button",
          className: "rf-px-4 rf-py-2 rf-text-gray-600 rf-hover:text-gray-800",
          onClick: onCancel,
          children: "Cancel"
        }
      ),
      /* @__PURE__ */ jsx6(
        "button",
        {
          type: "button",
          className: "rf-px-4 rf-py-2 rf-bg-blue-500 rf-text-white rf-rounded rf-hover:bg-blue-600 rf-disabled:opacity-50",
          onClick: () => selectedName && onSelect(selectedName),
          disabled: !selectedName,
          children: selectedName === searchInput ? `Create "${selectedName}"` : `Save to ${selectedName}`
        }
      )
    ] })
  ] }) });
};

// lib/components/RunFrameForCli/useEventHandler.ts
import { useEffect as useEffect6, useRef as useRef3 } from "react";
var useEventHandler = (callback) => {
  const lastProcessedEventId = useRef3(null);
  const recentEvents = useRunFrameStore((state) => state.recentEvents);
  useEffect6(() => {
    if (recentEvents.length === 0) return;
    const latestEvent = recentEvents[0];
    if (latestEvent.event_id !== lastProcessedEventId.current) {
      callback(latestEvent);
      lastProcessedEventId.current = latestEvent.event_id;
    }
  }, [recentEvents, callback]);
};

// lib/components/ui/alert-dialog.tsx
import * as React3 from "react";
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
var AlertDialog = AlertDialogPrimitive.Root;
var AlertDialogPortal = AlertDialogPrimitive.Portal;
var AlertDialogOverlay = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx7(
  AlertDialogPrimitive.Overlay,
  {
    className: cn(
      "rf-fixed rf-inset-0 rf-z-50 rf-bg-black/80 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",
      className
    ),
    ...props,
    ref
  }
));
AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
var AlertDialogContent = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxs6(AlertDialogPortal, { children: [
  /* @__PURE__ */ jsx7(AlertDialogOverlay, {}),
  /* @__PURE__ */ jsx7(
    AlertDialogPrimitive.Content,
    {
      ref,
      className: cn(
        "rf-fixed rf-left-[50%] rf-top-[50%] rf-z-50 rf-grid rf-w-full rf-max-w-lg rf-translate-x-[-50%] rf-translate-y-[-50%] rf-gap-4 rf-border rf-border-zinc-200 rf-bg-white rf-p-6 rf-shadow-lg rf-duration-200 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-[state=closed]:rf-slide-out-to-left-1/2 data-[state=closed]:rf-slide-out-to-top-[48%] data-[state=open]:rf-slide-in-from-left-1/2 data-[state=open]:rf-slide-in-from-top-[48%] sm:rf-rounded-lg dark:rf-border-zinc-800 dark:rf-bg-zinc-950",
        className
      ),
      ...props
    }
  )
] }));
AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
var AlertDialogHeader = ({
  className,
  ...props
}) => /* @__PURE__ */ jsx7(
  "div",
  {
    className: cn(
      "rf-flex rf-flex-col rf-space-y-2 rf-text-center sm:rf-text-left",
      className
    ),
    ...props
  }
);
AlertDialogHeader.displayName = "AlertDialogHeader";
var AlertDialogFooter = ({
  className,
  ...props
}) => /* @__PURE__ */ jsx7(
  "div",
  {
    className: cn(
      "rf-flex rf-flex-col-reverse sm:rf-flex-row sm:rf-justify-end sm:rf-space-x-2",
      className
    ),
    ...props
  }
);
AlertDialogFooter.displayName = "AlertDialogFooter";
var AlertDialogTitle = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx7(
  AlertDialogPrimitive.Title,
  {
    ref,
    className: cn("rf-text-lg rf-font-semibold", className),
    ...props
  }
));
AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
var AlertDialogDescription = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx7(
  AlertDialogPrimitive.Description,
  {
    ref,
    className: cn(
      "rf-text-sm rf-text-zinc-500 dark:rf-text-zinc-400",
      className
    ),
    ...props
  }
));
AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;
var AlertDialogAction = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx7(
  AlertDialogPrimitive.Action,
  {
    ref,
    className: cn(buttonVariants(), className),
    ...props
  }
));
AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;
var AlertDialogCancel = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx7(
  AlertDialogPrimitive.Cancel,
  {
    ref,
    className: cn(
      buttonVariants({ variant: "outline" }),
      "rf-mt-2 sm:rf-mt-0",
      className
    ),
    ...props
  }
));
AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;

// lib/components/ui/checkbox.tsx
import * as React4 from "react";
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
import { Check as Check2 } from "lucide-react";
import { jsx as jsx8 } from "react/jsx-runtime";
var Checkbox = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx8(
  CheckboxPrimitive.Root,
  {
    ref,
    className: cn(
      "rf-peer rf-h-4 rf-w-4 rf-shrink-0 rf-rounded-sm rf-border rf-border-zinc-200 rf-border-zinc-900 rf-shadow focus-visible:rf-outline-none focus-visible:rf-ring-1 focus-visible:rf-ring-zinc-950 disabled:rf-cursor-not-allowed disabled:rf-opacity-50 data-[state=checked]:rf-bg-zinc-900 data-[state=checked]:rf-text-zinc-50 dark:rf-border-zinc-800 dark:rf-border-zinc-50 dark:focus-visible:rf-ring-zinc-300 dark:data-[state=checked]:rf-bg-zinc-50 dark:data-[state=checked]:rf-text-zinc-900",
      className
    ),
    ...props,
    children: /* @__PURE__ */ jsx8(
      CheckboxPrimitive.Indicator,
      {
        className: cn(
          "rf-flex rf-items-center rf-justify-center rf-text-current"
        ),
        children: /* @__PURE__ */ jsx8(Check2, { className: "rf-h-4 rf-w-4" })
      }
    )
  }
));
Checkbox.displayName = CheckboxPrimitive.Root.displayName;

// lib/components/ImportComponentDialog/ImportComponentDialog.tsx
import "react";
import { useState as useState6, useEffect as useEffect7 } 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/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/components/ImportComponentDialog/ImportComponentDialog.tsx
import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
var ImportComponentDialog = ({
  isOpen,
  onClose,
  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 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 {
        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();
    }
  };
  useEffect7(() => {
    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__ */ jsx9(DialogTitle, { className: "rf-text-lg sm:rf-text-xl", children: "Import Component" }),
            /* @__PURE__ */ jsx9(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-2 rf-h-auto", children: [
                  /* @__PURE__ */ jsx9(
                    TabsTrigger,
                    {
                      value: "tscircuit.com",
                      className: "rf-text-xs sm:rf-text-sm",
                      children: "tscircuit.com"
                    }
                  ),
                  /* @__PURE__ */ jsx9(TabsTrigger, { value: "jlcpcb", className: "rf-text-xs sm:rf-text-sm", children: "JLCPCB Parts" })
                ] }),
                /* @__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__ */ jsx9(Search2, { className: "rf-absolute rf-left-2 rf-top-2.5 rf-h-4 rf-w-4 rf-text-muted-foreground" }),
                    /* @__PURE__ */ jsx9(
                      Input,
                      {
                        placeholder: activeTab === "tscircuit.com" ? "Search components..." : "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__ */ jsx9(
                    Button,
                    {
                      onClick: handleSearch,
                      disabled: isLoading || searchQuery.trim().length < 1,
                      className: "sm:rf-px-4 rf-px-3",
                      children: isLoading ? /* @__PURE__ */ jsx9(Loader22, { className: "rf-h-4 rf-w-4 rf-animate-spin" }) : /* @__PURE__ */ jsxs7(Fragment2, { children: [
                        /* @__PURE__ */ jsx9(Search2, { className: "rf-h-4 rf-w-4 sm:rf-hidden" }),
                        /* @__PURE__ */ jsx9("span", { className: "rf-hidden sm:rf-inline", children: "Search" })
                      ] })
                    }
                  )
                ] }),
                /* @__PURE__ */ jsx9("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__ */ jsx9("div", { className: "rf-divide-y", children: searchResults.map((result) => /* @__PURE__ */ jsxs7(
                  "div",
                  {
                    className: `rf-p-3 rf-flex rf-flex-col sm:rf-flex-row rf-items-start sm:rf-items-center rf-justify-between 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-flex-1 rf-min-w-0", children: [
                        /* @__PURE__ */ jsx9("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-break-words", children: [
                          result.partNumber && /* @__PURE__ */ jsx9("span", { className: "rf-mr-2", children: result.partNumber }),
                          result.description
                        ] })
                      ] }),
                      /* @__PURE__ */ jsx9("div", { className: "rf-flex rf-gap-2 rf-flex-shrink-0 rf-w-full sm:rf-w-auto", children: result.source === "tscircuit.com" && /* @__PURE__ */ jsx9(
                        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__ */ jsx9(Loader22, { className: "rf-h-8 rf-w-8 rf-animate-spin rf-mx-auto rf-mb-2" }),
                  /* @__PURE__ */ jsx9("p", { children: "Searching..." })
                ] }) : /* @__PURE__ */ jsx9("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__ */ jsx9(
              Button,
              {
                variant: "outline",
                onClick: onClose,
                className: "rf-order-2 sm:rf-order-1",
                children: "Cancel"
              }
            ),
            /* @__PURE__ */ jsx9(
              Button,
              {
                onClick: () => {
                  if (selectedComponent) {
                    onImport(selectedComponent);
                    onClose();
                  }
                },
                disabled: !selectedComponent,
                children: "Import Component"
              }
            )
          ] })
        ]
      }
    ),
    /* @__PURE__ */ jsx9(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__ */ jsx9(DialogHeader, { className: "rf-pb-4 rf-border-b", children: /* @__PURE__ */ jsx9("div", { className: "rf-flex rf-items-start rf-justify-between rf-gap-4", children: /* @__PURE__ */ jsx9("div", { className: "rf-flex-1 rf-min-w-0", children: /* @__PURE__ */ jsx9(DialogTitle, { className: "rf-text-xl rf-font-semibold rf-truncate", children: /* @__PURE__ */ jsx9(
            "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__ */ jsxs7("div", { className: "rf-flex-1 rf-overflow-y-auto rf-py-4 rf-space-y-6", children: [
            /* @__PURE__ */ jsx9("div", { children: /* @__PURE__ */ jsx9("div", { className: "rf-space-y-3", children: detailsComponent?.owner && /* @__PURE__ */ jsxs7("div", { children: [
              /* @__PURE__ */ jsx9("label", { className: "rf-text-xs rf-font-medium rf-text-gray-500 rf-uppercase rf-tracking-wide", children: "Created by" }),
              /* @__PURE__ */ jsx9("div", { className: "rf-mt-1 rf-text-sm rf-font-medium", children: /* @__PURE__ */ jsx9(
                "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__ */ jsx9("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__ */ jsx9(
                        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__ */ jsx9(
                        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__ */ jsx9(
                        TabsContent,
                        {
                          value: "pcb",
                          className: "rf-border rf-rounded-lg rf-overflow-hidden rf-bg-gray-50",
                          children: detailsComponent?.owner && detailsComponent?.name ? /* @__PURE__ */ jsx9("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__ */ jsx9(
                            "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__ */ jsx9("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__ */ jsx9("div", { className: "rf-text-sm rf-font-medium", children: "No PCB preview available" }),
                            /* @__PURE__ */ jsx9("div", { className: "rf-text-xs rf-mt-1", children: "Preview cannot be generated" })
                          ] }) })
                        }
                      ),
                      /* @__PURE__ */ jsx9(
                        TabsContent,
                        {
                          value: "schematic",
                          className: "rf-border rf-rounded-lg rf-overflow-hidden rf-bg-gray-50",
                          children: detailsComponent?.owner && detailsComponent?.name ? /* @__PURE__ */ jsx9("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__ */ jsx9(
                            "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__ */ jsx9("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__ */ jsx9("div", { className: "rf-text-sm rf-font-medium", children: "No schematic preview available" }),
                            /* @__PURE__ */ jsx9("div", { className: "rf-text-xs rf-mt-1", children: "Preview cannot be generated" })
                          ] }) })
                        }
                      )
                    ] })
                  ]
                }
              )
            ] }),
            packageDetails?.ai_description && /* @__PURE__ */ jsxs7("div", { children: [
              /* @__PURE__ */ jsx9("h3", { className: "rf-text-lg rf-font-semibold rf-mb-3", children: "AI Description" }),
              /* @__PURE__ */ jsx9("div", { className: "rf-bg-gray-50 rf-border rf-border-gray-200 rf-rounded-lg rf-p-4", children: /* @__PURE__ */ jsx9("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__ */ jsx9("h3", { className: "rf-text-lg rf-font-semibold rf-mb-3", children: "Usage Instructions" }),
              /* @__PURE__ */ jsx9("div", { className: "rf-bg-gray-50 rf-border rf-border-gray-200 rf-rounded-lg rf-p-4", children: /* @__PURE__ */ jsx9("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__ */ jsx9(Loader22, { className: "rf-h-4 rf-w-4 rf-animate-spin" }),
              /* @__PURE__ */ jsx9("span", { className: "rf-text-sm", children: "Loading package details..." })
            ] })
          ] }),
          /* @__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__ */ jsx9("div", { className: "rf-flex-1 rf-order-3 sm:rf-order-1", children: /* @__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__ */ jsx9(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__ */ jsx9(
                Button,
                {
                  variant: "outline",
                  onClick: () => setDetailsOpen(false),
                  className: "rf-order-2 sm:rf-order-1",
                  children: "Close"
                }
              ),
              /* @__PURE__ */ jsx9(
                Button,
                {
                  onClick: () => {
                    setDetailsOpen(false);
                    if (detailsComponent) {
                      onImport(detailsComponent);
                      onClose();
                    }
                  },
                  className: "rf-bg-blue-600 hover:rf-bg-blue-700 rf-order-1 sm:rf-order-2",
                  children: "Import Component"
                }
              )
            ] })
          ] })
        ]
      }
    ) })
  ] });
};

// lib/optional-features/exporting/formats/export-fabrication-files.ts
import JSZip from "jszip";
import {
  stringifyGerberCommandLayers,
  convertSoupToGerberCommands,
  convertSoupToExcellonDrillCommands,
  stringifyExcellonDrill
} from "circuit-json-to-gerber";
import {
  convertCircuitJsonToBomRows,
  convertBomRowsToCsv
} from "circuit-json-to-bom-csv";
import { convertCircuitJsonToPickAndPlaceCsv } from "circuit-json-to-pnp-csv";

// lib/optional-features/exporting/open-for-download.ts
var openForDownload = (content, opts) => {
  const { fileName, mimeType = "text/plain" } = opts;
  const blob = content instanceof Blob ? content : new Blob([content], { type: mimeType });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = fileName;
  document.body.appendChild(a);
  a.click();
  setTimeout(() => {
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  }, 0);
};

// lib/optional-features/exporting/formats/export-fabrication-files.ts
var exportFabricationFiles = async ({
  circuitJson,
  projectName
}) => {
  const zip = new JSZip();
  const filteredCircuitJson = circuitJson.filter(
    (element) => !("error_type" in element) && !("warning_type" in element)
  );
  const gerberLayerCmds = convertSoupToGerberCommands(filteredCircuitJson, {
    flip_y_axis: false
  });
  const gerberFileContents = stringifyGerberCommandLayers(gerberLayerCmds);
  for (const [fileName, fileContents] of Object.entries(gerberFileContents)) {
    zip.file(`gerber/${fileName}.gbr`, fileContents);
  }
  const drillCmds = convertSoupToExcellonDrillCommands({
    circuitJson: filteredCircuitJson,
    is_plated: true,
    flip_y_axis: false
  });
  const drillFileContents = stringifyExcellonDrill(drillCmds);
  zip.file("gerber/drill.drl", drillFileContents);
  const bomRows = await convertCircuitJsonToBomRows({ circuitJson });
  const bomCsv = await convertBomRowsToCsv(bomRows);
  zip.file("bom.csv", bomCsv);
  const pnpCsv = await convertCircuitJsonToPickAndPlaceCsv(circuitJson);
  zip.file("pick_and_place.csv", pnpCsv);
  const zipBlob = await zip.generateAsync({ type: "blob" });
  openForDownload(zipBlob, {
    fileName: `${projectName}_fabrication_files.zip`
  });
};

// lib/optional-features/exporting/export-and-download.ts
var availableExports = [
  { extension: "json", name: "Circuit JSON" },
  { extension: "zip", name: "Fabrication Files" }
  // { extension: "svg", name: "SVG" },
  // { extension: "dsn", name: "Specctra DSN" },
  // { extension: "glb", name: "GLB (Binary GLTF)" },
  // { extension: "kicad_mod", name: "KiCad Module" },
  // { extension: "kicad_project", name: "KiCad Project" },
  // { extension: "gbr", name: "Gerbers" },
];
var exportAndDownload = async ({
  exportName,
  circuitJson,
  projectName
}) => {
  if (exportName === "Fabrication Files") {
    exportFabricationFiles({ circuitJson, projectName });
    return;
  }
  if (exportName === "Circuit JSON") {
    openForDownload(JSON.stringify(circuitJson, null, 2), {
      fileName: `${projectName}.circuit.json`,
      mimeType: "application/json"
    });
    return;
  }
  throw new Error(`Unsupported export type: "${exportName}"`);
};

// lib/components/AiReviewDialog/AiReviewDialog.tsx
import { useState as useState9 } from "react";

// lib/components/AiReviewDialog/ListAiReviewsView.tsx
import { useEffect as useEffect8, useState as useState7 } from "react";
import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
var AiReviewListView = ({
  packageName,
  onSelectReview
}) => {
  const fsMap = useRunFrameStore((s) => s.fsMap);
  const circuitJson = useRunFrameStore((s) => s.circuitJson);
  const [reviews, setReviews] = useState7([]);
  const [loading, setLoading] = useState7(false);
  const [creating, setCreating] = useState7(false);
  useEffect8(() => {
    if (!packageName || !hasRegistryToken()) return;
    setLoading(true);
    registryKy.get("ai_reviews/list", { searchParams: { package_name: packageName } }).json().then((data) => setReviews(data.ai_reviews)).catch((err) => {
      console.error("Failed to load AI reviews", err);
      toast.error("Failed to load AI reviews");
    }).finally(() => setLoading(false));
  }, [packageName]);
  const requestReview = async () => {
    if (!circuitJson) {
      toast.error("Need Circuit JSON to Request AI Review");
      return;
    }
    if (!hasRegistryToken()) {
      toast.error("Missing registry token");
      return;
    }
    setCreating(true);
    try {
      const { ai_review } = await registryKy.post("ai_reviews/create", {
        json: {
          package_name: packageName ?? "unknown",
          fs_map: Object.fromEntries(fsMap),
          circuit_json: circuitJson
        }
      }).json();
      setReviews((r) => [ai_review, ...r]);
      onSelectReview(ai_review);
      toast.success("AI review requested");
    } catch (err) {
      console.error("Failed to create AI review", err);
      toast.error("Failed to request AI review");
    } finally {
      setCreating(false);
    }
  };
  return /* @__PURE__ */ jsxs8(Fragment3, { children: [
    /* @__PURE__ */ jsxs8(DialogHeader, { children: [
      /* @__PURE__ */ jsx10(DialogTitle, { children: "AI Review" }),
      /* @__PURE__ */ jsx10(DialogDescription, { children: "Select an AI review or request a new one." })
    ] }),
    /* @__PURE__ */ jsx10("div", { className: "rf-flex rf-gap-4 rf-mt-4", children: /* @__PURE__ */ jsx10("div", { className: "rf-w-48 rf-h-64 rf-overflow-y-auto rf-border rf-rounded rf-p-2 rf-flex-shrink-0", children: loading ? /* @__PURE__ */ jsx10("div", { className: "rf-text-sm", children: "Loading..." }) : reviews.length > 0 ? reviews.map((review) => /* @__PURE__ */ jsx10(
      "div",
      {
        className: "rf-text-sm rf-p-2 rf-cursor-pointer rf-rounded hover:rf-bg-zinc-100",
        onClick: () => onSelectReview(review),
        children: new Date(review.created_at || "").toLocaleString()
      },
      review.ai_review_id
    )) : /* @__PURE__ */ jsx10("div", { className: "rf-text-sm rf-text-muted-foreground", children: "No AI reviews found." }) }) }),
    /* @__PURE__ */ jsx10(DialogFooter, { className: "rf-mt-4", children: /* @__PURE__ */ jsx10(Button, { onClick: requestReview, disabled: creating, children: creating ? "Requesting..." : "Review my Board" }) })
  ] });
};

// lib/components/AiReviewDialog/ViewAiReviewView.tsx
import { useEffect as useEffect9, useMemo as useMemo3, useState as useState8 } from "react";
import { marked } from "marked";
import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
var AiReviewViewView = ({
  review,
  onBack
}) => {
  const [aiReviewText, setAiReviewText] = useState8(
    review.ai_review_text ?? null
  );
  const registryKy2 = getRegistryKy();
  const aiReviewId = review.ai_review_id;
  useEffect9(() => {
    if (!aiReviewId) return;
    let timeout;
    async function loadAiReviewText() {
      try {
        const response = await registryKy2.get(
          "ai_reviews/get",
          {
            searchParams: { ai_review_id: aiReviewId }
          }
        );
        const { ai_review: newAiReview } = await response.json();
        if (newAiReview.ai_review_text) {
          setAiReviewText(newAiReview.ai_review_text);
          return;
        }
      } catch (e) {
        console.error("Failed to load AI review text", e);
      }
      timeout = setTimeout(loadAiReviewText, 1e3);
    }
    timeout = setTimeout(loadAiReviewText, 1e3);
    return () => clearTimeout(timeout);
  }, [aiReviewId]);
  const html = useMemo3(
    () => marked.parse(review.ai_review_text || ""),
    [review.ai_review_text]
  );
  return /* @__PURE__ */ jsxs9(Fragment4, { children: [
    /* @__PURE__ */ jsxs9(DialogHeader, { className: "rf-flex rf-flex-row rf-items-center rf-justify-between", children: [
      /* @__PURE__ */ jsx11(Button, { variant: "ghost", size: "sm", onClick: onBack, children: "Back" }),
      /* @__PURE__ */ jsx11(DialogTitle, { children: "AI Review" })
    ] }),
    aiReviewText ? /* @__PURE__ */ jsx11(
      "div",
      {
        className: "rf-h-64 rf-overflow-y-auto rf-prose rf-max-w-none rf-mt-2",
        dangerouslySetInnerHTML: { __html: html }
      }
    ) : /* @__PURE__ */ jsx11("div", { className: "rf-h-64 rf-overflow-y-auto rf-prose rf-max-w-none rf-mt-2", children: /* @__PURE__ */ jsxs9("div", { className: "rf-flex rf-items-center rf-justify-center rf-h-full", children: [
      /* @__PURE__ */ jsxs9(
        "svg",
        {
          className: "rf-animate-spin rf-h-6 rf-w-6 rf-text-zinc-400 rf-mr-2",
          xmlns: "http://www.w3.org/2000/svg",
          fill: "none",
          viewBox: "0 0 24 24",
          "aria-hidden": "true",
          children: [
            /* @__PURE__ */ jsx11(
              "circle",
              {
                className: "rf-opacity-25",
                cx: "12",
                cy: "12",
                r: "10",
                stroke: "currentColor",
                strokeWidth: "4"
              }
            ),
            /* @__PURE__ */ jsx11(
              "path",
              {
                className: "rf-opacity-75",
                fill: "currentColor",
                d: "M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"
              }
            )
          ]
        }
      ),
      /* @__PURE__ */ jsx11("span", { children: "Loading..." })
    ] }) })
  ] });
};

// lib/components/AiReviewDialog/AiReviewDialog.tsx
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
var AiReviewDialog = ({
  isOpen,
  onClose,
  packageName
}) => {
  const [stage, setStage] = useState9(
    "list_reviews"
  );
  const [selectedReview, setSelectedReview] = useState9(null);
  const handleSelect = (review) => {
    setSelectedReview(review);
    setStage("view_review");
  };
  return /* @__PURE__ */ jsx12(
    Dialog,
    {
      open: isOpen,
      onOpenChange: (open) => {
        if (!open) {
          setStage("list_reviews");
          setSelectedReview(null);
          onClose();
        }
      },
      children: /* @__PURE__ */ jsxs10(DialogContent, { className: "rf-max-w-2xl", children: [
        stage === "list_reviews" && /* @__PURE__ */ jsx12(
          AiReviewListView,
          {
            packageName,
            onSelectReview: handleSelect
          }
        ),
        stage === "view_review" && selectedReview && /* @__PURE__ */ jsx12(
          AiReviewViewView,
          {
            review: selectedReview,
            onBack: () => setStage("list_reviews")
          }
        )
      ] })
    }
  );
};

// lib/components/RunFrameForCli/LeftHeader.tsx
import { Toaster } from "react-hot-toast";

// lib/optional-features/importing/import-component-from-jlcpcb.ts
import { fetchEasyEDAComponent, convertRawEasyToTsx } from "easyeda/browser";
import ky from "ky";
var importComponentFromJlcpcb = async (jlcpcbPartNumber) => {
  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 ?? ""
        }
      });
    }
  });
  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/RunFrameForCli/LeftHeader.tsx
import { Fragment as Fragment5, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
var RunframeCliLeftHeader = (props) => {
  const lastRunEvalVersion = useRunnerStore((s) => s.lastRunEvalVersion);
  const [snippetName, setSnippetName] = useState10(null);
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState10(false);
  const [hasNeverBeenSaved, setHasNeverBeenSaved] = useState10(true);
  const [isSaving, setIsSaving] = useState10(false);
  const [requestToSaveSentAt, setRequestToSaveSentAt] = useState10(
    null
  );
  const [availableSnippets, setAvailableSnippets] = useState10(
    null
  );
  const [isSelectSnippetDialogOpen, setIsSelectSnippetDialogOpen] = useState10(false);
  const [notificationMessage, setNotificationMessage] = useState10(
    null
  );
  const [errorMessage, setErrorMessage] = useState10(null);
  const [isError, setIsError] = useState10(false);
  const [isExporting, setisExporting] = useState10(false);
  const orderDialog = useOrderDialogCli();
  const pushEvent = useRunFrameStore((state) => state.pushEvent);
  const recentEvents = useRunFrameStore((state) => state.recentEvents);
  const firstRenderTime = useMemo4(() => Date.now(), []);
  useEventHandler((event) => {
    if (new Date(event.created_at).valueOf() < firstRenderTime + 500) return;
    if (event.event_type === "FILE_UPDATED") {
      setHasUnsavedChanges(true);
      return;
    }
    if (event.event_type === "SNIPPET_SAVED") {
      setHasUnsavedChanges(false);
      setHasNeverBeenSaved(false);
      setNotificationMessage("Snippet saved successfully.");
      setIsError(false);
      return;
    }
    if (event.event_type === "REQUEST_EXPORT") {
      setisExporting(true);
      setNotificationMessage("Export processing...");
      setIsError(false);
    }
    if (event.event_type === "EXPORT_CREATED") {
      setNotificationMessage(`Export created: ${event.exportFilePath}`);
      setIsError(false);
      setisExporting(false);
    }
  });
  useEffect10(() => {
    if (!isSaving || requestToSaveSentAt === null) return;
    const eventsSinceRequestToSave = recentEvents.filter(
      (event) => new Date(event.created_at).valueOf() > requestToSaveSentAt
    );
    const saveFailedEvent = eventsSinceRequestToSave.find(
      (event) => event.event_type === "FAILED_TO_SAVE_SNIPPET"
    );
    const saveSuccessEvent = eventsSinceRequestToSave.find(
      (event) => event.event_type === "SNIPPET_SAVED"
    );
    if (saveFailedEvent) {
      setIsSaving(false);
      setRequestToSaveSentAt(null);
      setErrorMessage(
        saveFailedEvent.message ?? "Failed to save snippet. See console for error."
      );
      console.error(saveFailedEvent.message);
      setIsError(true);
      if (saveFailedEvent.error_code === "SNIPPET_UNSET" && saveFailedEvent.available_snippet_names) {
        setAvailableSnippets(saveFailedEvent.available_snippet_names);
        setIsSelectSnippetDialogOpen(true);
      }
    }
    if (saveSuccessEvent) {
      setIsSaving(false);
      setRequestToSaveSentAt(null);
      setNotificationMessage("Snippet saved successfully.");
      setIsError(false);
    }
  }, [recentEvents, isSaving]);
  const triggerSaveSnippet = async () => {
    setIsSaving(true);
    setRequestToSaveSentAt(Date.now());
    setNotificationMessage(null);
    setIsError(false);
    await pushEvent({
      event_type: "REQUEST_TO_SAVE_SNIPPET",
      snippet_name: snippetName
    });
  };
  const circuitJson = useRunFrameStore((state) => state.circuitJson);
  const [isImportDialogOpen, setIsImportDialogOpen] = useState10(false);
  const [isAiReviewDialogOpen, setIsAiReviewDialogOpen] = useState10(false);
  return /* @__PURE__ */ jsxs11(Fragment5, { children: [
    /* @__PURE__ */ jsxs11(DropdownMenu, { children: [
      /* @__PURE__ */ jsx13(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx13("div", { className: "rf-whitespace-nowrap rf-text-xs font-medium rf-p-2 rf-mx-1 rf-cursor-pointer rf-relative", children: "File" }) }),
      /* @__PURE__ */ jsxs11(DropdownMenuContent, { children: [
        /* @__PURE__ */ jsx13(
          DropdownMenuItem,
          {
            className: "rf-text-xs",
            onSelect: triggerSaveSnippet,
            disabled: isSaving,
            children: isSaving ? "Saving..." : "Push"
          }
        ),
        parseInt(window.location.port) > 5e3 && /* @__PURE__ */ jsx13(
          DropdownMenuItem,
          {
            className: "rf-text-xs",
            onSelect: () => {
              orderDialog.open();
            },
            children: "Order"
          }
        ),
        /* @__PURE__ */ jsx13(
          DropdownMenuItem,
          {
            className: "rf-text-xs",
            onSelect: () => setIsImportDialogOpen(true),
            disabled: isSaving,
            children: "Import"
          }
        ),
        /* @__PURE__ */ jsx13(
          DropdownMenuItem,
          {
            className: "rf-text-xs",
            onSelect: () => {
              if (!hasRegistryToken()) {
                toast.error("Requires tscircuit token");
                return;
              }
              setIsAiReviewDialogOpen(true);
            },
            children: "AI Review"
          }
        ),
        /* @__PURE__ */ jsxs11(DropdownMenuSub, { children: [
          /* @__PURE__ */ jsx13(
            DropdownMenuSubTrigger,
            {
              className: "rf-text-xs",
              disabled: isExporting,
              children: isExporting ? "Exporting..." : "Export"
            }
          ),
          /* @__PURE__ */ jsx13(DropdownMenuPortal, { children: /* @__PURE__ */ jsx13(DropdownMenuSubContent, { children: availableExports.map((exp, i) => /* @__PURE__ */ jsx13(
            DropdownMenuItem,
            {
              onSelect: () => {
                if (!circuitJson) {
                  toast.error("No Circuit JSON to export");
                  return;
                }
                exportAndDownload({
                  exportName: exp.name,
                  circuitJson,
                  projectName: snippetName ?? "Untitled"
                });
              },
              disabled: isExporting,
              children: /* @__PURE__ */ jsx13("span", { className: "rf-text-xs", children: exp.name })
            },
            i
          )) }) })
        ] }),
        /* @__PURE__ */ jsxs11(DropdownMenuSub, { children: [
          /* @__PURE__ */ jsx13(DropdownMenuSubTrigger, { className: "rf-text-xs", children: "Advanced" }),
          /* @__PURE__ */ jsx13(DropdownMenuPortal, { children: /* @__PURE__ */ jsxs11(DropdownMenuSubContent, { children: [
            /* @__PURE__ */ jsx13(DropdownMenuItem, { className: "rf-flex rf-items-center rf-gap-2", children: /* @__PURE__ */ jsxs11("div", { className: "rf-flex rf-items-center rf-gap-2", children: [
              /* @__PURE__ */ jsx13(
                Checkbox,
                {
                  id: "load-latest-eval",
                  checked: props.shouldLoadLatestEval,
                  onCheckedChange: (checked) => {
                    props.onChangeShouldLoadLatestEval(checked === true);
                  }
                }
              ),
              /* @__PURE__ */ jsx13(
                "label",
                {
                  htmlFor: "load-latest-eval",
                  className: "rf-text-xs rf-cursor-pointer",
                  children: "Force Latest @tscircuit/eval"
                }
              )
            ] }) }),
            lastRunEvalVersion && /* @__PURE__ */ jsx13(DropdownMenuItem, { className: "rf-flex rf-items-center rf-gap-2", children: /* @__PURE__ */ jsx13("div", { className: "rf-flex rf-items-center rf-gap-2", children: /* @__PURE__ */ jsxs11("span", { className: "rf-text-xs", children: [
              "@tscircuit/eval@",
              lastRunEvalVersion
            ] }) }) }),
            /* @__PURE__ */ jsx13(
              DropdownMenuItem,
              {
                className: "rf-flex rf-items-center rf-gap-2",
                onClick: () => {
                  window.open("/api/admin", "_blank");
                },
                children: /* @__PURE__ */ jsx13("div", { className: "rf-flex rf-items-center rf-gap-2", children: /* @__PURE__ */ jsx13("span", { className: "rf-text-xs", children: "CLI Admin Panel" }) })
              }
            )
          ] }) })
        ] })
      ] }),
      /* @__PURE__ */ jsx13(AlertDialog, { open: isError, onOpenChange: setIsError, children: /* @__PURE__ */ jsxs11(AlertDialogContent, { children: [
        /* @__PURE__ */ jsxs11(AlertDialogHeader, { children: [
          /* @__PURE__ */ jsx13(AlertDialogTitle, { children: "Error Saving Snippet" }),
          /* @__PURE__ */ jsx13(AlertDialogDescription, { children: errorMessage })
        ] }),
        /* @__PURE__ */ jsx13(AlertDialogFooter, { children: /* @__PURE__ */ jsx13(AlertDialogCancel, { onClick: () => setIsError(false), children: "Dismiss" }) })
      ] }) }),
      /* @__PURE__ */ jsx13(
        SelectSnippetDialog,
        {
          snippetNames: availableSnippets ?? [],
          onSelect: async (name) => {
            setIsSaving(true);
            setRequestToSaveSentAt(Date.now());
            setSnippetName(name);
            await pushEvent({
              event_type: "REQUEST_TO_SAVE_SNIPPET",
              snippet_name: name
            });
            setIsSelectSnippetDialogOpen(false);
          },
          onCancel: () => setIsSelectSnippetDialogOpen(false),
          isOpen: isSelectSnippetDialogOpen
        }
      )
    ] }),
    /* @__PURE__ */ jsx13(
      ImportComponentDialog,
      {
        isOpen: isImportDialogOpen,
        onClose: () => setIsImportDialogOpen(false),
        onImport: async (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
                );
                return { filePath };
              }
            },
            {
              loading: `Importing component: "${component.name}"`,
              error: (error) => {
                console.error("IMPORT ERROR", error);
                return `Error importing component: "${component.name}": ${error.toString()}`;
              },
              success: (data) => data?.filePath ? `Imported to "${data.filePath}"` : "Import Successful"
            }
          );
        }
      }
    ),
    /* @__PURE__ */ jsx13(
      AiReviewDialog,
      {
        isOpen: isAiReviewDialogOpen,
        onClose: () => setIsAiReviewDialogOpen(false),
        packageName: snippetName
      }
    ),
    /* @__PURE__ */ jsx13(
      Toaster,
      {
        position: "top-center",
        reverseOrder: false,
        containerStyle: { zIndex: 1e5 },
        toastOptions: { style: { zIndex: 1e5 } }
      }
    ),
    /* @__PURE__ */ jsx13(
      orderDialog.OrderDialog,
      {
        isOpen: orderDialog.isOpen,
        onClose: orderDialog.close,
        stage: orderDialog.stage,
        setStage: orderDialog.setStage
      }
    )
  ] });
};

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