@tscircuit/schematic-viewer 2.0.48 → 2.0.50
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 +0 -0
- package/dist/index.d.ts +13 -3
- package/dist/index.js +246 -3
- package/dist/index.js.map +1 -1
- package/examples/example15-analog-simulation-viewer.fixture.tsx +145 -0
- package/lib/components/AnalogSimulationViewer.tsx +283 -0
- package/lib/components/EditIcon.tsx +1 -0
- package/lib/components/GridIcon.tsx +1 -0
- package/lib/components/SpicePlot.tsx +1 -1
- package/lib/components/SpiceSimulationIcon.tsx +1 -0
- package/lib/components/ViewMenu.tsx +1 -1
- package/lib/components/ViewMenuIcon.tsx +1 -0
- package/lib/hooks/useChangeSchematicTracesForMovedComponents.ts +2 -2
- package/lib/hooks/useSchematicGroupsOverlay.ts +1 -1
- package/lib/index.ts +1 -0
- package/package.json +3 -3
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
|
-
|
|
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
|
@@ -711,6 +711,7 @@ var EditIcon = ({
|
|
|
711
711
|
{
|
|
712
712
|
onClick: handleInteraction,
|
|
713
713
|
onTouchEnd: handleInteraction,
|
|
714
|
+
title: active ? "Disable edit mode" : "Enable edit mode",
|
|
714
715
|
style: {
|
|
715
716
|
position: "absolute",
|
|
716
717
|
top: "16px",
|
|
@@ -760,6 +761,7 @@ var GridIcon = ({
|
|
|
760
761
|
{
|
|
761
762
|
onClick: handleInteraction,
|
|
762
763
|
onTouchEnd: handleInteraction,
|
|
764
|
+
title: active ? "Hide grid" : "Show grid",
|
|
763
765
|
style: {
|
|
764
766
|
position: "absolute",
|
|
765
767
|
top: "56px",
|
|
@@ -806,6 +808,7 @@ var ViewMenuIcon = ({
|
|
|
806
808
|
{
|
|
807
809
|
onClick: handleInteraction,
|
|
808
810
|
onTouchEnd: handleInteraction,
|
|
811
|
+
title: active ? "Hide view menu" : "Show view menu",
|
|
809
812
|
style: {
|
|
810
813
|
position: "absolute",
|
|
811
814
|
top: "16px",
|
|
@@ -848,7 +851,7 @@ import { su as su5 } from "@tscircuit/soup-util";
|
|
|
848
851
|
// package.json
|
|
849
852
|
var package_default = {
|
|
850
853
|
name: "@tscircuit/schematic-viewer",
|
|
851
|
-
version: "2.0.
|
|
854
|
+
version: "2.0.49",
|
|
852
855
|
main: "dist/index.js",
|
|
853
856
|
type: "module",
|
|
854
857
|
scripts: {
|
|
@@ -875,7 +878,7 @@ var package_default = {
|
|
|
875
878
|
"react-dom": "^19.1.0",
|
|
876
879
|
"react-reconciler": "^0.31.0",
|
|
877
880
|
semver: "^7.7.2",
|
|
878
|
-
tscircuit: "^0.0.
|
|
881
|
+
tscircuit: "^0.0.1037",
|
|
879
882
|
tsup: "^8.3.5",
|
|
880
883
|
vite: "^6.0.3"
|
|
881
884
|
},
|
|
@@ -885,7 +888,7 @@ var package_default = {
|
|
|
885
888
|
},
|
|
886
889
|
dependencies: {
|
|
887
890
|
"chart.js": "^4.5.0",
|
|
888
|
-
"circuit-json-to-spice": "^0.0.
|
|
891
|
+
"circuit-json-to-spice": "^0.0.30",
|
|
889
892
|
debug: "^4.4.0",
|
|
890
893
|
"performance-now": "^2.1.0",
|
|
891
894
|
"react-chartjs-2": "^5.3.0",
|
|
@@ -1079,6 +1082,7 @@ var SpiceSimulationIcon = ({
|
|
|
1079
1082
|
"div",
|
|
1080
1083
|
{
|
|
1081
1084
|
onClick,
|
|
1085
|
+
title: "Run SPICE simulation",
|
|
1082
1086
|
style: {
|
|
1083
1087
|
position: "absolute",
|
|
1084
1088
|
top: "16px",
|
|
@@ -2541,7 +2545,246 @@ var SchematicViewer = ({
|
|
|
2541
2545
|
)
|
|
2542
2546
|
] });
|
|
2543
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__ */ jsx12(
|
|
2718
|
+
"div",
|
|
2719
|
+
{
|
|
2720
|
+
style: {
|
|
2721
|
+
display: "flex",
|
|
2722
|
+
alignItems: "center",
|
|
2723
|
+
justifyContent: "center",
|
|
2724
|
+
backgroundColor: "#fef2f2",
|
|
2725
|
+
minHeight: "300px",
|
|
2726
|
+
fontFamily: "sans-serif",
|
|
2727
|
+
fontSize: "16px",
|
|
2728
|
+
color: "#dc2626",
|
|
2729
|
+
...containerStyle
|
|
2730
|
+
},
|
|
2731
|
+
className,
|
|
2732
|
+
children: "Failed to generate simulation SVG"
|
|
2733
|
+
}
|
|
2734
|
+
);
|
|
2735
|
+
}
|
|
2736
|
+
return /* @__PURE__ */ jsx12(
|
|
2737
|
+
"div",
|
|
2738
|
+
{
|
|
2739
|
+
ref: (node) => {
|
|
2740
|
+
containerRef.current = node;
|
|
2741
|
+
transformRef.current = node;
|
|
2742
|
+
},
|
|
2743
|
+
style: {
|
|
2744
|
+
position: "relative",
|
|
2745
|
+
backgroundColor: containerBackgroundColor,
|
|
2746
|
+
overflow: "hidden",
|
|
2747
|
+
minHeight: "300px",
|
|
2748
|
+
cursor: isDragging ? "grabbing" : "grab",
|
|
2749
|
+
...containerStyle
|
|
2750
|
+
},
|
|
2751
|
+
className,
|
|
2752
|
+
onMouseDown: handleMouseDown,
|
|
2753
|
+
onTouchStart: handleTouchStart,
|
|
2754
|
+
children: svgObjectUrl ? /* @__PURE__ */ jsx12(
|
|
2755
|
+
"img",
|
|
2756
|
+
{
|
|
2757
|
+
ref: imgRef,
|
|
2758
|
+
src: svgObjectUrl,
|
|
2759
|
+
alt: "Circuit Simulation",
|
|
2760
|
+
style: {
|
|
2761
|
+
transformOrigin: "0 0",
|
|
2762
|
+
width: "100%",
|
|
2763
|
+
height: "100%",
|
|
2764
|
+
display: "block",
|
|
2765
|
+
objectFit: "contain"
|
|
2766
|
+
}
|
|
2767
|
+
}
|
|
2768
|
+
) : /* @__PURE__ */ jsx12(
|
|
2769
|
+
"div",
|
|
2770
|
+
{
|
|
2771
|
+
style: {
|
|
2772
|
+
display: "flex",
|
|
2773
|
+
alignItems: "center",
|
|
2774
|
+
justifyContent: "center",
|
|
2775
|
+
height: "100%",
|
|
2776
|
+
minHeight: "300px",
|
|
2777
|
+
color: "#666",
|
|
2778
|
+
fontFamily: "sans-serif"
|
|
2779
|
+
},
|
|
2780
|
+
children: "Failed to render SVG"
|
|
2781
|
+
}
|
|
2782
|
+
)
|
|
2783
|
+
}
|
|
2784
|
+
);
|
|
2785
|
+
};
|
|
2544
2786
|
export {
|
|
2787
|
+
AnalogSimulationViewer,
|
|
2545
2788
|
MouseTracker,
|
|
2546
2789
|
SchematicViewer,
|
|
2547
2790
|
useMouseEventsOverBoundingBox
|