@tscircuit/schematic-viewer 2.0.49 → 2.0.51

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/bun.lockb CHANGED
Binary file
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@ import { ManualEditEvent } from '@tscircuit/props';
4
4
  import { CircuitJson } from 'circuit-json';
5
5
  import { ReactNode } from 'react';
6
6
 
7
- interface Props {
7
+ interface Props$1 {
8
8
  circuitJson: CircuitJson;
9
9
  containerStyle?: React.CSSProperties;
10
10
  editEvents?: ManualEditEvent[];
@@ -22,7 +22,7 @@ interface Props {
22
22
  event: MouseEvent;
23
23
  }) => void;
24
24
  }
25
- declare const SchematicViewer: ({ circuitJson, containerStyle, editEvents: unappliedEditEvents, onEditEvent, defaultEditMode, debugGrid, editingEnabled, debug, clickToInteractEnabled, colorOverrides, spiceSimulationEnabled, disableGroups, onSchematicComponentClicked, }: Props) => react_jsx_runtime.JSX.Element;
25
+ declare const SchematicViewer: ({ circuitJson, containerStyle, editEvents: unappliedEditEvents, onEditEvent, defaultEditMode, debugGrid, editingEnabled, debug, clickToInteractEnabled, colorOverrides, spiceSimulationEnabled, disableGroups, onSchematicComponentClicked, }: Props$1) => react_jsx_runtime.JSX.Element;
26
26
 
27
27
  interface BoundingBoxBounds {
28
28
  minX: number;
@@ -42,4 +42,14 @@ declare const useMouseEventsOverBoundingBox: (options: UseMouseEventsOverBoundin
42
42
  hovering: boolean;
43
43
  };
44
44
 
45
- export { MouseTracker, SchematicViewer, useMouseEventsOverBoundingBox };
45
+ interface Props {
46
+ circuitJson: CircuitJson;
47
+ containerStyle?: React.CSSProperties;
48
+ colorOverrides?: ColorOverrides;
49
+ width?: number;
50
+ height?: number;
51
+ className?: string;
52
+ }
53
+ declare const AnalogSimulationViewer: ({ circuitJson: inputCircuitJson, containerStyle, colorOverrides, width, height, className, }: Props) => react_jsx_runtime.JSX.Element;
54
+
55
+ export { AnalogSimulationViewer, MouseTracker, SchematicViewer, useMouseEventsOverBoundingBox };
package/dist/index.js CHANGED
@@ -851,7 +851,7 @@ import { su as su5 } from "@tscircuit/soup-util";
851
851
  // package.json
852
852
  var package_default = {
853
853
  name: "@tscircuit/schematic-viewer",
854
- version: "2.0.48",
854
+ version: "2.0.50",
855
855
  main: "dist/index.js",
856
856
  type: "module",
857
857
  scripts: {
@@ -878,7 +878,7 @@ var package_default = {
878
878
  "react-dom": "^19.1.0",
879
879
  "react-reconciler": "^0.31.0",
880
880
  semver: "^7.7.2",
881
- tscircuit: "^0.0.611",
881
+ tscircuit: "^0.0.1037",
882
882
  tsup: "^8.3.5",
883
883
  vite: "^6.0.3"
884
884
  },
@@ -888,7 +888,7 @@ var package_default = {
888
888
  },
889
889
  dependencies: {
890
890
  "chart.js": "^4.5.0",
891
- "circuit-json-to-spice": "^0.0.10",
891
+ "circuit-json-to-spice": "^0.0.30",
892
892
  debug: "^4.4.0",
893
893
  "performance-now": "^2.1.0",
894
894
  "react-chartjs-2": "^5.3.0",
@@ -2545,7 +2545,267 @@ var SchematicViewer = ({
2545
2545
  )
2546
2546
  ] });
2547
2547
  };
2548
+
2549
+ // lib/components/AnalogSimulationViewer.tsx
2550
+ import {
2551
+ convertCircuitJsonToSchematicSimulationSvg
2552
+ } from "circuit-to-svg";
2553
+ import { useEffect as useEffect12, useState as useState7, useMemo as useMemo6, useRef as useRef8 } from "react";
2554
+ import { useMouseMatrixTransform as useMouseMatrixTransform2 } from "use-mouse-matrix-transform";
2555
+ import { toString as transformToString2 } from "transformation-matrix";
2556
+ import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
2557
+ var AnalogSimulationViewer = ({
2558
+ circuitJson: inputCircuitJson,
2559
+ containerStyle,
2560
+ colorOverrides,
2561
+ width,
2562
+ height,
2563
+ className
2564
+ }) => {
2565
+ const [circuitJson, setCircuitJson] = useState7(null);
2566
+ const [isLoading, setIsLoading] = useState7(true);
2567
+ const [error, setError] = useState7(null);
2568
+ const [svgObjectUrl, setSvgObjectUrl] = useState7(null);
2569
+ const containerRef = useRef8(null);
2570
+ const imgRef = useRef8(null);
2571
+ const { containerWidth, containerHeight } = useResizeHandling(
2572
+ containerRef
2573
+ );
2574
+ const [isDragging, setIsDragging] = useState7(false);
2575
+ const {
2576
+ ref: transformRef,
2577
+ cancelDrag: _cancelDrag,
2578
+ transform: _svgToScreenProjection
2579
+ } = useMouseMatrixTransform2({
2580
+ onSetTransform(transform) {
2581
+ if (imgRef.current) {
2582
+ imgRef.current.style.transform = transformToString2(transform);
2583
+ }
2584
+ }
2585
+ });
2586
+ const effectiveWidth = width || containerWidth || 1e3;
2587
+ const effectiveHeight = height || containerHeight || 600;
2588
+ useEffect12(() => {
2589
+ setIsLoading(true);
2590
+ setError(null);
2591
+ setCircuitJson(inputCircuitJson);
2592
+ setIsLoading(false);
2593
+ }, [inputCircuitJson]);
2594
+ const simulationExperimentId = useMemo6(() => {
2595
+ if (!circuitJson) return null;
2596
+ const simulationElement = circuitJson.find(
2597
+ (el) => el.type === "simulation_experiment"
2598
+ );
2599
+ return simulationElement?.simulation_experiment_id || null;
2600
+ }, [circuitJson]);
2601
+ const simulationGraphIds = useMemo6(() => {
2602
+ if (!circuitJson) return [];
2603
+ return circuitJson.filter((el) => el.type === "simulation_transient_voltage_graph").map((el) => el.simulation_transient_voltage_graph_id);
2604
+ }, [circuitJson]);
2605
+ const simulationSvg = useMemo6(() => {
2606
+ if (!circuitJson || !effectiveWidth || !effectiveHeight || !simulationExperimentId)
2607
+ return "";
2608
+ try {
2609
+ return convertCircuitJsonToSchematicSimulationSvg({
2610
+ circuitJson,
2611
+ simulation_experiment_id: simulationExperimentId,
2612
+ simulation_transient_voltage_graph_ids: simulationGraphIds,
2613
+ width: effectiveWidth,
2614
+ height: effectiveHeight,
2615
+ schematicOptions: { colorOverrides }
2616
+ });
2617
+ } catch (fallbackErr) {
2618
+ console.error("Failed to generate fallback schematic SVG:", fallbackErr);
2619
+ return "";
2620
+ }
2621
+ }, [
2622
+ circuitJson,
2623
+ effectiveWidth,
2624
+ effectiveHeight,
2625
+ colorOverrides,
2626
+ simulationExperimentId,
2627
+ simulationGraphIds
2628
+ ]);
2629
+ useEffect12(() => {
2630
+ if (!simulationSvg) {
2631
+ setSvgObjectUrl(null);
2632
+ return;
2633
+ }
2634
+ try {
2635
+ const blob = new Blob([simulationSvg], { type: "image/svg+xml" });
2636
+ const url = URL.createObjectURL(blob);
2637
+ setSvgObjectUrl(url);
2638
+ return () => {
2639
+ URL.revokeObjectURL(url);
2640
+ };
2641
+ } catch (error2) {
2642
+ console.error("Failed to create SVG object URL:", error2);
2643
+ setSvgObjectUrl(null);
2644
+ }
2645
+ }, [simulationSvg]);
2646
+ const containerBackgroundColor = useMemo6(() => {
2647
+ if (!simulationSvg) return "transparent";
2648
+ const match = simulationSvg.match(
2649
+ /<svg[^>]*style="[^"]*background-color:\s*([^;\"]+)/i
2650
+ );
2651
+ return match?.[1] ?? "transparent";
2652
+ }, [simulationSvg]);
2653
+ const handleMouseDown = (_e) => {
2654
+ setIsDragging(true);
2655
+ };
2656
+ const handleTouchStart = (_e) => {
2657
+ setIsDragging(true);
2658
+ };
2659
+ useEffect12(() => {
2660
+ const handleMouseUp = () => {
2661
+ setIsDragging(false);
2662
+ };
2663
+ const handleTouchEnd = () => {
2664
+ setIsDragging(false);
2665
+ };
2666
+ window.addEventListener("mouseup", handleMouseUp);
2667
+ window.addEventListener("touchend", handleTouchEnd);
2668
+ return () => {
2669
+ window.removeEventListener("mouseup", handleMouseUp);
2670
+ window.removeEventListener("touchend", handleTouchEnd);
2671
+ };
2672
+ }, []);
2673
+ if (isLoading) {
2674
+ return /* @__PURE__ */ jsx12(
2675
+ "div",
2676
+ {
2677
+ style: {
2678
+ display: "flex",
2679
+ alignItems: "center",
2680
+ justifyContent: "center",
2681
+ backgroundColor: "#f5f5f5",
2682
+ minHeight: "300px",
2683
+ fontFamily: "sans-serif",
2684
+ fontSize: "16px",
2685
+ color: "#666",
2686
+ ...containerStyle
2687
+ },
2688
+ className,
2689
+ children: "Loading circuit..."
2690
+ }
2691
+ );
2692
+ }
2693
+ if (error) {
2694
+ return /* @__PURE__ */ jsx12(
2695
+ "div",
2696
+ {
2697
+ style: {
2698
+ display: "flex",
2699
+ alignItems: "center",
2700
+ justifyContent: "center",
2701
+ backgroundColor: "#fef2f2",
2702
+ minHeight: "300px",
2703
+ fontFamily: "sans-serif",
2704
+ fontSize: "16px",
2705
+ color: "#dc2626",
2706
+ ...containerStyle
2707
+ },
2708
+ className,
2709
+ children: /* @__PURE__ */ jsxs7("div", { style: { textAlign: "center", padding: "20px" }, children: [
2710
+ /* @__PURE__ */ jsx12("div", { style: { fontWeight: "bold", marginBottom: "8px" }, children: "Circuit Conversion Error" }),
2711
+ /* @__PURE__ */ jsx12("div", { style: { fontSize: "14px" }, children: error })
2712
+ ] })
2713
+ }
2714
+ );
2715
+ }
2716
+ if (!simulationSvg) {
2717
+ return /* @__PURE__ */ jsxs7(
2718
+ "div",
2719
+ {
2720
+ style: {
2721
+ display: "flex",
2722
+ flexDirection: "column",
2723
+ alignItems: "center",
2724
+ justifyContent: "center",
2725
+ backgroundColor: "#f8fafc",
2726
+ minHeight: "300px",
2727
+ fontFamily: "sans-serif",
2728
+ gap: "12px",
2729
+ ...containerStyle
2730
+ },
2731
+ className,
2732
+ children: [
2733
+ /* @__PURE__ */ jsx12("div", { style: { fontSize: "16px", color: "#475569", fontWeight: 500 }, children: "No Simulation Found" }),
2734
+ /* @__PURE__ */ jsxs7("div", { style: { fontSize: "14px", color: "#64748b" }, children: [
2735
+ "Use",
2736
+ " ",
2737
+ /* @__PURE__ */ jsx12(
2738
+ "code",
2739
+ {
2740
+ style: {
2741
+ backgroundColor: "#e2e8f0",
2742
+ padding: "2px 6px",
2743
+ borderRadius: "4px",
2744
+ fontFamily: "monospace",
2745
+ fontSize: "13px"
2746
+ },
2747
+ children: "<analogsimulation />"
2748
+ }
2749
+ ),
2750
+ " ",
2751
+ "to create simulations"
2752
+ ] })
2753
+ ]
2754
+ }
2755
+ );
2756
+ }
2757
+ return /* @__PURE__ */ jsx12(
2758
+ "div",
2759
+ {
2760
+ ref: (node) => {
2761
+ containerRef.current = node;
2762
+ transformRef.current = node;
2763
+ },
2764
+ style: {
2765
+ position: "relative",
2766
+ backgroundColor: containerBackgroundColor,
2767
+ overflow: "hidden",
2768
+ minHeight: "300px",
2769
+ cursor: isDragging ? "grabbing" : "grab",
2770
+ ...containerStyle
2771
+ },
2772
+ className,
2773
+ onMouseDown: handleMouseDown,
2774
+ onTouchStart: handleTouchStart,
2775
+ children: svgObjectUrl ? /* @__PURE__ */ jsx12(
2776
+ "img",
2777
+ {
2778
+ ref: imgRef,
2779
+ src: svgObjectUrl,
2780
+ alt: "Circuit Simulation",
2781
+ style: {
2782
+ transformOrigin: "0 0",
2783
+ width: "100%",
2784
+ height: "100%",
2785
+ display: "block",
2786
+ objectFit: "contain"
2787
+ }
2788
+ }
2789
+ ) : /* @__PURE__ */ jsx12(
2790
+ "div",
2791
+ {
2792
+ style: {
2793
+ display: "flex",
2794
+ alignItems: "center",
2795
+ justifyContent: "center",
2796
+ height: "100%",
2797
+ minHeight: "300px",
2798
+ color: "#666",
2799
+ fontFamily: "sans-serif"
2800
+ },
2801
+ children: "Failed to render SVG"
2802
+ }
2803
+ )
2804
+ }
2805
+ );
2806
+ };
2548
2807
  export {
2808
+ AnalogSimulationViewer,
2549
2809
  MouseTracker,
2550
2810
  SchematicViewer,
2551
2811
  useMouseEventsOverBoundingBox