@tscircuit/schematic-viewer 2.0.79 → 2.0.81

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -438,7 +438,7 @@ var enableDebug = () => {
438
438
  };
439
439
 
440
440
  // lib/components/SchematicViewer.tsx
441
- import { useCallback as useCallback6, useEffect as useEffect9, useMemo as useMemo4, useRef as useRef6, useState as useState6 } from "react";
441
+ import { useCallback as useCallback6, useEffect as useEffect9, useMemo as useMemo5, useRef as useRef6, useState as useState6 } from "react";
442
442
  import { toString as transformToString } from "transformation-matrix";
443
443
  import { useMouseMatrixTransform } from "use-mouse-matrix-transform";
444
444
 
@@ -575,12 +575,137 @@ var useContextMenu = ({ containerRef }) => {
575
575
  };
576
576
  };
577
577
 
578
+ // lib/utils/component-details.ts
579
+ import {
580
+ getPcbElementBounds,
581
+ getPcbElementsWithinBounds
582
+ } from "@tscircuit/circuit-json-util";
583
+ import { gzipSync, strToU8 } from "fflate";
584
+ var hiddenSourceComponentKeys = /* @__PURE__ */ new Set([
585
+ "type",
586
+ "source_component_id",
587
+ "source_group_id",
588
+ "subcircuit_id",
589
+ "display_name",
590
+ "ftype",
591
+ "are_pins_interchangeable"
592
+ ]);
593
+ var priorityKeys = [
594
+ "name",
595
+ "resistance",
596
+ "capacitance",
597
+ "inductance",
598
+ "frequency",
599
+ "voltage",
600
+ "current",
601
+ "max_voltage_rating",
602
+ "max_current_rating",
603
+ "power_rating",
604
+ "manufacturer_part_number",
605
+ "supplier_part_numbers"
606
+ ];
607
+ var getKeyPriority = (key) => {
608
+ const priority = priorityKeys.indexOf(key);
609
+ return priority === -1 ? priorityKeys.length : priority;
610
+ };
611
+ var formatComponentValue = (sourceComponent, key, value) => {
612
+ if (key === "name") return String(value);
613
+ const displayValue = sourceComponent[`display_${key}`];
614
+ if (typeof displayValue === "string" && displayValue.trim()) {
615
+ const propValue = key === "resistance" ? displayValue.replace(/Ω$/, "") : displayValue;
616
+ return JSON.stringify(propValue);
617
+ }
618
+ return JSON.stringify(value) ?? String(value);
619
+ };
620
+ var getSourceComponentInfoEntries = (sourceComponent) => Object.entries(sourceComponent).filter(([key, value]) => {
621
+ if (hiddenSourceComponentKeys.has(key)) return false;
622
+ if (key.startsWith("display_") && key.slice("display_".length) in sourceComponent) {
623
+ return false;
624
+ }
625
+ return value !== void 0 && value !== null && value !== "";
626
+ }).sort(([keyA], [keyB]) => {
627
+ const priorityDifference = getKeyPriority(keyA) - getKeyPriority(keyB);
628
+ return priorityDifference || keyA.localeCompare(keyB);
629
+ }).map(([key, value]) => ({
630
+ key,
631
+ label: key,
632
+ value: formatComponentValue(sourceComponent, key, value)
633
+ }));
634
+ var getSchematicComponentDetails = (circuitJson, schematicComponentId) => {
635
+ const schematicComponent = circuitJson.find(
636
+ (element) => element.type === "schematic_component" && element.schematic_component_id === schematicComponentId
637
+ );
638
+ if (!schematicComponent) return null;
639
+ const sourceComponent = circuitJson.find(
640
+ (element) => element.type === "source_component" && element.source_component_id === schematicComponent.source_component_id
641
+ );
642
+ if (!sourceComponent) return null;
643
+ const pcbComponent = circuitJson.find(
644
+ (element) => element.type === "pcb_component" && element.source_component_id === sourceComponent.source_component_id
645
+ );
646
+ const cadComponent = circuitJson.find(
647
+ (element) => element.type === "cad_component" && element.source_component_id === sourceComponent.source_component_id && (!pcbComponent || element.pcb_component_id === pcbComponent.pcb_component_id)
648
+ );
649
+ const footprinterString = pcbComponent?.footprinter_string ?? cadComponent?.footprinter_string;
650
+ const footprintPreview = pcbComponent ? getPcbComponentPreview(circuitJson, pcbComponent.pcb_component_id) : null;
651
+ return {
652
+ schematicComponent,
653
+ sourceComponent,
654
+ pcbComponent,
655
+ footprinterString,
656
+ footprintPreviewCircuitJson: footprintPreview?.circuitJson,
657
+ footprintPreviewViewBox: footprintPreview?.viewBox
658
+ };
659
+ };
660
+ var PCB_PREVIEW_PADDING_MM = 2;
661
+ var getPcbComponentPreview = (circuitJson, pcbComponentId) => {
662
+ const pcbComponent = circuitJson.find(
663
+ (element) => element.type === "pcb_component" && element.pcb_component_id === pcbComponentId
664
+ );
665
+ if (!pcbComponent) return null;
666
+ const componentBounds = getPcbElementBounds(pcbComponent);
667
+ if (!componentBounds) return null;
668
+ const viewBox = {
669
+ minX: componentBounds.minX - PCB_PREVIEW_PADDING_MM,
670
+ minY: componentBounds.minY - PCB_PREVIEW_PADDING_MM,
671
+ maxX: componentBounds.maxX + PCB_PREVIEW_PADDING_MM,
672
+ maxY: componentBounds.maxY + PCB_PREVIEW_PADDING_MM
673
+ };
674
+ return {
675
+ circuitJson: getPcbElementsWithinBounds(circuitJson, viewBox),
676
+ viewBox
677
+ };
678
+ };
679
+ var bytesToBase64 = (bytes) => {
680
+ let binary = "";
681
+ const chunkSize = 8192;
682
+ for (let index = 0; index < bytes.length; index += chunkSize) {
683
+ binary += String.fromCharCode(...bytes.subarray(index, index + chunkSize));
684
+ }
685
+ return btoa(binary);
686
+ };
687
+ var getFootprintPreviewUrl = (footprintPreviewCircuitJson, viewBox) => {
688
+ const encodedCircuitJson = bytesToBase64(
689
+ gzipSync(strToU8(JSON.stringify(footprintPreviewCircuitJson)))
690
+ );
691
+ const url = new URL("https://svg.tscircuit.com/");
692
+ url.searchParams.set("svg_type", "pcb");
693
+ url.searchParams.set("circuit_json", encodedCircuitJson);
694
+ url.searchParams.set(
695
+ "viewbox",
696
+ [viewBox.minX, viewBox.minY, viewBox.maxX, viewBox.maxY].join(",")
697
+ );
698
+ url.searchParams.set("background_color", "#f8fafc");
699
+ return url.toString();
700
+ };
701
+
578
702
  // lib/utils/z-index-map.ts
579
703
  var zIndexMap = {
580
704
  contextMenu: 110,
581
705
  viewMenu: 55,
582
706
  viewMenuIcon: 48,
583
707
  clickToInteractOverlay: 100,
708
+ schematicComponentDetailsTooltip: 105,
584
709
  schematicComponentHoverOutline: 47,
585
710
  schematicPortHoverOutline: 48
586
711
  };
@@ -764,6 +889,150 @@ var MouseTrackerProvider = ({ children }) => {
764
889
  return /* @__PURE__ */ jsx(MouseTrackerContext.Provider, { value, children });
765
890
  };
766
891
 
892
+ // lib/components/SchematicComponentDetailsTooltip.tsx
893
+ import { useMemo as useMemo2 } from "react";
894
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
895
+ var detailLabelStyle = {
896
+ color: "#64748b",
897
+ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace',
898
+ fontSize: "12px",
899
+ lineHeight: 1.45
900
+ };
901
+ var SchematicComponentDetailsTooltip = ({
902
+ sourceComponent,
903
+ footprinterString,
904
+ footprintPreviewCircuitJson,
905
+ footprintPreviewViewBox,
906
+ left,
907
+ top,
908
+ width,
909
+ maxHeight
910
+ }) => {
911
+ const infoEntries = useMemo2(
912
+ () => getSourceComponentInfoEntries(sourceComponent),
913
+ [sourceComponent]
914
+ );
915
+ const footprintPreviewUrl = useMemo2(
916
+ () => footprintPreviewCircuitJson?.length && footprintPreviewViewBox ? getFootprintPreviewUrl(
917
+ footprintPreviewCircuitJson,
918
+ footprintPreviewViewBox
919
+ ) : void 0,
920
+ [footprintPreviewCircuitJson, footprintPreviewViewBox]
921
+ );
922
+ return /* @__PURE__ */ jsxs(
923
+ "dialog",
924
+ {
925
+ open: true,
926
+ "aria-label": `${sourceComponent.name} component details`,
927
+ "data-schematic-component-details-tooltip": true,
928
+ style: {
929
+ position: "absolute",
930
+ left,
931
+ right: "auto",
932
+ top,
933
+ bottom: "auto",
934
+ width,
935
+ maxHeight,
936
+ margin: 0,
937
+ padding: 0,
938
+ overflowY: "auto",
939
+ boxSizing: "border-box",
940
+ border: "1px solid #cbd5e1",
941
+ borderRadius: "4px",
942
+ backgroundColor: "rgba(255, 255, 255, 0.98)",
943
+ boxShadow: "0 20px 25px -5px rgba(15, 23, 42, 0.18), 0 8px 10px -6px rgba(15, 23, 42, 0.12)",
944
+ color: "#0f172a",
945
+ fontFamily: 'Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
946
+ pointerEvents: "auto",
947
+ userSelect: "text",
948
+ WebkitUserSelect: "text",
949
+ zIndex: zIndexMap.schematicComponentDetailsTooltip
950
+ },
951
+ onMouseDown: (event) => event.stopPropagation(),
952
+ onClick: (event) => event.stopPropagation(),
953
+ children: [
954
+ /* @__PURE__ */ jsxs(
955
+ "dl",
956
+ {
957
+ style: {
958
+ display: "grid",
959
+ gridTemplateColumns: "minmax(110px, 0.8fr) minmax(0, 1.2fr)",
960
+ gap: "6px 12px",
961
+ margin: 0,
962
+ padding: "8px"
963
+ },
964
+ children: [
965
+ infoEntries.map((entry) => /* @__PURE__ */ jsxs("div", { style: { display: "contents" }, children: [
966
+ /* @__PURE__ */ jsx2("dt", { style: detailLabelStyle, children: entry.label }),
967
+ /* @__PURE__ */ jsx2(
968
+ "dd",
969
+ {
970
+ style: {
971
+ minWidth: 0,
972
+ margin: 0,
973
+ color: "#1e293b",
974
+ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace',
975
+ fontSize: "12px",
976
+ lineHeight: 1.45,
977
+ overflowWrap: "anywhere"
978
+ },
979
+ children: entry.value
980
+ }
981
+ )
982
+ ] }, entry.key)),
983
+ footprinterString && /* @__PURE__ */ jsxs("div", { style: { display: "contents" }, children: [
984
+ /* @__PURE__ */ jsx2("dt", { style: detailLabelStyle, children: "footprint" }),
985
+ /* @__PURE__ */ jsx2(
986
+ "dd",
987
+ {
988
+ style: {
989
+ minWidth: 0,
990
+ margin: 0,
991
+ color: "#1e293b",
992
+ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace',
993
+ fontSize: "12px",
994
+ lineHeight: 1.45,
995
+ overflowWrap: "anywhere"
996
+ },
997
+ children: JSON.stringify(footprinterString)
998
+ }
999
+ )
1000
+ ] })
1001
+ ]
1002
+ }
1003
+ ),
1004
+ footprinterString && footprintPreviewUrl && /* @__PURE__ */ jsx2("div", { style: { padding: "0 4px 4px" }, children: /* @__PURE__ */ jsx2(
1005
+ "div",
1006
+ {
1007
+ style: {
1008
+ height: "210px",
1009
+ overflow: "hidden",
1010
+ border: "1px solid #e2e8f0",
1011
+ borderRadius: "2px",
1012
+ background: "#f8fafc"
1013
+ },
1014
+ children: /* @__PURE__ */ jsx2(
1015
+ "img",
1016
+ {
1017
+ src: footprintPreviewUrl,
1018
+ alt: `${sourceComponent.name} ${footprinterString} PCB footprint`,
1019
+ loading: "lazy",
1020
+ referrerPolicy: "no-referrer",
1021
+ style: {
1022
+ display: "block",
1023
+ width: "100%",
1024
+ height: "100%",
1025
+ objectFit: "contain"
1026
+ }
1027
+ }
1028
+ )
1029
+ }
1030
+ ) })
1031
+ ]
1032
+ }
1033
+ );
1034
+ };
1035
+
767
1036
  // lib/components/SchematicComponentMouseTarget.tsx
768
1037
  import { useCallback as useCallback4, useEffect as useEffect7, useRef as useRef4, useState as useState3 } from "react";
769
1038
 
@@ -772,7 +1041,7 @@ import {
772
1041
  useContext as useContext2,
773
1042
  useEffect as useEffect6,
774
1043
  useId,
775
- useMemo as useMemo2,
1044
+ useMemo as useMemo3,
776
1045
  useRef as useRef3,
777
1046
  useSyncExternalStore
778
1047
  } from "react";
@@ -786,7 +1055,7 @@ var useMouseEventsOverBoundingBox = (options) => {
786
1055
  const id = useId();
787
1056
  const latestOptionsRef = useRef3(options);
788
1057
  latestOptionsRef.current = options;
789
- const handleClick = useMemo2(
1058
+ const handleClick = useMemo3(
790
1059
  () => (event) => {
791
1060
  latestOptionsRef.current.onClick?.(event);
792
1061
  },
@@ -825,7 +1094,7 @@ var useMouseEventsOverBoundingBox = (options) => {
825
1094
  };
826
1095
 
827
1096
  // lib/components/SchematicComponentMouseTarget.tsx
828
- import { jsx as jsx2 } from "react/jsx-runtime";
1097
+ import { jsx as jsx3 } from "react/jsx-runtime";
829
1098
  var areMeasurementsEqual = (a, b) => {
830
1099
  if (!a && !b) return true;
831
1100
  if (!a || !b) return false;
@@ -938,7 +1207,7 @@ var SchematicComponentMouseTarget = ({
938
1207
  return null;
939
1208
  }
940
1209
  const rect = measurement.rect;
941
- return /* @__PURE__ */ jsx2(
1210
+ return /* @__PURE__ */ jsx3(
942
1211
  "div",
943
1212
  {
944
1213
  style: {
@@ -957,7 +1226,7 @@ var SchematicComponentMouseTarget = ({
957
1226
 
958
1227
  // lib/components/SchematicPortMouseTarget.tsx
959
1228
  import { useCallback as useCallback5, useEffect as useEffect8, useRef as useRef5, useState as useState4 } from "react";
960
- import { Fragment as Fragment2, jsx as jsx3, jsxs } from "react/jsx-runtime";
1229
+ import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
961
1230
  var areMeasurementsEqual2 = (a, b) => {
962
1231
  if (!a && !b) return true;
963
1232
  if (!a || !b) return false;
@@ -1072,8 +1341,8 @@ var SchematicPortMouseTarget = ({
1072
1341
  return null;
1073
1342
  }
1074
1343
  const rect = measurement.rect;
1075
- return /* @__PURE__ */ jsxs(Fragment2, { children: [
1076
- /* @__PURE__ */ jsx3(
1344
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
1345
+ /* @__PURE__ */ jsx4(
1077
1346
  "div",
1078
1347
  {
1079
1348
  style: {
@@ -1091,7 +1360,7 @@ var SchematicPortMouseTarget = ({
1091
1360
  }
1092
1361
  }
1093
1362
  ),
1094
- hovering && portLabel && /* @__PURE__ */ jsx3(
1363
+ hovering && portLabel && /* @__PURE__ */ jsx4(
1095
1364
  "div",
1096
1365
  {
1097
1366
  style: {
@@ -1118,7 +1387,7 @@ var SchematicPortMouseTarget = ({
1118
1387
  // lib/components/SchematicSheetSelector.tsx
1119
1388
  import { useState as useState5 } from "react";
1120
1389
  import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
1121
- import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
1390
+ import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
1122
1391
  var FONT_FAMILY = 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
1123
1392
  var contentStyles = {
1124
1393
  backgroundColor: "#ffffff",
@@ -1168,7 +1437,7 @@ var MENU_CSS = `
1168
1437
  .sv-sheet-chevron { transition: transform 0.2s ease; }
1169
1438
  [data-state="open"] > .sv-sheet-chevron { transform: rotate(180deg); }
1170
1439
  `;
1171
- var CheckIcon = () => /* @__PURE__ */ jsx4(
1440
+ var CheckIcon = () => /* @__PURE__ */ jsx5(
1172
1441
  "svg",
1173
1442
  {
1174
1443
  width: "14",
@@ -1180,10 +1449,10 @@ var CheckIcon = () => /* @__PURE__ */ jsx4(
1180
1449
  strokeLinecap: "round",
1181
1450
  strokeLinejoin: "round",
1182
1451
  "aria-hidden": "true",
1183
- children: /* @__PURE__ */ jsx4("path", { d: "M20 6 9 17l-5-5" })
1452
+ children: /* @__PURE__ */ jsx5("path", { d: "M20 6 9 17l-5-5" })
1184
1453
  }
1185
1454
  );
1186
- var ChevronDownIcon = ({ className }) => /* @__PURE__ */ jsx4(
1455
+ var ChevronDownIcon = ({ className }) => /* @__PURE__ */ jsx5(
1187
1456
  "svg",
1188
1457
  {
1189
1458
  className,
@@ -1197,7 +1466,7 @@ var ChevronDownIcon = ({ className }) => /* @__PURE__ */ jsx4(
1197
1466
  strokeLinejoin: "round",
1198
1467
  style: { opacity: 0.6, flexShrink: 0 },
1199
1468
  "aria-hidden": "true",
1200
- children: /* @__PURE__ */ jsx4("path", { d: "m6 9 6 6 6-6" })
1469
+ children: /* @__PURE__ */ jsx5("path", { d: "m6 9 6 6 6-6" })
1201
1470
  }
1202
1471
  );
1203
1472
  var SchematicSheetSelector = ({
@@ -1211,10 +1480,10 @@ var SchematicSheetSelector = ({
1211
1480
  (s) => s.schematic_sheet_id === selectedSheetId
1212
1481
  );
1213
1482
  const selectedLabel = selectedSheet?.name ?? "Select sheet";
1214
- return /* @__PURE__ */ jsxs2(Fragment3, { children: [
1215
- /* @__PURE__ */ jsx4("style", { children: MENU_CSS }),
1216
- /* @__PURE__ */ jsxs2(DropdownMenu.Root, { open, onOpenChange: setOpen, modal: false, children: [
1217
- /* @__PURE__ */ jsx4(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs2(
1483
+ return /* @__PURE__ */ jsxs3(Fragment3, { children: [
1484
+ /* @__PURE__ */ jsx5("style", { children: MENU_CSS }),
1485
+ /* @__PURE__ */ jsxs3(DropdownMenu.Root, { open, onOpenChange: setOpen, modal: false, children: [
1486
+ /* @__PURE__ */ jsx5(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs3(
1218
1487
  "button",
1219
1488
  {
1220
1489
  type: "button",
@@ -1241,13 +1510,13 @@ var SchematicSheetSelector = ({
1241
1510
  zIndex: zIndexMap.viewMenuIcon
1242
1511
  },
1243
1512
  children: [
1244
- /* @__PURE__ */ jsx4("span", { style: { color: "#888888", flexShrink: 0 }, children: "Sheet:" }),
1245
- /* @__PURE__ */ jsx4("span", { style: { ...ellipsisStyles, minWidth: 0 }, children: selectedLabel }),
1246
- /* @__PURE__ */ jsx4(ChevronDownIcon, { className: "sv-sheet-chevron" })
1513
+ /* @__PURE__ */ jsx5("span", { style: { color: "#888888", flexShrink: 0 }, children: "Sheet:" }),
1514
+ /* @__PURE__ */ jsx5("span", { style: { ...ellipsisStyles, minWidth: 0 }, children: selectedLabel }),
1515
+ /* @__PURE__ */ jsx5(ChevronDownIcon, { className: "sv-sheet-chevron" })
1247
1516
  ]
1248
1517
  }
1249
1518
  ) }),
1250
- /* @__PURE__ */ jsx4(DropdownMenu.Portal, { children: /* @__PURE__ */ jsx4(
1519
+ /* @__PURE__ */ jsx5(DropdownMenu.Portal, { children: /* @__PURE__ */ jsx5(
1251
1520
  DropdownMenu.Content,
1252
1521
  {
1253
1522
  style: contentStyles,
@@ -1257,7 +1526,7 @@ var SchematicSheetSelector = ({
1257
1526
  collisionPadding: 10,
1258
1527
  children: sheets.map((sheet) => {
1259
1528
  const selected = sheet.schematic_sheet_id === selectedSheetId;
1260
- return /* @__PURE__ */ jsxs2(
1529
+ return /* @__PURE__ */ jsxs3(
1261
1530
  DropdownMenu.Item,
1262
1531
  {
1263
1532
  className: "sv-sheet-item",
@@ -1269,8 +1538,8 @@ var SchematicSheetSelector = ({
1269
1538
  setOpen(false);
1270
1539
  },
1271
1540
  children: [
1272
- /* @__PURE__ */ jsx4("span", { style: iconSlotStyles, children: selected && /* @__PURE__ */ jsx4(CheckIcon, {}) }),
1273
- /* @__PURE__ */ jsx4("span", { style: { ...ellipsisStyles, minWidth: 0 }, children: sheet.name })
1541
+ /* @__PURE__ */ jsx5("span", { style: iconSlotStyles, children: selected && /* @__PURE__ */ jsx5(CheckIcon, {}) }),
1542
+ /* @__PURE__ */ jsx5("span", { style: { ...ellipsisStyles, minWidth: 0 }, children: sheet.name })
1274
1543
  ]
1275
1544
  },
1276
1545
  sheet.schematic_sheet_id
@@ -1285,12 +1554,12 @@ var SchematicSheetSelector = ({
1285
1554
  // lib/components/ViewMenu.tsx
1286
1555
  import * as DropdownMenu2 from "@radix-ui/react-dropdown-menu";
1287
1556
  import { su as su3 } from "@tscircuit/soup-util";
1288
- import { useMemo as useMemo3 } from "react";
1557
+ import { useMemo as useMemo4 } from "react";
1289
1558
 
1290
1559
  // package.json
1291
1560
  var package_default = {
1292
1561
  name: "@tscircuit/schematic-viewer",
1293
- version: "2.0.78",
1562
+ version: "2.0.80",
1294
1563
  main: "dist/index.js",
1295
1564
  type: "module",
1296
1565
  scripts: {
@@ -1329,16 +1598,18 @@ var package_default = {
1329
1598
  },
1330
1599
  dependencies: {
1331
1600
  "@radix-ui/react-dropdown-menu": "^2.1.16",
1601
+ "@tscircuit/circuit-json-util": "^0.0.108",
1332
1602
  "circuit-json": "^0.0.465",
1333
1603
  "circuit-to-svg": "^0.0.393",
1334
1604
  debug: "^4.4.0",
1605
+ fflate: "^0.8.3",
1335
1606
  "performance-now": "^2.1.0",
1336
1607
  "use-mouse-matrix-transform": "^1.2.2"
1337
1608
  }
1338
1609
  };
1339
1610
 
1340
1611
  // lib/components/ViewMenu.tsx
1341
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
1612
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1342
1613
  var FONT_FAMILY2 = 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
1343
1614
  var contentStyles2 = {
1344
1615
  backgroundColor: "#262626",
@@ -1387,7 +1658,7 @@ var HIGHLIGHT_CSS = `
1387
1658
  .sv-vm-item:hover:not([data-disabled]) { background-color: #404040; }
1388
1659
  .sv-vm-item[data-disabled] { opacity: 0.45; cursor: not-allowed; }
1389
1660
  `;
1390
- var CheckIcon2 = () => /* @__PURE__ */ jsx5(
1661
+ var CheckIcon2 = () => /* @__PURE__ */ jsx6(
1391
1662
  "svg",
1392
1663
  {
1393
1664
  width: "14",
@@ -1399,7 +1670,7 @@ var CheckIcon2 = () => /* @__PURE__ */ jsx5(
1399
1670
  strokeLinecap: "round",
1400
1671
  strokeLinejoin: "round",
1401
1672
  "aria-hidden": "true",
1402
- children: /* @__PURE__ */ jsx5("path", { d: "M20 6 9 17l-5-5" })
1673
+ children: /* @__PURE__ */ jsx6("path", { d: "M20 6 9 17l-5-5" })
1403
1674
  }
1404
1675
  );
1405
1676
  var ViewMenu = ({
@@ -1415,7 +1686,7 @@ var ViewMenu = ({
1415
1686
  showPorts,
1416
1687
  onTogglePorts
1417
1688
  }) => {
1418
- const hasGroups = useMemo3(() => {
1689
+ const hasGroups = useMemo4(() => {
1419
1690
  if (!circuitJson || circuitJson.length === 0) return false;
1420
1691
  try {
1421
1692
  const sourceGroups = su3(circuitJson).source_group?.list() || [];
@@ -1439,7 +1710,7 @@ var ViewMenu = ({
1439
1710
  return false;
1440
1711
  }
1441
1712
  }, [circuitJsonKey]);
1442
- const hasPorts = useMemo3(() => {
1713
+ const hasPorts = useMemo4(() => {
1443
1714
  if (!circuitJson || circuitJson.length === 0) return false;
1444
1715
  try {
1445
1716
  return (su3(circuitJson).schematic_port?.list() || []).length > 0;
@@ -1448,7 +1719,7 @@ var ViewMenu = ({
1448
1719
  return false;
1449
1720
  }
1450
1721
  }, [circuitJsonKey]);
1451
- return /* @__PURE__ */ jsx5(
1722
+ return /* @__PURE__ */ jsx6(
1452
1723
  "div",
1453
1724
  {
1454
1725
  ref: menuRef,
@@ -1459,9 +1730,9 @@ var ViewMenu = ({
1459
1730
  width: 0,
1460
1731
  height: 0
1461
1732
  },
1462
- children: /* @__PURE__ */ jsxs3(DropdownMenu2.Root, { open: true, onOpenChange, modal: false, children: [
1463
- /* @__PURE__ */ jsx5(DropdownMenu2.Trigger, { asChild: true, children: /* @__PURE__ */ jsx5("div", { style: { position: "absolute", width: 1, height: 1 } }) }),
1464
- /* @__PURE__ */ jsx5(DropdownMenu2.Portal, { children: /* @__PURE__ */ jsxs3(
1733
+ children: /* @__PURE__ */ jsxs4(DropdownMenu2.Root, { open: true, onOpenChange, modal: false, children: [
1734
+ /* @__PURE__ */ jsx6(DropdownMenu2.Trigger, { asChild: true, children: /* @__PURE__ */ jsx6("div", { style: { position: "absolute", width: 1, height: 1 } }) }),
1735
+ /* @__PURE__ */ jsx6(DropdownMenu2.Portal, { children: /* @__PURE__ */ jsxs4(
1465
1736
  DropdownMenu2.Content,
1466
1737
  {
1467
1738
  style: contentStyles2,
@@ -1470,8 +1741,8 @@ var ViewMenu = ({
1470
1741
  collisionPadding: 10,
1471
1742
  avoidCollisions: true,
1472
1743
  children: [
1473
- /* @__PURE__ */ jsx5("style", { children: HIGHLIGHT_CSS }),
1474
- /* @__PURE__ */ jsxs3(
1744
+ /* @__PURE__ */ jsx6("style", { children: HIGHLIGHT_CSS }),
1745
+ /* @__PURE__ */ jsxs4(
1475
1746
  DropdownMenu2.Item,
1476
1747
  {
1477
1748
  className: "sv-vm-item",
@@ -1484,12 +1755,12 @@ var ViewMenu = ({
1484
1755
  if (hasPorts) onTogglePorts(!showPorts);
1485
1756
  },
1486
1757
  children: [
1487
- /* @__PURE__ */ jsx5("span", { style: iconSlotStyles2, children: showPorts && /* @__PURE__ */ jsx5(CheckIcon2, {}) }),
1488
- /* @__PURE__ */ jsx5("span", { children: "Show Schematic Ports" })
1758
+ /* @__PURE__ */ jsx6("span", { style: iconSlotStyles2, children: showPorts && /* @__PURE__ */ jsx6(CheckIcon2, {}) }),
1759
+ /* @__PURE__ */ jsx6("span", { children: "Show Schematic Ports" })
1489
1760
  ]
1490
1761
  }
1491
1762
  ),
1492
- /* @__PURE__ */ jsxs3(
1763
+ /* @__PURE__ */ jsxs4(
1493
1764
  DropdownMenu2.Item,
1494
1765
  {
1495
1766
  className: "sv-vm-item",
@@ -1502,12 +1773,12 @@ var ViewMenu = ({
1502
1773
  if (hasGroups) onToggleGroups(!showGroups);
1503
1774
  },
1504
1775
  children: [
1505
- /* @__PURE__ */ jsx5("span", { style: iconSlotStyles2, children: showGroups && /* @__PURE__ */ jsx5(CheckIcon2, {}) }),
1506
- /* @__PURE__ */ jsx5("span", { children: "View Schematic Groups" })
1776
+ /* @__PURE__ */ jsx6("span", { style: iconSlotStyles2, children: showGroups && /* @__PURE__ */ jsx6(CheckIcon2, {}) }),
1777
+ /* @__PURE__ */ jsx6("span", { children: "View Schematic Groups" })
1507
1778
  ]
1508
1779
  }
1509
1780
  ),
1510
- /* @__PURE__ */ jsxs3(
1781
+ /* @__PURE__ */ jsxs4(
1511
1782
  DropdownMenu2.Item,
1512
1783
  {
1513
1784
  className: "sv-vm-item",
@@ -1518,13 +1789,13 @@ var ViewMenu = ({
1518
1789
  onToggleGrid(!showGrid);
1519
1790
  },
1520
1791
  children: [
1521
- /* @__PURE__ */ jsx5("span", { style: iconSlotStyles2, children: showGrid && /* @__PURE__ */ jsx5(CheckIcon2, {}) }),
1522
- /* @__PURE__ */ jsx5("span", { children: "Show Grid" })
1792
+ /* @__PURE__ */ jsx6("span", { style: iconSlotStyles2, children: showGrid && /* @__PURE__ */ jsx6(CheckIcon2, {}) }),
1793
+ /* @__PURE__ */ jsx6("span", { children: "Show Grid" })
1523
1794
  ]
1524
1795
  }
1525
1796
  ),
1526
- /* @__PURE__ */ jsx5(DropdownMenu2.Separator, { style: separatorStyles }),
1527
- /* @__PURE__ */ jsxs3(
1797
+ /* @__PURE__ */ jsx6(DropdownMenu2.Separator, { style: separatorStyles }),
1798
+ /* @__PURE__ */ jsxs4(
1528
1799
  "div",
1529
1800
  {
1530
1801
  style: {
@@ -1550,7 +1821,7 @@ var ViewMenu = ({
1550
1821
  };
1551
1822
 
1552
1823
  // lib/components/SchematicViewer.tsx
1553
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1824
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1554
1825
  var SchematicViewer = ({
1555
1826
  circuitJson,
1556
1827
  containerStyle,
@@ -1573,11 +1844,11 @@ var SchematicViewer = ({
1573
1844
  const getCircuitHash = (circuitJson2) => {
1574
1845
  return `${circuitJson2?.length || 0}_${circuitJson2?.editCount || 0}`;
1575
1846
  };
1576
- const circuitJsonKey = useMemo4(
1847
+ const circuitJsonKey = useMemo5(
1577
1848
  () => getCircuitHash(circuitJson),
1578
1849
  [circuitJson]
1579
1850
  );
1580
- const schematicSheets = useMemo4(() => {
1851
+ const schematicSheets = useMemo5(() => {
1581
1852
  try {
1582
1853
  return circuitJson.filter((elm) => elm?.type === "schematic_sheet").slice().sort((a, b) => (a.sheet_index ?? 0) - (b.sheet_index ?? 0));
1583
1854
  } catch (err) {
@@ -1630,6 +1901,7 @@ var SchematicViewer = ({
1630
1901
  }, [showSchematicPorts]);
1631
1902
  const [isHoveringClickableComponent, setIsHoveringClickableComponent] = useState6(false);
1632
1903
  const hoveringComponentsRef = useRef6(/* @__PURE__ */ new Set());
1904
+ const [selectedSchematicComponent, setSelectedSchematicComponent] = useState6(null);
1633
1905
  const handleComponentHoverChange = useCallback6(
1634
1906
  (componentId, isHovering) => {
1635
1907
  if (isHovering) {
@@ -1656,7 +1928,8 @@ var SchematicViewer = ({
1656
1928
  );
1657
1929
  const svgDivRef = useRef6(null);
1658
1930
  const touchStartRef = useRef6(null);
1659
- const schematicComponentIds = useMemo4(() => {
1931
+ const zoomScaleRef = useRef6({ x: 1, y: 1 });
1932
+ const schematicComponentIds = useMemo5(() => {
1660
1933
  try {
1661
1934
  const components = su4(circuitJson).schematic_component?.list() ?? [];
1662
1935
  return components.filter(
@@ -1667,7 +1940,7 @@ var SchematicViewer = ({
1667
1940
  return [];
1668
1941
  }
1669
1942
  }, [circuitJsonKey, circuitJson, activeSheetId]);
1670
- const schematicPortsInfo = useMemo4(() => {
1943
+ const schematicPortsInfo = useMemo5(() => {
1671
1944
  if (!showSchematicPortsInternal) return [];
1672
1945
  try {
1673
1946
  const ports = (su4(circuitJson).schematic_port?.list() ?? []).filter(
@@ -1716,6 +1989,11 @@ var SchematicViewer = ({
1716
1989
  );
1717
1990
  const { ref: containerRef } = useMouseMatrixTransform({
1718
1991
  onSetTransform(transform) {
1992
+ const zoomChanged = transform.a !== zoomScaleRef.current.x || transform.d !== zoomScaleRef.current.y;
1993
+ zoomScaleRef.current = { x: transform.a, y: transform.d };
1994
+ if (zoomChanged) {
1995
+ setSelectedSchematicComponent(null);
1996
+ }
1719
1997
  if (!svgDivRef.current) return;
1720
1998
  svgDivRef.current.style.transform = transformToString(transform);
1721
1999
  },
@@ -1731,7 +2009,77 @@ var SchematicViewer = ({
1731
2009
  contextMenuEventHandlers
1732
2010
  } = useContextMenu({ containerRef });
1733
2011
  const { containerWidth, containerHeight } = useResizeHandling(containerRef);
1734
- const svgString = useMemo4(() => {
2012
+ const selectedComponentDetails = useMemo5(
2013
+ () => selectedSchematicComponent ? getSchematicComponentDetails(
2014
+ circuitJson,
2015
+ selectedSchematicComponent.schematicComponentId
2016
+ ) : null,
2017
+ [circuitJsonKey, circuitJson, selectedSchematicComponent]
2018
+ );
2019
+ const componentTooltipLayout = useMemo5(() => {
2020
+ if (!selectedSchematicComponent || !containerWidth || !containerHeight) {
2021
+ return null;
2022
+ }
2023
+ const margin = 12;
2024
+ const gap = 14;
2025
+ const width = Math.min(420, containerWidth - margin * 2);
2026
+ const maxHeight = Math.min(520, containerHeight - margin * 2);
2027
+ const { anchorX, anchorY } = selectedSchematicComponent;
2028
+ const rightOfAnchor = anchorX + gap;
2029
+ const leftOfAnchor = anchorX - width - gap;
2030
+ const left = rightOfAnchor + width <= containerWidth - margin ? rightOfAnchor : leftOfAnchor >= margin ? leftOfAnchor : Math.max(
2031
+ margin,
2032
+ Math.min(anchorX - width / 2, containerWidth - width - margin)
2033
+ );
2034
+ const top = Math.max(
2035
+ margin,
2036
+ Math.min(anchorY - 24, containerHeight - maxHeight - margin)
2037
+ );
2038
+ return { left, top, width, maxHeight };
2039
+ }, [selectedSchematicComponent, containerWidth, containerHeight]);
2040
+ const handleSchematicComponentClick = useCallback6(
2041
+ (schematicComponentId, event) => {
2042
+ if (event.target instanceof Element && event.target.closest("[data-schematic-component-details-tooltip]")) {
2043
+ return;
2044
+ }
2045
+ const containerRect = containerRef.current?.getBoundingClientRect();
2046
+ if (!containerRect) return;
2047
+ setSelectedSchematicComponent({
2048
+ schematicComponentId,
2049
+ anchorX: event.clientX - containerRect.left,
2050
+ anchorY: event.clientY - containerRect.top
2051
+ });
2052
+ onSchematicComponentClicked?.({
2053
+ schematicComponentId,
2054
+ event
2055
+ });
2056
+ },
2057
+ [containerRef, onSchematicComponentClicked]
2058
+ );
2059
+ useEffect9(() => {
2060
+ setSelectedSchematicComponent(null);
2061
+ }, [circuitJsonKey, activeSheetId]);
2062
+ useEffect9(() => {
2063
+ if (!selectedSchematicComponent) return;
2064
+ const handleKeyDown = (event) => {
2065
+ if (event.key === "Escape") {
2066
+ setSelectedSchematicComponent(null);
2067
+ }
2068
+ };
2069
+ const handleDocumentMouseDown = (event) => {
2070
+ if (event.target instanceof Element && event.target.closest("[data-schematic-component-details-tooltip]")) {
2071
+ return;
2072
+ }
2073
+ setSelectedSchematicComponent(null);
2074
+ };
2075
+ window.addEventListener("keydown", handleKeyDown);
2076
+ document.addEventListener("mousedown", handleDocumentMouseDown);
2077
+ return () => {
2078
+ window.removeEventListener("keydown", handleKeyDown);
2079
+ document.removeEventListener("mousedown", handleDocumentMouseDown);
2080
+ };
2081
+ }, [selectedSchematicComponent]);
2082
+ const svgString = useMemo5(() => {
1735
2083
  if (!containerWidth || !containerHeight) return "";
1736
2084
  return convertCircuitJsonToSchematicSvg(circuitJson, {
1737
2085
  width: containerWidth,
@@ -1754,7 +2102,7 @@ var SchematicViewer = ({
1754
2102
  showSchematicPortsInternal,
1755
2103
  activeSheetId
1756
2104
  ]);
1757
- const containerBackgroundColor = useMemo4(() => {
2105
+ const containerBackgroundColor = useMemo5(() => {
1758
2106
  const match = svgString.match(
1759
2107
  /<svg[^>]*style="[^"]*background-color:\s*([^;\"]+)/i
1760
2108
  );
@@ -1772,8 +2120,8 @@ var SchematicViewer = ({
1772
2120
  circuitJsonKey: `${circuitJsonKey}_${activeSheetId ?? ""}`,
1773
2121
  enabled: netHoverHighlightEnabled
1774
2122
  });
1775
- const svgDiv = useMemo4(
1776
- () => /* @__PURE__ */ jsx6(
2123
+ const svgDiv = useMemo5(
2124
+ () => /* @__PURE__ */ jsx7(
1777
2125
  "div",
1778
2126
  {
1779
2127
  ref: svgDivRef,
@@ -1781,18 +2129,18 @@ var SchematicViewer = ({
1781
2129
  pointerEvents: clickToInteractEnabled ? isInteractionEnabled ? "auto" : "none" : "auto",
1782
2130
  transformOrigin: "0 0"
1783
2131
  },
1784
- className: onSchematicComponentClicked ? "schematic-component-clickable" : void 0,
2132
+ className: "schematic-component-clickable",
1785
2133
  dangerouslySetInnerHTML: { __html: svgString }
1786
2134
  }
1787
2135
  ),
1788
2136
  [svgString, isInteractionEnabled, clickToInteractEnabled]
1789
2137
  );
1790
- return /* @__PURE__ */ jsxs4(MouseTracker, { children: [
1791
- netHoverHighlightEnabled && /* @__PURE__ */ jsx6("style", { children: `.sch-net-faded { opacity: 0.35; }
2138
+ return /* @__PURE__ */ jsxs5(MouseTracker, { children: [
2139
+ netHoverHighlightEnabled && /* @__PURE__ */ jsx7("style", { children: `.sch-net-faded { opacity: 0.35; }
1792
2140
  svg :is(g.trace, g.trace-overlays, g[data-schematic-component-id], [data-schematic-net-label-id]) { transition: opacity 0.12s ease-in-out; }` }),
1793
- onSchematicComponentClicked && /* @__PURE__ */ jsx6("style", { children: ".schematic-component-clickable [data-schematic-component-id]:hover { cursor: pointer !important; }" }),
1794
- onSchematicPortClicked && /* @__PURE__ */ jsx6("style", { children: "[data-schematic-port-id]:hover { cursor: pointer !important; }" }),
1795
- /* @__PURE__ */ jsxs4(
2141
+ /* @__PURE__ */ jsx7("style", { children: ".schematic-component-clickable [data-schematic-component-id]:hover { cursor: pointer !important; }" }),
2142
+ onSchematicPortClicked && /* @__PURE__ */ jsx7("style", { children: "[data-schematic-port-id]:hover { cursor: pointer !important; }" }),
2143
+ /* @__PURE__ */ jsxs5(
1796
2144
  "div",
1797
2145
  {
1798
2146
  ref: containerRef,
@@ -1800,7 +2148,7 @@ var SchematicViewer = ({
1800
2148
  position: "relative",
1801
2149
  backgroundColor: containerBackgroundColor,
1802
2150
  overflow: "hidden",
1803
- cursor: clickToInteractEnabled && !isInteractionEnabled ? "pointer" : isHoveringClickableComponent && onSchematicComponentClicked ? "pointer" : isHoveringClickablePort && onSchematicPortClicked ? "pointer" : "grab",
2151
+ cursor: clickToInteractEnabled && !isInteractionEnabled ? "pointer" : isHoveringClickableComponent ? "pointer" : isHoveringClickablePort && onSchematicPortClicked ? "pointer" : "grab",
1804
2152
  minHeight: "300px",
1805
2153
  userSelect: "none",
1806
2154
  WebkitUserSelect: "none",
@@ -1827,7 +2175,7 @@ var SchematicViewer = ({
1827
2175
  },
1828
2176
  onTouchCancel: contextMenuEventHandlers.onTouchCancel,
1829
2177
  children: [
1830
- !isInteractionEnabled && clickToInteractEnabled && /* @__PURE__ */ jsx6(
2178
+ !isInteractionEnabled && clickToInteractEnabled && /* @__PURE__ */ jsx7(
1831
2179
  "div",
1832
2180
  {
1833
2181
  onClick: (e) => {
@@ -1846,7 +2194,7 @@ var SchematicViewer = ({
1846
2194
  pointerEvents: "all",
1847
2195
  touchAction: "pan-x pan-y pinch-zoom"
1848
2196
  },
1849
- children: /* @__PURE__ */ jsx6(
2197
+ children: /* @__PURE__ */ jsx7(
1850
2198
  "div",
1851
2199
  {
1852
2200
  style: {
@@ -1863,7 +2211,7 @@ var SchematicViewer = ({
1863
2211
  )
1864
2212
  }
1865
2213
  ),
1866
- menuVisible && /* @__PURE__ */ jsx6(
2214
+ menuVisible && /* @__PURE__ */ jsx7(
1867
2215
  ViewMenu,
1868
2216
  {
1869
2217
  circuitJson,
@@ -1890,7 +2238,7 @@ var SchematicViewer = ({
1890
2238
  onToggleGrid: setShowGridInternal
1891
2239
  }
1892
2240
  ),
1893
- /* @__PURE__ */ jsx6(
2241
+ /* @__PURE__ */ jsx7(
1894
2242
  SchematicSheetSelector,
1895
2243
  {
1896
2244
  sheets: schematicSheets,
@@ -1898,7 +2246,7 @@ var SchematicViewer = ({
1898
2246
  onSelectSheet: handleSelectSheet
1899
2247
  }
1900
2248
  ),
1901
- onSchematicComponentClicked && schematicComponentIds.map((componentId) => /* @__PURE__ */ jsx6(
2249
+ schematicComponentIds.map((componentId) => /* @__PURE__ */ jsx7(
1902
2250
  SchematicComponentMouseTarget,
1903
2251
  {
1904
2252
  componentId,
@@ -1907,17 +2255,22 @@ var SchematicViewer = ({
1907
2255
  showOutline: true,
1908
2256
  circuitJsonKey,
1909
2257
  onHoverChange: handleComponentHoverChange,
1910
- onComponentClick: (id, event) => {
1911
- onSchematicComponentClicked?.({
1912
- schematicComponentId: id,
1913
- event
1914
- });
1915
- }
2258
+ onComponentClick: handleSchematicComponentClick
1916
2259
  },
1917
2260
  componentId
1918
2261
  )),
1919
2262
  svgDiv,
1920
- showSchematicPortsInternal && schematicPortsInfo.map(({ portId, label }) => /* @__PURE__ */ jsx6(
2263
+ selectedComponentDetails && componentTooltipLayout && /* @__PURE__ */ jsx7(
2264
+ SchematicComponentDetailsTooltip,
2265
+ {
2266
+ sourceComponent: selectedComponentDetails.sourceComponent,
2267
+ footprinterString: selectedComponentDetails.footprinterString,
2268
+ footprintPreviewCircuitJson: selectedComponentDetails.footprintPreviewCircuitJson,
2269
+ footprintPreviewViewBox: selectedComponentDetails.footprintPreviewViewBox,
2270
+ ...componentTooltipLayout
2271
+ }
2272
+ ),
2273
+ showSchematicPortsInternal && schematicPortsInfo.map(({ portId, label }) => /* @__PURE__ */ jsx7(
1921
2274
  SchematicPortMouseTarget,
1922
2275
  {
1923
2276
  portId,
@@ -1947,7 +2300,7 @@ import {
1947
2300
  convertCircuitJsonToSchematicSimulationSvg,
1948
2301
  convertCircuitJsonToSimulationGraphSvg
1949
2302
  } from "circuit-to-svg";
1950
- import { useEffect as useEffect10, useMemo as useMemo5, useRef as useRef7, useState as useState8 } from "react";
2303
+ import { useEffect as useEffect10, useMemo as useMemo6, useRef as useRef7, useState as useState8 } from "react";
1951
2304
  import { toString as transformToString2 } from "transformation-matrix";
1952
2305
  import { useMouseMatrixTransform as useMouseMatrixTransform2 } from "use-mouse-matrix-transform";
1953
2306
 
@@ -1966,7 +2319,7 @@ var getAnalogSimulationBackgroundColor = (simulationSvg, colorOverrides) => getR
1966
2319
  // lib/components/AnalogSimulationSelector.tsx
1967
2320
  import * as DropdownMenu3 from "@radix-ui/react-dropdown-menu";
1968
2321
  import { useState as useState7 } from "react";
1969
- import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
2322
+ import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1970
2323
  var FONT_FAMILY3 = 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
1971
2324
  var contentStyles3 = {
1972
2325
  backgroundColor: "#ffffff",
@@ -2016,7 +2369,7 @@ var MENU_CSS2 = `
2016
2369
  .sv-simulation-chevron { transition: transform 0.2s ease; }
2017
2370
  [data-state="open"] > .sv-simulation-chevron { transform: rotate(180deg); }
2018
2371
  `;
2019
- var CheckIcon3 = () => /* @__PURE__ */ jsx7(
2372
+ var CheckIcon3 = () => /* @__PURE__ */ jsx8(
2020
2373
  "svg",
2021
2374
  {
2022
2375
  width: "14",
@@ -2028,10 +2381,10 @@ var CheckIcon3 = () => /* @__PURE__ */ jsx7(
2028
2381
  strokeLinecap: "round",
2029
2382
  strokeLinejoin: "round",
2030
2383
  "aria-hidden": "true",
2031
- children: /* @__PURE__ */ jsx7("path", { d: "M20 6 9 17l-5-5" })
2384
+ children: /* @__PURE__ */ jsx8("path", { d: "M20 6 9 17l-5-5" })
2032
2385
  }
2033
2386
  );
2034
- var ChevronDownIcon2 = ({ className }) => /* @__PURE__ */ jsx7(
2387
+ var ChevronDownIcon2 = ({ className }) => /* @__PURE__ */ jsx8(
2035
2388
  "svg",
2036
2389
  {
2037
2390
  className,
@@ -2045,7 +2398,7 @@ var ChevronDownIcon2 = ({ className }) => /* @__PURE__ */ jsx7(
2045
2398
  strokeLinejoin: "round",
2046
2399
  style: { opacity: 0.6, flexShrink: 0 },
2047
2400
  "aria-hidden": "true",
2048
- children: /* @__PURE__ */ jsx7("path", { d: "m6 9 6 6 6-6" })
2401
+ children: /* @__PURE__ */ jsx8("path", { d: "m6 9 6 6 6-6" })
2049
2402
  }
2050
2403
  );
2051
2404
  var getSimulationLabels = (simulations) => {
@@ -2071,10 +2424,10 @@ var AnalogSimulationSelector = ({
2071
2424
  ({ simulation }) => simulation.simulation_experiment_id === selectedSimulationExperimentId
2072
2425
  );
2073
2426
  const selectedLabel = selectedSimulation?.label ?? "Select simulation";
2074
- return /* @__PURE__ */ jsxs5(Fragment4, { children: [
2075
- /* @__PURE__ */ jsx7("style", { children: MENU_CSS2 }),
2076
- /* @__PURE__ */ jsxs5(DropdownMenu3.Root, { open, onOpenChange: setOpen, modal: false, children: [
2077
- /* @__PURE__ */ jsx7(DropdownMenu3.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs5(
2427
+ return /* @__PURE__ */ jsxs6(Fragment4, { children: [
2428
+ /* @__PURE__ */ jsx8("style", { children: MENU_CSS2 }),
2429
+ /* @__PURE__ */ jsxs6(DropdownMenu3.Root, { open, onOpenChange: setOpen, modal: false, children: [
2430
+ /* @__PURE__ */ jsx8(DropdownMenu3.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs6(
2078
2431
  "button",
2079
2432
  {
2080
2433
  type: "button",
@@ -2101,13 +2454,13 @@ var AnalogSimulationSelector = ({
2101
2454
  zIndex: zIndexMap.viewMenuIcon
2102
2455
  },
2103
2456
  children: [
2104
- /* @__PURE__ */ jsx7("span", { style: { color: "#888888", flexShrink: 0 }, children: "Simulation:" }),
2105
- /* @__PURE__ */ jsx7("span", { style: { ...ellipsisStyles2, minWidth: 0 }, children: selectedLabel }),
2106
- /* @__PURE__ */ jsx7(ChevronDownIcon2, { className: "sv-simulation-chevron" })
2457
+ /* @__PURE__ */ jsx8("span", { style: { color: "#888888", flexShrink: 0 }, children: "Simulation:" }),
2458
+ /* @__PURE__ */ jsx8("span", { style: { ...ellipsisStyles2, minWidth: 0 }, children: selectedLabel }),
2459
+ /* @__PURE__ */ jsx8(ChevronDownIcon2, { className: "sv-simulation-chevron" })
2107
2460
  ]
2108
2461
  }
2109
2462
  ) }),
2110
- /* @__PURE__ */ jsx7(DropdownMenu3.Portal, { children: /* @__PURE__ */ jsx7(
2463
+ /* @__PURE__ */ jsx8(DropdownMenu3.Portal, { children: /* @__PURE__ */ jsx8(
2111
2464
  DropdownMenu3.Content,
2112
2465
  {
2113
2466
  style: contentStyles3,
@@ -2117,7 +2470,7 @@ var AnalogSimulationSelector = ({
2117
2470
  collisionPadding: 10,
2118
2471
  children: simulationLabels.map(({ simulation, label }) => {
2119
2472
  const selected = simulation.simulation_experiment_id === selectedSimulationExperimentId;
2120
- return /* @__PURE__ */ jsxs5(
2473
+ return /* @__PURE__ */ jsxs6(
2121
2474
  DropdownMenu3.Item,
2122
2475
  {
2123
2476
  className: "sv-simulation-item",
@@ -2129,8 +2482,8 @@ var AnalogSimulationSelector = ({
2129
2482
  setOpen(false);
2130
2483
  },
2131
2484
  children: [
2132
- /* @__PURE__ */ jsx7("span", { style: iconSlotStyles3, children: selected && /* @__PURE__ */ jsx7(CheckIcon3, {}) }),
2133
- /* @__PURE__ */ jsx7("span", { style: { ...ellipsisStyles2, minWidth: 0 }, children: label })
2485
+ /* @__PURE__ */ jsx8("span", { style: iconSlotStyles3, children: selected && /* @__PURE__ */ jsx8(CheckIcon3, {}) }),
2486
+ /* @__PURE__ */ jsx8("span", { style: { ...ellipsisStyles2, minWidth: 0 }, children: label })
2134
2487
  ]
2135
2488
  },
2136
2489
  simulation.simulation_experiment_id
@@ -2143,7 +2496,7 @@ var AnalogSimulationSelector = ({
2143
2496
  };
2144
2497
 
2145
2498
  // lib/components/AnalogSimulationViewer.tsx
2146
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
2499
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
2147
2500
  var DEFAULT_RENDER_WIDTH = 1200;
2148
2501
  var DEFAULT_COMBINED_RENDER_ASPECT_RATIO = 1;
2149
2502
  var DEFAULT_GRAPH_ONLY_RENDER_ASPECT_RATIO = 2;
@@ -2189,7 +2542,7 @@ var AnalogSimulationViewer = ({
2189
2542
  setCircuitJson(inputCircuitJson);
2190
2543
  setIsLoading(false);
2191
2544
  }, [inputCircuitJson]);
2192
- const simulationExperiments = useMemo5(() => {
2545
+ const simulationExperiments = useMemo6(() => {
2193
2546
  if (!circuitJson) return [];
2194
2547
  return circuitJson.filter(
2195
2548
  (element) => element.type === "simulation_experiment"
@@ -2208,7 +2561,7 @@ var AnalogSimulationViewer = ({
2208
2561
  setSelectedSimulationExperimentId(nextSimulationExperimentId);
2209
2562
  onSimulationChange?.(nextSimulationExperimentId);
2210
2563
  };
2211
- const simulationSvg = useMemo5(() => {
2564
+ const simulationSvg = useMemo6(() => {
2212
2565
  if (!circuitJson || !effectiveWidth || !effectiveHeight || !simulationExperimentId)
2213
2566
  return "";
2214
2567
  try {
@@ -2253,7 +2606,7 @@ var AnalogSimulationViewer = ({
2253
2606
  setSvgObjectUrl(null);
2254
2607
  }
2255
2608
  }, [simulationSvg]);
2256
- const containerBackgroundColor = useMemo5(() => {
2609
+ const containerBackgroundColor = useMemo6(() => {
2257
2610
  return getAnalogSimulationBackgroundColor(simulationSvg, colorOverrides);
2258
2611
  }, [simulationSvg, colorOverrides]);
2259
2612
  const handleMouseDown = (_e) => {
@@ -2277,7 +2630,7 @@ var AnalogSimulationViewer = ({
2277
2630
  };
2278
2631
  }, []);
2279
2632
  if (isLoading) {
2280
- return /* @__PURE__ */ jsx8(
2633
+ return /* @__PURE__ */ jsx9(
2281
2634
  "div",
2282
2635
  {
2283
2636
  style: {
@@ -2297,7 +2650,7 @@ var AnalogSimulationViewer = ({
2297
2650
  );
2298
2651
  }
2299
2652
  if (error) {
2300
- return /* @__PURE__ */ jsx8(
2653
+ return /* @__PURE__ */ jsx9(
2301
2654
  "div",
2302
2655
  {
2303
2656
  style: {
@@ -2312,15 +2665,15 @@ var AnalogSimulationViewer = ({
2312
2665
  ...containerStyle
2313
2666
  },
2314
2667
  className,
2315
- children: /* @__PURE__ */ jsxs6("div", { style: { textAlign: "center", padding: "20px" }, children: [
2316
- /* @__PURE__ */ jsx8("div", { style: { fontWeight: "bold", marginBottom: "8px" }, children: "Circuit Conversion Error" }),
2317
- /* @__PURE__ */ jsx8("div", { style: { fontSize: "14px" }, children: error })
2668
+ children: /* @__PURE__ */ jsxs7("div", { style: { textAlign: "center", padding: "20px" }, children: [
2669
+ /* @__PURE__ */ jsx9("div", { style: { fontWeight: "bold", marginBottom: "8px" }, children: "Circuit Conversion Error" }),
2670
+ /* @__PURE__ */ jsx9("div", { style: { fontSize: "14px" }, children: error })
2318
2671
  ] })
2319
2672
  }
2320
2673
  );
2321
2674
  }
2322
2675
  if (!simulationSvg) {
2323
- return /* @__PURE__ */ jsxs6(
2676
+ return /* @__PURE__ */ jsxs7(
2324
2677
  "div",
2325
2678
  {
2326
2679
  style: {
@@ -2336,11 +2689,11 @@ var AnalogSimulationViewer = ({
2336
2689
  },
2337
2690
  className,
2338
2691
  children: [
2339
- /* @__PURE__ */ jsx8("div", { style: { fontSize: "16px", color: "#475569", fontWeight: 500 }, children: "No Simulation Found" }),
2340
- /* @__PURE__ */ jsxs6("div", { style: { fontSize: "14px", color: "#64748b" }, children: [
2692
+ /* @__PURE__ */ jsx9("div", { style: { fontSize: "16px", color: "#475569", fontWeight: 500 }, children: "No Simulation Found" }),
2693
+ /* @__PURE__ */ jsxs7("div", { style: { fontSize: "14px", color: "#64748b" }, children: [
2341
2694
  "Use",
2342
2695
  " ",
2343
- /* @__PURE__ */ jsx8(
2696
+ /* @__PURE__ */ jsx9(
2344
2697
  "code",
2345
2698
  {
2346
2699
  style: {
@@ -2360,7 +2713,7 @@ var AnalogSimulationViewer = ({
2360
2713
  }
2361
2714
  );
2362
2715
  }
2363
- return /* @__PURE__ */ jsxs6(
2716
+ return /* @__PURE__ */ jsxs7(
2364
2717
  "div",
2365
2718
  {
2366
2719
  ref: (node) => {
@@ -2379,7 +2732,7 @@ var AnalogSimulationViewer = ({
2379
2732
  onMouseDown: handleMouseDown,
2380
2733
  onTouchStart: handleTouchStart,
2381
2734
  children: [
2382
- /* @__PURE__ */ jsx8(
2735
+ /* @__PURE__ */ jsx9(
2383
2736
  AnalogSimulationSelector,
2384
2737
  {
2385
2738
  simulations: simulationExperiments,
@@ -2387,7 +2740,7 @@ var AnalogSimulationViewer = ({
2387
2740
  onSelectSimulation: handleSelectSimulation
2388
2741
  }
2389
2742
  ),
2390
- svgObjectUrl ? /* @__PURE__ */ jsx8(
2743
+ svgObjectUrl ? /* @__PURE__ */ jsx9(
2391
2744
  "img",
2392
2745
  {
2393
2746
  ref: imgRef,
@@ -2401,7 +2754,7 @@ var AnalogSimulationViewer = ({
2401
2754
  objectFit: "contain"
2402
2755
  }
2403
2756
  }
2404
- ) : /* @__PURE__ */ jsx8(
2757
+ ) : /* @__PURE__ */ jsx9(
2405
2758
  "div",
2406
2759
  {
2407
2760
  style: {