@tscircuit/schematic-viewer 2.0.77 → 2.0.79
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.d.ts +2 -7
- package/dist/index.js +602 -1020
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -1,201 +1,51 @@
|
|
|
1
1
|
// lib/components/SchematicViewer.tsx
|
|
2
|
+
import { su as su4 } from "@tscircuit/soup-util";
|
|
2
3
|
import {
|
|
3
4
|
convertCircuitJsonToSchematicSvg
|
|
4
5
|
} from "circuit-to-svg";
|
|
5
|
-
import { su as su7 } from "@tscircuit/soup-util";
|
|
6
|
-
|
|
7
|
-
// lib/hooks/useChangeSchematicComponentLocationsInSvg.ts
|
|
8
|
-
import "@tscircuit/soup-util";
|
|
9
|
-
import "transformation-matrix";
|
|
10
|
-
import { useEffect, useRef } from "react";
|
|
11
6
|
|
|
12
|
-
// lib/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
(event) => "schematic_component_id" in event && event.schematic_component_id === schematic_component_id
|
|
19
|
-
).filter(
|
|
20
|
-
(event) => "edit_event_type" in event && event.edit_event_type === "edit_schematic_component_location"
|
|
21
|
-
);
|
|
22
|
-
const totalOffsetX = editEventsForComponent.reduce((acc, event) => {
|
|
23
|
-
return acc + event.new_center.x - event.original_center.x;
|
|
24
|
-
}, 0);
|
|
25
|
-
const totalOffsetY = editEventsForComponent.reduce((acc, event) => {
|
|
26
|
-
return acc + event.new_center.y - event.original_center.y;
|
|
27
|
-
}, 0);
|
|
28
|
-
return {
|
|
29
|
-
x: totalOffsetX,
|
|
30
|
-
y: totalOffsetY
|
|
31
|
-
};
|
|
7
|
+
// lib/hooks/useLocalStorage.ts
|
|
8
|
+
import { useCallback } from "react";
|
|
9
|
+
var STORAGE_KEYS = {
|
|
10
|
+
IS_SHOWING_SCHEMATIC_GROUPS: "schematic_viewer_show_groups",
|
|
11
|
+
IS_SHOWING_SCHEMATIC_PORTS: "schematic_viewer_show_ports",
|
|
12
|
+
SELECTED_SCHEMATIC_SHEET: "schematic_viewer_selected_sheet"
|
|
32
13
|
};
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}) => {
|
|
42
|
-
const lastSvgContentRef = useRef(null);
|
|
43
|
-
useEffect(() => {
|
|
44
|
-
const svg = svgDivRef.current;
|
|
45
|
-
if (!svg) return;
|
|
46
|
-
const observer = new MutationObserver((mutations) => {
|
|
47
|
-
const currentSvgContent = svg.innerHTML;
|
|
48
|
-
if (currentSvgContent !== lastSvgContentRef.current) {
|
|
49
|
-
lastSvgContentRef.current = currentSvgContent;
|
|
50
|
-
applyTransforms();
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
const applyTransforms = () => {
|
|
54
|
-
const componentsThatHaveBeenMoved = /* @__PURE__ */ new Set();
|
|
55
|
-
for (const event of editEvents) {
|
|
56
|
-
if ("edit_event_type" in event && event.edit_event_type === "edit_schematic_component_location") {
|
|
57
|
-
componentsThatHaveBeenMoved.add(event.schematic_component_id);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
if (activeEditEvent) {
|
|
61
|
-
componentsThatHaveBeenMoved.add(activeEditEvent.schematic_component_id);
|
|
62
|
-
}
|
|
63
|
-
const allComponents = svg.querySelectorAll(
|
|
64
|
-
'[data-circuit-json-type="schematic_component"]'
|
|
65
|
-
);
|
|
66
|
-
for (const component of Array.from(allComponents)) {
|
|
67
|
-
const schematic_component_id = component.getAttribute(
|
|
68
|
-
"data-schematic-component-id"
|
|
69
|
-
);
|
|
70
|
-
const offsetMm = getComponentOffsetDueToEvents({
|
|
71
|
-
editEvents: [
|
|
72
|
-
...editEvents,
|
|
73
|
-
...activeEditEvent ? [activeEditEvent] : []
|
|
74
|
-
],
|
|
75
|
-
schematic_component_id
|
|
76
|
-
});
|
|
77
|
-
const offsetPx = {
|
|
78
|
-
x: offsetMm.x * realToSvgProjection.a,
|
|
79
|
-
y: offsetMm.y * realToSvgProjection.d
|
|
80
|
-
};
|
|
81
|
-
const style = component.style;
|
|
82
|
-
style.transform = `translate(${offsetPx.x}px, ${offsetPx.y}px)`;
|
|
83
|
-
if (activeEditEvent?.schematic_component_id === schematic_component_id) {
|
|
84
|
-
style.outline = "solid 2px rgba(255,0,0,0.5)";
|
|
85
|
-
style.outlineOffset = "5px";
|
|
86
|
-
} else if (style.outline) {
|
|
87
|
-
style.outline = "";
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
observer.observe(svg, {
|
|
92
|
-
childList: true,
|
|
93
|
-
// Watch for changes to the child elements
|
|
94
|
-
subtree: false,
|
|
95
|
-
// Watch for changes in the entire subtree
|
|
96
|
-
characterData: false
|
|
97
|
-
// Watch for changes to text content
|
|
98
|
-
});
|
|
99
|
-
applyTransforms();
|
|
100
|
-
return () => {
|
|
101
|
-
observer.disconnect();
|
|
102
|
-
};
|
|
103
|
-
}, [svgDivRef, editEvents, activeEditEvent]);
|
|
14
|
+
var getStoredBoolean = (key, defaultValue) => {
|
|
15
|
+
if (typeof window === "undefined") return defaultValue;
|
|
16
|
+
try {
|
|
17
|
+
const stored = localStorage.getItem(key);
|
|
18
|
+
return stored !== null ? JSON.parse(stored) : defaultValue;
|
|
19
|
+
} catch {
|
|
20
|
+
return defaultValue;
|
|
21
|
+
}
|
|
104
22
|
};
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
for (const editEvent of [
|
|
128
|
-
...editEvents,
|
|
129
|
-
...activeEditEvent ? [activeEditEvent] : []
|
|
130
|
-
]) {
|
|
131
|
-
if ("schematic_component_id" in editEvent && editEvent.edit_event_type === "edit_schematic_component_location") {
|
|
132
|
-
const sch_component = su2(circuitJson).schematic_component.get(
|
|
133
|
-
editEvent.schematic_component_id
|
|
134
|
-
);
|
|
135
|
-
if (!sch_component) return;
|
|
136
|
-
const src_ports = su2(circuitJson).source_port.list({
|
|
137
|
-
source_component_id: sch_component.source_component_id
|
|
138
|
-
});
|
|
139
|
-
const src_port_ids = new Set(src_ports.map((sp) => sp.source_port_id));
|
|
140
|
-
const src_traces = su2(circuitJson).source_trace.list().filter(
|
|
141
|
-
(st) => st.connected_source_port_ids?.some(
|
|
142
|
-
(spi) => src_port_ids.has(spi)
|
|
143
|
-
)
|
|
144
|
-
);
|
|
145
|
-
const src_trace_ids = new Set(
|
|
146
|
-
src_traces.map((st) => st.source_trace_id)
|
|
147
|
-
);
|
|
148
|
-
const schematic_traces = su2(circuitJson).schematic_trace.list().filter((st) => src_trace_ids.has(st.source_trace_id));
|
|
149
|
-
schematic_traces.forEach((trace) => {
|
|
150
|
-
const traceElements = svg.querySelectorAll(
|
|
151
|
-
`[data-schematic-trace-id="${trace.schematic_trace_id}"] path`
|
|
152
|
-
);
|
|
153
|
-
for (const traceElement of Array.from(traceElements)) {
|
|
154
|
-
if (traceElement.getAttribute("class")?.includes("invisible"))
|
|
155
|
-
continue;
|
|
156
|
-
traceElement.setAttribute("stroke-dasharray", "20,20");
|
|
157
|
-
traceElement.style.animation = "dash-animation 350ms linear infinite, pulse-animation 900ms linear infinite";
|
|
158
|
-
if (!svg.querySelector("style#dash-animation")) {
|
|
159
|
-
const style = document.createElement("style");
|
|
160
|
-
style.id = "dash-animation";
|
|
161
|
-
style.textContent = `
|
|
162
|
-
@keyframes dash-animation {
|
|
163
|
-
to {
|
|
164
|
-
stroke-dashoffset: -40;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
@keyframes pulse-animation {
|
|
168
|
-
0% { opacity: 0.6; }
|
|
169
|
-
50% { opacity: 0.2; }
|
|
170
|
-
100% { opacity: 0.6; }
|
|
171
|
-
}
|
|
172
|
-
`;
|
|
173
|
-
svg.appendChild(style);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
};
|
|
180
|
-
updateTraceStyles();
|
|
181
|
-
const observer = new MutationObserver(updateTraceStyles);
|
|
182
|
-
observer.observe(svg, {
|
|
183
|
-
childList: true,
|
|
184
|
-
// Watch for changes to the child elements
|
|
185
|
-
subtree: false,
|
|
186
|
-
// Watch for changes in the entire subtree
|
|
187
|
-
characterData: false
|
|
188
|
-
// Watch for changes to text content
|
|
189
|
-
});
|
|
190
|
-
return () => {
|
|
191
|
-
observer.disconnect();
|
|
192
|
-
};
|
|
193
|
-
}, [svgDivRef, activeEditEvent, circuitJson, editEvents]);
|
|
23
|
+
var setStoredBoolean = (key, value) => {
|
|
24
|
+
if (typeof window === "undefined") return;
|
|
25
|
+
try {
|
|
26
|
+
localStorage.setItem(key, JSON.stringify(value));
|
|
27
|
+
} catch {
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
var getStoredString = (key) => {
|
|
31
|
+
if (typeof window === "undefined") return null;
|
|
32
|
+
try {
|
|
33
|
+
return localStorage.getItem(key);
|
|
34
|
+
} catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
var setStoredString = (key, value) => {
|
|
39
|
+
if (typeof window === "undefined") return;
|
|
40
|
+
try {
|
|
41
|
+
localStorage.setItem(key, value);
|
|
42
|
+
} catch {
|
|
43
|
+
}
|
|
194
44
|
};
|
|
195
45
|
|
|
196
46
|
// lib/hooks/useSchematicGroupsOverlay.ts
|
|
197
|
-
import { useEffect
|
|
198
|
-
import { su
|
|
47
|
+
import { useEffect } from "react";
|
|
48
|
+
import { su } from "@tscircuit/soup-util";
|
|
199
49
|
var GROUP_COLORS = [
|
|
200
50
|
"#8B0000",
|
|
201
51
|
// Dark Red
|
|
@@ -220,7 +70,7 @@ var GROUP_COLORS = [
|
|
|
220
70
|
];
|
|
221
71
|
var useSchematicGroupsOverlay = (options) => {
|
|
222
72
|
const { svgDivRef, circuitJson, circuitJsonKey, showGroups } = options;
|
|
223
|
-
|
|
73
|
+
useEffect(() => {
|
|
224
74
|
if (svgDivRef.current) {
|
|
225
75
|
const existingOverlays = svgDivRef.current.querySelectorAll(
|
|
226
76
|
".schematic-group-overlay"
|
|
@@ -239,8 +89,8 @@ var useSchematicGroupsOverlay = (options) => {
|
|
|
239
89
|
const existingOverlays = svg.querySelectorAll(".schematic-group-overlay");
|
|
240
90
|
existingOverlays.forEach((overlay) => overlay.remove());
|
|
241
91
|
try {
|
|
242
|
-
const sourceGroups =
|
|
243
|
-
const schematicComponents =
|
|
92
|
+
const sourceGroups = su(circuitJson).source_group?.list().filter((x) => !!!x.is_subcircuit) || [];
|
|
93
|
+
const schematicComponents = su(circuitJson).schematic_component?.list() || [];
|
|
244
94
|
const sourceGroupHierarchy = /* @__PURE__ */ new Map();
|
|
245
95
|
sourceGroups.forEach((group) => {
|
|
246
96
|
const groupWithParent = group;
|
|
@@ -278,7 +128,7 @@ var useSchematicGroupsOverlay = (options) => {
|
|
|
278
128
|
if (hasMeaningfulGroups) {
|
|
279
129
|
const groupMap = /* @__PURE__ */ new Map();
|
|
280
130
|
for (const comp of schematicComponents) {
|
|
281
|
-
const sourceComp =
|
|
131
|
+
const sourceComp = su(circuitJson).source_component.get(
|
|
282
132
|
comp.source_component_id
|
|
283
133
|
);
|
|
284
134
|
if (sourceComp?.source_group_id) {
|
|
@@ -462,8 +312,8 @@ function calculateGroupBounds(components, svg) {
|
|
|
462
312
|
}
|
|
463
313
|
|
|
464
314
|
// lib/hooks/useSchematicNetHover.ts
|
|
465
|
-
import { su as
|
|
466
|
-
import { useEffect as
|
|
315
|
+
import { su as su2 } from "@tscircuit/soup-util";
|
|
316
|
+
import { useEffect as useEffect2 } from "react";
|
|
467
317
|
var FADED_CLASS = "sch-net-faded";
|
|
468
318
|
var TRACE_SELECTOR = "g.trace[data-subcircuit-connectivity-map-key], g.trace-overlays[data-subcircuit-connectivity-map-key]";
|
|
469
319
|
var NET_LABEL_SELECTOR = "[data-schematic-net-label-id]";
|
|
@@ -473,7 +323,7 @@ var useSchematicNetHover = ({
|
|
|
473
323
|
circuitJsonKey,
|
|
474
324
|
enabled
|
|
475
325
|
}) => {
|
|
476
|
-
|
|
326
|
+
useEffect2(() => {
|
|
477
327
|
const svgDiv = svgDivRef.current;
|
|
478
328
|
if (!enabled || !svgDiv) return;
|
|
479
329
|
const { componentIdToKeys, netLabelIdToKey } = buildNetRegistry(circuitJson);
|
|
@@ -549,7 +399,7 @@ var useSchematicNetHover = ({
|
|
|
549
399
|
}, [svgDivRef, circuitJsonKey, enabled]);
|
|
550
400
|
};
|
|
551
401
|
function buildNetRegistry(circuitJson) {
|
|
552
|
-
const cju =
|
|
402
|
+
const cju = su2(circuitJson);
|
|
553
403
|
const srcCompToSchComp = /* @__PURE__ */ new Map();
|
|
554
404
|
for (const c of cju.schematic_component.list()) {
|
|
555
405
|
if (c.source_component_id) {
|
|
@@ -586,23 +436,18 @@ var debug = Debug("schematic-viewer");
|
|
|
586
436
|
var enableDebug = () => {
|
|
587
437
|
Debug.enable("schematic-viewer*");
|
|
588
438
|
};
|
|
589
|
-
var debug_default = debug;
|
|
590
439
|
|
|
591
440
|
// lib/components/SchematicViewer.tsx
|
|
592
|
-
import { useCallback as useCallback6, useEffect as
|
|
593
|
-
import {
|
|
594
|
-
fromString,
|
|
595
|
-
identity,
|
|
596
|
-
toString as transformToString
|
|
597
|
-
} from "transformation-matrix";
|
|
441
|
+
import { useCallback as useCallback6, useEffect as useEffect9, useMemo as useMemo4, useRef as useRef6, useState as useState6 } from "react";
|
|
442
|
+
import { toString as transformToString } from "transformation-matrix";
|
|
598
443
|
import { useMouseMatrixTransform } from "use-mouse-matrix-transform";
|
|
599
444
|
|
|
600
445
|
// lib/hooks/use-resize-handling.ts
|
|
601
|
-
import { useEffect as
|
|
446
|
+
import { useEffect as useEffect3, useState } from "react";
|
|
602
447
|
var useResizeHandling = (containerRef) => {
|
|
603
448
|
const [containerWidth, setContainerWidth] = useState(0);
|
|
604
449
|
const [containerHeight, setContainerHeight] = useState(0);
|
|
605
|
-
|
|
450
|
+
useEffect3(() => {
|
|
606
451
|
if (!containerRef.current) return;
|
|
607
452
|
const updateDimensions = () => {
|
|
608
453
|
const rect = containerRef.current?.getBoundingClientRect();
|
|
@@ -621,597 +466,123 @@ var useResizeHandling = (containerRef) => {
|
|
|
621
466
|
return { containerWidth, containerHeight };
|
|
622
467
|
};
|
|
623
468
|
|
|
624
|
-
// lib/hooks/
|
|
625
|
-
import {
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
var
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
const
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
}, [editEvents]);
|
|
658
|
-
const startDrag = useCallback(
|
|
659
|
-
(clientX, clientY, target) => {
|
|
660
|
-
if (!enabled) return false;
|
|
661
|
-
const componentGroup = target.closest(
|
|
662
|
-
'[data-circuit-json-type="schematic_component"]'
|
|
663
|
-
);
|
|
664
|
-
if (!componentGroup) return false;
|
|
665
|
-
const schematic_component_id = componentGroup.getAttribute(
|
|
666
|
-
"data-schematic-component-id"
|
|
667
|
-
);
|
|
668
|
-
if (!schematic_component_id) return false;
|
|
669
|
-
if (cancelDrag) cancelDrag();
|
|
670
|
-
const schematic_component = su5(circuitJson).schematic_component.get(
|
|
671
|
-
schematic_component_id
|
|
672
|
-
);
|
|
673
|
-
if (!schematic_component) return false;
|
|
674
|
-
dragStartPosRef.current = { x: clientX, y: clientY };
|
|
675
|
-
let current_position;
|
|
676
|
-
const trackedPosition = componentPositionsRef.current.get(
|
|
677
|
-
schematic_component_id
|
|
678
|
-
);
|
|
679
|
-
if (trackedPosition) {
|
|
680
|
-
current_position = { ...trackedPosition };
|
|
681
|
-
} else {
|
|
682
|
-
const editEventOffset = getComponentOffsetDueToEvents({
|
|
683
|
-
editEvents,
|
|
684
|
-
schematic_component_id
|
|
685
|
-
});
|
|
686
|
-
current_position = {
|
|
687
|
-
x: schematic_component.center.x + editEventOffset.x,
|
|
688
|
-
y: schematic_component.center.y + editEventOffset.y
|
|
689
|
-
};
|
|
690
|
-
componentPositionsRef.current.set(schematic_component_id, {
|
|
691
|
-
...current_position
|
|
692
|
-
});
|
|
469
|
+
// lib/hooks/useContextMenu.ts
|
|
470
|
+
import { useCallback as useCallback2, useEffect as useEffect4, useRef, useState as useState2 } from "react";
|
|
471
|
+
var LONG_PRESS_DURATION_MS = 600;
|
|
472
|
+
var MOVEMENT_THRESHOLD_PX = 10;
|
|
473
|
+
var useContextMenu = ({ containerRef }) => {
|
|
474
|
+
const [menuVisible, setMenuVisible] = useState2(false);
|
|
475
|
+
const [menuPos, setMenuPos] = useState2({ x: 0, y: 0 });
|
|
476
|
+
const menuRef = useRef(null);
|
|
477
|
+
const interactionOriginRef = useRef(null);
|
|
478
|
+
const longPressTimeoutRef = useRef(null);
|
|
479
|
+
const ignoreContextMenuUntilRef = useRef(0);
|
|
480
|
+
const clearLongPressTimeout = useCallback2(() => {
|
|
481
|
+
if (longPressTimeoutRef.current === null) return;
|
|
482
|
+
window.clearTimeout(longPressTimeoutRef.current);
|
|
483
|
+
longPressTimeoutRef.current = null;
|
|
484
|
+
}, []);
|
|
485
|
+
const handleContextMenu = useCallback2((event) => {
|
|
486
|
+
event.preventDefault();
|
|
487
|
+
if (Date.now() < ignoreContextMenuUntilRef.current) return;
|
|
488
|
+
const origin = interactionOriginRef.current;
|
|
489
|
+
if (!origin) return;
|
|
490
|
+
const movedTooFar = Math.abs(event.clientX - origin.x) > MOVEMENT_THRESHOLD_PX || Math.abs(event.clientY - origin.y) > MOVEMENT_THRESHOLD_PX;
|
|
491
|
+
interactionOriginRef.current = null;
|
|
492
|
+
if (movedTooFar) return;
|
|
493
|
+
setMenuPos({ x: event.clientX, y: event.clientY });
|
|
494
|
+
setMenuVisible(true);
|
|
495
|
+
}, []);
|
|
496
|
+
const handleTouchStart = useCallback2(
|
|
497
|
+
(event) => {
|
|
498
|
+
clearLongPressTimeout();
|
|
499
|
+
if (event.touches.length !== 1) {
|
|
500
|
+
interactionOriginRef.current = null;
|
|
501
|
+
return;
|
|
693
502
|
}
|
|
694
|
-
const
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
new_center: { ...current_position },
|
|
700
|
-
in_progress: true,
|
|
701
|
-
created_at: Date.now(),
|
|
702
|
-
_element: componentGroup
|
|
503
|
+
const touch = event.touches[0];
|
|
504
|
+
if (!touch) return;
|
|
505
|
+
interactionOriginRef.current = {
|
|
506
|
+
x: touch.clientX,
|
|
507
|
+
y: touch.clientY
|
|
703
508
|
};
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
const handleTouchStart = useCallback(
|
|
717
|
-
(e) => {
|
|
718
|
-
if (e.touches.length !== 1) return;
|
|
719
|
-
const touch = e.touches[0];
|
|
720
|
-
if (startDrag(touch.clientX, touch.clientY, e.target)) {
|
|
721
|
-
e.preventDefault();
|
|
722
|
-
}
|
|
509
|
+
longPressTimeoutRef.current = window.setTimeout(() => {
|
|
510
|
+
const container = containerRef.current;
|
|
511
|
+
if (!container || !interactionOriginRef.current) return;
|
|
512
|
+
const rect = container.getBoundingClientRect();
|
|
513
|
+
setMenuPos({
|
|
514
|
+
x: rect.left + rect.width / 2,
|
|
515
|
+
y: rect.top + rect.height / 2
|
|
516
|
+
});
|
|
517
|
+
setMenuVisible(true);
|
|
518
|
+
ignoreContextMenuUntilRef.current = Date.now() + 1e3;
|
|
519
|
+
interactionOriginRef.current = null;
|
|
520
|
+
}, LONG_PRESS_DURATION_MS);
|
|
723
521
|
},
|
|
724
|
-
[
|
|
522
|
+
[clearLongPressTimeout, containerRef]
|
|
725
523
|
);
|
|
726
|
-
const
|
|
727
|
-
(
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
y: screenDelta.y / realToScreenProjection.d
|
|
736
|
-
};
|
|
737
|
-
let newCenter = {
|
|
738
|
-
x: activeEditEventRef.current.original_center.x + mmDelta.x,
|
|
739
|
-
y: activeEditEventRef.current.original_center.y + mmDelta.y
|
|
740
|
-
};
|
|
741
|
-
if (snapToGrid) {
|
|
742
|
-
const snap = (v) => Math.round(v * 10) / 10;
|
|
743
|
-
newCenter = { x: snap(newCenter.x), y: snap(newCenter.y) };
|
|
524
|
+
const handleTouchMove = useCallback2(
|
|
525
|
+
(event) => {
|
|
526
|
+
const origin = interactionOriginRef.current;
|
|
527
|
+
if (!origin || event.touches.length !== 1) return;
|
|
528
|
+
const touch = event.touches[0];
|
|
529
|
+
const movedTooFar = !touch || Math.abs(touch.clientX - origin.x) > MOVEMENT_THRESHOLD_PX || Math.abs(touch.clientY - origin.y) > MOVEMENT_THRESHOLD_PX;
|
|
530
|
+
if (movedTooFar) {
|
|
531
|
+
interactionOriginRef.current = null;
|
|
532
|
+
clearLongPressTimeout();
|
|
744
533
|
}
|
|
745
|
-
const newEditEvent = {
|
|
746
|
-
...activeEditEventRef.current,
|
|
747
|
-
new_center: newCenter
|
|
748
|
-
};
|
|
749
|
-
activeEditEventRef.current = newEditEvent;
|
|
750
|
-
setActiveEditEvent(newEditEvent);
|
|
751
|
-
},
|
|
752
|
-
[realToScreenProjection, snapToGrid]
|
|
753
|
-
);
|
|
754
|
-
const handleMouseMove = useCallback(
|
|
755
|
-
(e) => updateDragPosition(e.clientX, e.clientY),
|
|
756
|
-
[updateDragPosition]
|
|
757
|
-
);
|
|
758
|
-
const handleTouchMove = useCallback(
|
|
759
|
-
(e) => {
|
|
760
|
-
if (e.touches.length !== 1 || !activeEditEventRef.current) return;
|
|
761
|
-
e.preventDefault();
|
|
762
|
-
const touch = e.touches[0];
|
|
763
|
-
updateDragPosition(touch.clientX, touch.clientY);
|
|
764
534
|
},
|
|
765
|
-
[
|
|
535
|
+
[clearLongPressTimeout]
|
|
766
536
|
);
|
|
767
|
-
const
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
const handleMouseUp = useCallback(() => endDrag(), [endDrag]);
|
|
785
|
-
const handleTouchEnd = useCallback(() => endDrag(), [endDrag]);
|
|
786
|
-
useEffect6(() => {
|
|
787
|
-
window.addEventListener("mousemove", handleMouseMove);
|
|
788
|
-
window.addEventListener("mouseup", handleMouseUp);
|
|
789
|
-
window.addEventListener("touchmove", handleTouchMove, { passive: false });
|
|
790
|
-
window.addEventListener("touchend", handleTouchEnd);
|
|
537
|
+
const handleTouchEnd = useCallback2(() => {
|
|
538
|
+
clearLongPressTimeout();
|
|
539
|
+
interactionOriginRef.current = null;
|
|
540
|
+
}, [clearLongPressTimeout]);
|
|
541
|
+
const handleClickAway = useCallback2((event) => {
|
|
542
|
+
const target = event.target;
|
|
543
|
+
if (menuRef.current?.contains(target)) return;
|
|
544
|
+
const isInRadixPortal = target.closest?.(
|
|
545
|
+
"[data-radix-popper-content-wrapper], [data-radix-dropdown-menu-content]"
|
|
546
|
+
);
|
|
547
|
+
if (isInRadixPortal) return;
|
|
548
|
+
setMenuVisible(false);
|
|
549
|
+
}, []);
|
|
550
|
+
useEffect4(() => {
|
|
551
|
+
if (!menuVisible) return;
|
|
552
|
+
document.addEventListener("mousedown", handleClickAway);
|
|
553
|
+
document.addEventListener("touchstart", handleClickAway);
|
|
791
554
|
return () => {
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
window.removeEventListener("touchmove", handleTouchMove);
|
|
795
|
-
window.removeEventListener("touchend", handleTouchEnd);
|
|
555
|
+
document.removeEventListener("mousedown", handleClickAway);
|
|
556
|
+
document.removeEventListener("touchstart", handleClickAway);
|
|
796
557
|
};
|
|
797
|
-
}, [
|
|
558
|
+
}, [handleClickAway, menuVisible]);
|
|
559
|
+
useEffect4(() => clearLongPressTimeout, [clearLongPressTimeout]);
|
|
798
560
|
return {
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
// lib/utils/z-index-map.ts
|
|
807
|
-
var zIndexMap = {
|
|
808
|
-
schematicEditIcon: 50,
|
|
809
|
-
schematicGridIcon: 49,
|
|
810
|
-
viewMenuIcon: 48,
|
|
811
|
-
viewMenu: 55,
|
|
812
|
-
viewMenuBackdrop: 54,
|
|
813
|
-
clickToInteractOverlay: 100,
|
|
814
|
-
schematicComponentHoverOutline: 47,
|
|
815
|
-
schematicPortHoverOutline: 48
|
|
816
|
-
};
|
|
817
|
-
|
|
818
|
-
// lib/components/EditIcon.tsx
|
|
819
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
820
|
-
var EditIcon = ({
|
|
821
|
-
onClick,
|
|
822
|
-
active
|
|
823
|
-
}) => {
|
|
824
|
-
const handleInteraction = (e) => {
|
|
825
|
-
e.preventDefault();
|
|
826
|
-
onClick();
|
|
827
|
-
};
|
|
828
|
-
return /* @__PURE__ */ jsx(
|
|
829
|
-
"div",
|
|
830
|
-
{
|
|
831
|
-
onClick: handleInteraction,
|
|
832
|
-
onTouchEnd: handleInteraction,
|
|
833
|
-
title: active ? "Disable edit mode" : "Enable edit mode",
|
|
834
|
-
style: {
|
|
835
|
-
position: "absolute",
|
|
836
|
-
top: "16px",
|
|
837
|
-
right: "64px",
|
|
838
|
-
backgroundColor: active ? "#4CAF50" : "#fff",
|
|
839
|
-
color: active ? "#fff" : "#000",
|
|
840
|
-
padding: "8px",
|
|
841
|
-
borderRadius: "4px",
|
|
842
|
-
cursor: "pointer",
|
|
843
|
-
boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
|
|
844
|
-
display: "flex",
|
|
845
|
-
alignItems: "center",
|
|
846
|
-
gap: "4px",
|
|
847
|
-
zIndex: zIndexMap.schematicEditIcon
|
|
561
|
+
menuVisible,
|
|
562
|
+
menuPos,
|
|
563
|
+
menuRef,
|
|
564
|
+
setMenuVisible,
|
|
565
|
+
contextMenuEventHandlers: {
|
|
566
|
+
onMouseDown: (event) => {
|
|
567
|
+
interactionOriginRef.current = event.button === 2 || event.button === 0 && event.ctrlKey ? { x: event.clientX, y: event.clientY } : null;
|
|
848
568
|
},
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
viewBox: "0 0 24 24",
|
|
855
|
-
fill: "none",
|
|
856
|
-
stroke: "currentColor",
|
|
857
|
-
strokeWidth: "2",
|
|
858
|
-
children: [
|
|
859
|
-
/* @__PURE__ */ jsx("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
|
|
860
|
-
/* @__PURE__ */ jsx("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
|
|
861
|
-
]
|
|
862
|
-
}
|
|
863
|
-
)
|
|
569
|
+
onContextMenu: handleContextMenu,
|
|
570
|
+
onTouchStart: handleTouchStart,
|
|
571
|
+
onTouchMove: handleTouchMove,
|
|
572
|
+
onTouchEnd: handleTouchEnd,
|
|
573
|
+
onTouchCancel: handleTouchEnd
|
|
864
574
|
}
|
|
865
|
-
);
|
|
866
|
-
};
|
|
867
|
-
|
|
868
|
-
// lib/components/GridIcon.tsx
|
|
869
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
870
|
-
var GridIcon = ({
|
|
871
|
-
onClick,
|
|
872
|
-
active
|
|
873
|
-
}) => {
|
|
874
|
-
const handleInteraction = (e) => {
|
|
875
|
-
e.preventDefault();
|
|
876
|
-
onClick();
|
|
877
575
|
};
|
|
878
|
-
return /* @__PURE__ */ jsx2(
|
|
879
|
-
"div",
|
|
880
|
-
{
|
|
881
|
-
onClick: handleInteraction,
|
|
882
|
-
onTouchEnd: handleInteraction,
|
|
883
|
-
title: active ? "Hide grid" : "Show grid",
|
|
884
|
-
style: {
|
|
885
|
-
position: "absolute",
|
|
886
|
-
top: "56px",
|
|
887
|
-
right: "64px",
|
|
888
|
-
backgroundColor: active ? "#4CAF50" : "#fff",
|
|
889
|
-
color: active ? "#fff" : "#000",
|
|
890
|
-
padding: "8px",
|
|
891
|
-
borderRadius: "4px",
|
|
892
|
-
cursor: "pointer",
|
|
893
|
-
boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
|
|
894
|
-
display: "flex",
|
|
895
|
-
alignItems: "center",
|
|
896
|
-
gap: "4px",
|
|
897
|
-
zIndex: zIndexMap.schematicGridIcon
|
|
898
|
-
},
|
|
899
|
-
children: /* @__PURE__ */ jsx2(
|
|
900
|
-
"svg",
|
|
901
|
-
{
|
|
902
|
-
width: "16",
|
|
903
|
-
height: "16",
|
|
904
|
-
viewBox: "0 0 24 24",
|
|
905
|
-
fill: "none",
|
|
906
|
-
stroke: "currentColor",
|
|
907
|
-
strokeWidth: "2",
|
|
908
|
-
children: /* @__PURE__ */ jsx2("path", { d: "M3 3h7v7H3zM14 3h7v7h-7zM3 14h7v7H3zM14 14h7v7h-7z" })
|
|
909
|
-
}
|
|
910
|
-
)
|
|
911
|
-
}
|
|
912
|
-
);
|
|
913
|
-
};
|
|
914
|
-
|
|
915
|
-
// lib/components/ViewMenu.tsx
|
|
916
|
-
import { useMemo } from "react";
|
|
917
|
-
import { su as su6 } from "@tscircuit/soup-util";
|
|
918
|
-
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
|
919
|
-
|
|
920
|
-
// package.json
|
|
921
|
-
var package_default = {
|
|
922
|
-
name: "@tscircuit/schematic-viewer",
|
|
923
|
-
version: "2.0.76",
|
|
924
|
-
main: "dist/index.js",
|
|
925
|
-
type: "module",
|
|
926
|
-
scripts: {
|
|
927
|
-
start: "cosmos",
|
|
928
|
-
build: "tsup-node ./lib/index.ts --dts --format esm --sourcemap",
|
|
929
|
-
"build:site": "cosmos-export",
|
|
930
|
-
"vercel-build": "bun run build:site",
|
|
931
|
-
format: "biome format --write .",
|
|
932
|
-
"format:check": "biome format ."
|
|
933
|
-
},
|
|
934
|
-
files: [
|
|
935
|
-
"dist"
|
|
936
|
-
],
|
|
937
|
-
devDependencies: {
|
|
938
|
-
"@biomejs/biome": "^1.9.4",
|
|
939
|
-
"@types/bun": "latest",
|
|
940
|
-
"@types/debug": "^4.1.12",
|
|
941
|
-
"@types/react": "^19.0.1",
|
|
942
|
-
"@types/react-dom": "^19.0.2",
|
|
943
|
-
"@vitejs/plugin-react": "^4.3.4",
|
|
944
|
-
react: "^19.1.0",
|
|
945
|
-
"react-cosmos": "^6.2.1",
|
|
946
|
-
"react-cosmos-plugin-vite": "^6.2.0",
|
|
947
|
-
"react-dom": "^19.1.0",
|
|
948
|
-
"react-reconciler": "^0.31.0",
|
|
949
|
-
semver: "^7.7.2",
|
|
950
|
-
tscircuit: "^0.0.2112",
|
|
951
|
-
tsup: "^8.3.5",
|
|
952
|
-
vite: "^6.0.3"
|
|
953
|
-
},
|
|
954
|
-
peerDependencies: {
|
|
955
|
-
typescript: "^5.0.0",
|
|
956
|
-
tscircuit: "*"
|
|
957
|
-
},
|
|
958
|
-
dependencies: {
|
|
959
|
-
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
960
|
-
"circuit-json": "^0.0.465",
|
|
961
|
-
"circuit-to-svg": "^0.0.393",
|
|
962
|
-
debug: "^4.4.0",
|
|
963
|
-
"performance-now": "^2.1.0",
|
|
964
|
-
"use-mouse-matrix-transform": "^1.2.2"
|
|
965
|
-
}
|
|
966
|
-
};
|
|
967
|
-
|
|
968
|
-
// lib/components/ViewMenuIcon.tsx
|
|
969
|
-
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
970
|
-
var ViewMenuIcon = ({
|
|
971
|
-
active = false,
|
|
972
|
-
...props
|
|
973
|
-
}) => {
|
|
974
|
-
return /* @__PURE__ */ jsx3(
|
|
975
|
-
"button",
|
|
976
|
-
{
|
|
977
|
-
type: "button",
|
|
978
|
-
title: active ? "Hide view menu" : "Show view menu",
|
|
979
|
-
...props,
|
|
980
|
-
style: {
|
|
981
|
-
position: "absolute",
|
|
982
|
-
top: "16px",
|
|
983
|
-
right: "16px",
|
|
984
|
-
backgroundColor: active ? "#4CAF50" : "#fff",
|
|
985
|
-
color: active ? "#fff" : "#000",
|
|
986
|
-
padding: "8px",
|
|
987
|
-
border: "none",
|
|
988
|
-
borderRadius: "4px",
|
|
989
|
-
cursor: "pointer",
|
|
990
|
-
outline: "none",
|
|
991
|
-
boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
|
|
992
|
-
display: "flex",
|
|
993
|
-
alignItems: "center",
|
|
994
|
-
gap: "4px",
|
|
995
|
-
zIndex: zIndexMap.viewMenuIcon
|
|
996
|
-
},
|
|
997
|
-
children: /* @__PURE__ */ jsxs2(
|
|
998
|
-
"svg",
|
|
999
|
-
{
|
|
1000
|
-
width: "16",
|
|
1001
|
-
height: "16",
|
|
1002
|
-
viewBox: "0 0 24 24",
|
|
1003
|
-
fill: "none",
|
|
1004
|
-
stroke: "currentColor",
|
|
1005
|
-
strokeWidth: "2",
|
|
1006
|
-
children: [
|
|
1007
|
-
/* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "1" }),
|
|
1008
|
-
/* @__PURE__ */ jsx3("circle", { cx: "12", cy: "5", r: "1" }),
|
|
1009
|
-
/* @__PURE__ */ jsx3("circle", { cx: "12", cy: "19", r: "1" })
|
|
1010
|
-
]
|
|
1011
|
-
}
|
|
1012
|
-
)
|
|
1013
|
-
}
|
|
1014
|
-
);
|
|
1015
|
-
};
|
|
1016
|
-
|
|
1017
|
-
// lib/components/ViewMenu.tsx
|
|
1018
|
-
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1019
|
-
var FONT_FAMILY = 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
1020
|
-
var contentStyles = {
|
|
1021
|
-
backgroundColor: "#ffffff",
|
|
1022
|
-
color: "#111111",
|
|
1023
|
-
borderRadius: 8,
|
|
1024
|
-
boxShadow: "0 6px 24px rgba(0,0,0,0.12), 0 1px 3px rgba(0,0,0,0.08)",
|
|
1025
|
-
border: "1px solid #e5e7eb",
|
|
1026
|
-
padding: 4,
|
|
1027
|
-
minWidth: 224,
|
|
1028
|
-
fontSize: 13,
|
|
1029
|
-
fontFamily: FONT_FAMILY,
|
|
1030
|
-
outline: "none",
|
|
1031
|
-
zIndex: zIndexMap.viewMenu
|
|
1032
|
-
};
|
|
1033
|
-
var itemStyles = {
|
|
1034
|
-
display: "flex",
|
|
1035
|
-
alignItems: "center",
|
|
1036
|
-
gap: 8,
|
|
1037
|
-
padding: "7px 10px 7px 8px",
|
|
1038
|
-
borderRadius: 6,
|
|
1039
|
-
cursor: "pointer",
|
|
1040
|
-
outline: "none",
|
|
1041
|
-
userSelect: "none",
|
|
1042
|
-
color: "#111111",
|
|
1043
|
-
fontSize: 13,
|
|
1044
|
-
fontFamily: FONT_FAMILY
|
|
1045
|
-
};
|
|
1046
|
-
var iconSlotStyles = {
|
|
1047
|
-
width: 16,
|
|
1048
|
-
height: 16,
|
|
1049
|
-
flexShrink: 0,
|
|
1050
|
-
display: "inline-flex",
|
|
1051
|
-
alignItems: "center",
|
|
1052
|
-
justifyContent: "center",
|
|
1053
|
-
color: "#111111"
|
|
1054
|
-
};
|
|
1055
|
-
var separatorStyles = {
|
|
1056
|
-
height: 1,
|
|
1057
|
-
backgroundColor: "#ececec",
|
|
1058
|
-
margin: "4px 0"
|
|
1059
|
-
};
|
|
1060
|
-
var HIGHLIGHT_CSS = `
|
|
1061
|
-
.sv-vm-item[data-highlighted]:not([data-disabled]),
|
|
1062
|
-
.sv-vm-item:hover:not([data-disabled]) { background-color: #f1f3f5; }
|
|
1063
|
-
.sv-vm-item[data-disabled] { opacity: 0.45; cursor: not-allowed; }
|
|
1064
|
-
`;
|
|
1065
|
-
var CheckIcon = () => /* @__PURE__ */ jsx4(
|
|
1066
|
-
"svg",
|
|
1067
|
-
{
|
|
1068
|
-
width: "14",
|
|
1069
|
-
height: "14",
|
|
1070
|
-
viewBox: "0 0 24 24",
|
|
1071
|
-
fill: "none",
|
|
1072
|
-
stroke: "currentColor",
|
|
1073
|
-
strokeWidth: "2.5",
|
|
1074
|
-
strokeLinecap: "round",
|
|
1075
|
-
strokeLinejoin: "round",
|
|
1076
|
-
"aria-hidden": "true",
|
|
1077
|
-
children: /* @__PURE__ */ jsx4("path", { d: "M20 6 9 17l-5-5" })
|
|
1078
|
-
}
|
|
1079
|
-
);
|
|
1080
|
-
var ViewMenu = ({
|
|
1081
|
-
circuitJson,
|
|
1082
|
-
circuitJsonKey,
|
|
1083
|
-
open,
|
|
1084
|
-
onOpenChange,
|
|
1085
|
-
showGroups,
|
|
1086
|
-
onToggleGroups,
|
|
1087
|
-
showGrid,
|
|
1088
|
-
onToggleGrid
|
|
1089
|
-
}) => {
|
|
1090
|
-
const hasGroups = useMemo(() => {
|
|
1091
|
-
if (!circuitJson || circuitJson.length === 0) return false;
|
|
1092
|
-
try {
|
|
1093
|
-
const sourceGroups = su6(circuitJson).source_group?.list() || [];
|
|
1094
|
-
if (sourceGroups.length > 0) return true;
|
|
1095
|
-
const schematicComponents = su6(circuitJson).schematic_component?.list() || [];
|
|
1096
|
-
if (schematicComponents.length > 1) {
|
|
1097
|
-
const componentTypes = /* @__PURE__ */ new Set();
|
|
1098
|
-
for (const comp of schematicComponents) {
|
|
1099
|
-
const sourceComp = su6(circuitJson).source_component.get(
|
|
1100
|
-
comp.source_component_id
|
|
1101
|
-
);
|
|
1102
|
-
if (sourceComp?.ftype) {
|
|
1103
|
-
componentTypes.add(sourceComp.ftype);
|
|
1104
|
-
}
|
|
1105
|
-
}
|
|
1106
|
-
return componentTypes.size > 1;
|
|
1107
|
-
}
|
|
1108
|
-
return false;
|
|
1109
|
-
} catch (error) {
|
|
1110
|
-
console.error("Error checking for groups:", error);
|
|
1111
|
-
return false;
|
|
1112
|
-
}
|
|
1113
|
-
}, [circuitJsonKey]);
|
|
1114
|
-
return /* @__PURE__ */ jsxs3(DropdownMenu.Root, { open, onOpenChange, modal: false, children: [
|
|
1115
|
-
/* @__PURE__ */ jsx4(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx4(ViewMenuIcon, { active: open }) }),
|
|
1116
|
-
/* @__PURE__ */ jsx4(DropdownMenu.Portal, { children: /* @__PURE__ */ jsxs3(
|
|
1117
|
-
DropdownMenu.Content,
|
|
1118
|
-
{
|
|
1119
|
-
style: contentStyles,
|
|
1120
|
-
side: "bottom",
|
|
1121
|
-
align: "end",
|
|
1122
|
-
sideOffset: 8,
|
|
1123
|
-
collisionPadding: 10,
|
|
1124
|
-
children: [
|
|
1125
|
-
/* @__PURE__ */ jsx4("style", { children: HIGHLIGHT_CSS }),
|
|
1126
|
-
/* @__PURE__ */ jsxs3(
|
|
1127
|
-
DropdownMenu.Item,
|
|
1128
|
-
{
|
|
1129
|
-
className: "sv-vm-item",
|
|
1130
|
-
style: itemStyles,
|
|
1131
|
-
disabled: !hasGroups,
|
|
1132
|
-
title: hasGroups ? void 0 : "No groups found in this schematic",
|
|
1133
|
-
onSelect: (e) => e.preventDefault(),
|
|
1134
|
-
onPointerUp: () => {
|
|
1135
|
-
if (hasGroups) onToggleGroups(!showGroups);
|
|
1136
|
-
},
|
|
1137
|
-
children: [
|
|
1138
|
-
/* @__PURE__ */ jsx4("span", { style: iconSlotStyles, children: showGroups && /* @__PURE__ */ jsx4(CheckIcon, {}) }),
|
|
1139
|
-
/* @__PURE__ */ jsx4("span", { children: "View Schematic Groups" })
|
|
1140
|
-
]
|
|
1141
|
-
}
|
|
1142
|
-
),
|
|
1143
|
-
/* @__PURE__ */ jsxs3(
|
|
1144
|
-
DropdownMenu.Item,
|
|
1145
|
-
{
|
|
1146
|
-
className: "sv-vm-item",
|
|
1147
|
-
style: itemStyles,
|
|
1148
|
-
onSelect: (e) => e.preventDefault(),
|
|
1149
|
-
onPointerUp: () => onToggleGrid(!showGrid),
|
|
1150
|
-
children: [
|
|
1151
|
-
/* @__PURE__ */ jsx4("span", { style: iconSlotStyles, children: showGrid && /* @__PURE__ */ jsx4(CheckIcon, {}) }),
|
|
1152
|
-
/* @__PURE__ */ jsx4("span", { children: "Show Grid" })
|
|
1153
|
-
]
|
|
1154
|
-
}
|
|
1155
|
-
),
|
|
1156
|
-
/* @__PURE__ */ jsx4(DropdownMenu.Separator, { style: separatorStyles }),
|
|
1157
|
-
/* @__PURE__ */ jsxs3(
|
|
1158
|
-
"div",
|
|
1159
|
-
{
|
|
1160
|
-
style: {
|
|
1161
|
-
padding: "4px 8px",
|
|
1162
|
-
fontSize: 12,
|
|
1163
|
-
color: "#9ca3af",
|
|
1164
|
-
textAlign: "center",
|
|
1165
|
-
fontFamily: FONT_FAMILY
|
|
1166
|
-
},
|
|
1167
|
-
children: [
|
|
1168
|
-
"v",
|
|
1169
|
-
String(package_default?.version)
|
|
1170
|
-
]
|
|
1171
|
-
}
|
|
1172
|
-
)
|
|
1173
|
-
]
|
|
1174
|
-
}
|
|
1175
|
-
) })
|
|
1176
|
-
] });
|
|
1177
|
-
};
|
|
1178
|
-
|
|
1179
|
-
// lib/hooks/useLocalStorage.ts
|
|
1180
|
-
import { useCallback as useCallback2 } from "react";
|
|
1181
|
-
var STORAGE_KEYS = {
|
|
1182
|
-
IS_SHOWING_SCHEMATIC_GROUPS: "schematic_viewer_show_groups",
|
|
1183
|
-
SELECTED_SCHEMATIC_SHEET: "schematic_viewer_selected_sheet"
|
|
1184
|
-
};
|
|
1185
|
-
var getStoredBoolean = (key, defaultValue) => {
|
|
1186
|
-
if (typeof window === "undefined") return defaultValue;
|
|
1187
|
-
try {
|
|
1188
|
-
const stored = localStorage.getItem(key);
|
|
1189
|
-
return stored !== null ? JSON.parse(stored) : defaultValue;
|
|
1190
|
-
} catch {
|
|
1191
|
-
return defaultValue;
|
|
1192
|
-
}
|
|
1193
|
-
};
|
|
1194
|
-
var setStoredBoolean = (key, value) => {
|
|
1195
|
-
if (typeof window === "undefined") return;
|
|
1196
|
-
try {
|
|
1197
|
-
localStorage.setItem(key, JSON.stringify(value));
|
|
1198
|
-
} catch {
|
|
1199
|
-
}
|
|
1200
|
-
};
|
|
1201
|
-
var getStoredString = (key) => {
|
|
1202
|
-
if (typeof window === "undefined") return null;
|
|
1203
|
-
try {
|
|
1204
|
-
return localStorage.getItem(key);
|
|
1205
|
-
} catch {
|
|
1206
|
-
return null;
|
|
1207
|
-
}
|
|
1208
576
|
};
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
577
|
+
|
|
578
|
+
// lib/utils/z-index-map.ts
|
|
579
|
+
var zIndexMap = {
|
|
580
|
+
contextMenu: 110,
|
|
581
|
+
viewMenu: 55,
|
|
582
|
+
viewMenuIcon: 48,
|
|
583
|
+
clickToInteractOverlay: 100,
|
|
584
|
+
schematicComponentHoverOutline: 47,
|
|
585
|
+
schematicPortHoverOutline: 48
|
|
1215
586
|
};
|
|
1216
587
|
|
|
1217
588
|
// lib/components/MouseTracker.tsx
|
|
@@ -1219,11 +590,11 @@ import {
|
|
|
1219
590
|
createContext,
|
|
1220
591
|
useCallback as useCallback3,
|
|
1221
592
|
useContext,
|
|
1222
|
-
useEffect as
|
|
1223
|
-
useMemo
|
|
1224
|
-
useRef as
|
|
593
|
+
useEffect as useEffect5,
|
|
594
|
+
useMemo,
|
|
595
|
+
useRef as useRef2
|
|
1225
596
|
} from "react";
|
|
1226
|
-
import { Fragment, jsx
|
|
597
|
+
import { Fragment, jsx } from "react/jsx-runtime";
|
|
1227
598
|
var MouseTrackerContext = createContext(null);
|
|
1228
599
|
var DRAG_THRESHOLD_PX = 5;
|
|
1229
600
|
var boundsAreEqual = (a, b) => {
|
|
@@ -1234,12 +605,12 @@ var boundsAreEqual = (a, b) => {
|
|
|
1234
605
|
var MouseTracker = ({ children }) => {
|
|
1235
606
|
const existingContext = useContext(MouseTrackerContext);
|
|
1236
607
|
if (existingContext) {
|
|
1237
|
-
return /* @__PURE__ */
|
|
608
|
+
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
1238
609
|
}
|
|
1239
|
-
return /* @__PURE__ */
|
|
610
|
+
return /* @__PURE__ */ jsx(MouseTrackerProvider, { children });
|
|
1240
611
|
};
|
|
1241
612
|
var MouseTrackerProvider = ({ children }) => {
|
|
1242
|
-
const storeRef =
|
|
613
|
+
const storeRef = useRef2({
|
|
1243
614
|
pointer: null,
|
|
1244
615
|
boundingBoxes: /* @__PURE__ */ new Map(),
|
|
1245
616
|
hoveringIds: /* @__PURE__ */ new Set(),
|
|
@@ -1306,7 +677,7 @@ var MouseTrackerProvider = ({ children }) => {
|
|
|
1306
677
|
const isHovering = useCallback3((id) => {
|
|
1307
678
|
return storeRef.current.hoveringIds.has(id);
|
|
1308
679
|
}, []);
|
|
1309
|
-
|
|
680
|
+
useEffect5(() => {
|
|
1310
681
|
const handlePointerPosition = (event) => {
|
|
1311
682
|
const { clientX, clientY } = event;
|
|
1312
683
|
const pointer = storeRef.current.pointer;
|
|
@@ -1374,7 +745,7 @@ var MouseTrackerProvider = ({ children }) => {
|
|
|
1374
745
|
window.removeEventListener("click", handleClick);
|
|
1375
746
|
};
|
|
1376
747
|
}, [updateHovering]);
|
|
1377
|
-
const value =
|
|
748
|
+
const value = useMemo(
|
|
1378
749
|
() => ({
|
|
1379
750
|
registerBoundingBox,
|
|
1380
751
|
updateBoundingBox,
|
|
@@ -1390,19 +761,19 @@ var MouseTrackerProvider = ({ children }) => {
|
|
|
1390
761
|
isHovering
|
|
1391
762
|
]
|
|
1392
763
|
);
|
|
1393
|
-
return /* @__PURE__ */
|
|
764
|
+
return /* @__PURE__ */ jsx(MouseTrackerContext.Provider, { value, children });
|
|
1394
765
|
};
|
|
1395
766
|
|
|
1396
767
|
// lib/components/SchematicComponentMouseTarget.tsx
|
|
1397
|
-
import { useCallback as useCallback4, useEffect as
|
|
768
|
+
import { useCallback as useCallback4, useEffect as useEffect7, useRef as useRef4, useState as useState3 } from "react";
|
|
1398
769
|
|
|
1399
770
|
// lib/hooks/useMouseEventsOverBoundingBox.ts
|
|
1400
771
|
import {
|
|
1401
772
|
useContext as useContext2,
|
|
1402
|
-
useEffect as
|
|
773
|
+
useEffect as useEffect6,
|
|
1403
774
|
useId,
|
|
1404
|
-
useMemo as
|
|
1405
|
-
useRef as
|
|
775
|
+
useMemo as useMemo2,
|
|
776
|
+
useRef as useRef3,
|
|
1406
777
|
useSyncExternalStore
|
|
1407
778
|
} from "react";
|
|
1408
779
|
var useMouseEventsOverBoundingBox = (options) => {
|
|
@@ -1413,15 +784,15 @@ var useMouseEventsOverBoundingBox = (options) => {
|
|
|
1413
784
|
);
|
|
1414
785
|
}
|
|
1415
786
|
const id = useId();
|
|
1416
|
-
const latestOptionsRef =
|
|
787
|
+
const latestOptionsRef = useRef3(options);
|
|
1417
788
|
latestOptionsRef.current = options;
|
|
1418
|
-
const handleClick =
|
|
789
|
+
const handleClick = useMemo2(
|
|
1419
790
|
() => (event) => {
|
|
1420
791
|
latestOptionsRef.current.onClick?.(event);
|
|
1421
792
|
},
|
|
1422
793
|
[]
|
|
1423
794
|
);
|
|
1424
|
-
|
|
795
|
+
useEffect6(() => {
|
|
1425
796
|
context.registerBoundingBox(id, {
|
|
1426
797
|
bounds: latestOptionsRef.current.bounds,
|
|
1427
798
|
onClick: latestOptionsRef.current.onClick ? handleClick : void 0
|
|
@@ -1430,7 +801,7 @@ var useMouseEventsOverBoundingBox = (options) => {
|
|
|
1430
801
|
context.unregisterBoundingBox(id);
|
|
1431
802
|
};
|
|
1432
803
|
}, [context, handleClick, id]);
|
|
1433
|
-
|
|
804
|
+
useEffect6(() => {
|
|
1434
805
|
context.updateBoundingBox(id, {
|
|
1435
806
|
bounds: latestOptionsRef.current.bounds,
|
|
1436
807
|
onClick: latestOptionsRef.current.onClick ? handleClick : void 0
|
|
@@ -1454,7 +825,7 @@ var useMouseEventsOverBoundingBox = (options) => {
|
|
|
1454
825
|
};
|
|
1455
826
|
|
|
1456
827
|
// lib/components/SchematicComponentMouseTarget.tsx
|
|
1457
|
-
import { jsx as
|
|
828
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
1458
829
|
var areMeasurementsEqual = (a, b) => {
|
|
1459
830
|
if (!a && !b) return true;
|
|
1460
831
|
if (!a || !b) return false;
|
|
@@ -1470,7 +841,7 @@ var SchematicComponentMouseTarget = ({
|
|
|
1470
841
|
circuitJsonKey
|
|
1471
842
|
}) => {
|
|
1472
843
|
const [measurement, setMeasurement] = useState3(null);
|
|
1473
|
-
const frameRef =
|
|
844
|
+
const frameRef = useRef4(null);
|
|
1474
845
|
const measure = useCallback4(() => {
|
|
1475
846
|
frameRef.current = null;
|
|
1476
847
|
const svgDiv = svgDivRef.current;
|
|
@@ -1510,10 +881,10 @@ var SchematicComponentMouseTarget = ({
|
|
|
1510
881
|
if (frameRef.current !== null) return;
|
|
1511
882
|
frameRef.current = window.requestAnimationFrame(measure);
|
|
1512
883
|
}, [measure]);
|
|
1513
|
-
|
|
884
|
+
useEffect7(() => {
|
|
1514
885
|
scheduleMeasure();
|
|
1515
886
|
}, [scheduleMeasure, circuitJsonKey]);
|
|
1516
|
-
|
|
887
|
+
useEffect7(() => {
|
|
1517
888
|
scheduleMeasure();
|
|
1518
889
|
const svgDiv = svgDivRef.current;
|
|
1519
890
|
const container = containerRef.current;
|
|
@@ -1558,7 +929,7 @@ var SchematicComponentMouseTarget = ({
|
|
|
1558
929
|
bounds,
|
|
1559
930
|
onClick: onComponentClick ? handleClick : void 0
|
|
1560
931
|
});
|
|
1561
|
-
|
|
932
|
+
useEffect7(() => {
|
|
1562
933
|
if (onHoverChange) {
|
|
1563
934
|
onHoverChange(componentId, hovering);
|
|
1564
935
|
}
|
|
@@ -1567,7 +938,7 @@ var SchematicComponentMouseTarget = ({
|
|
|
1567
938
|
return null;
|
|
1568
939
|
}
|
|
1569
940
|
const rect = measurement.rect;
|
|
1570
|
-
return /* @__PURE__ */
|
|
941
|
+
return /* @__PURE__ */ jsx2(
|
|
1571
942
|
"div",
|
|
1572
943
|
{
|
|
1573
944
|
style: {
|
|
@@ -1585,8 +956,8 @@ var SchematicComponentMouseTarget = ({
|
|
|
1585
956
|
};
|
|
1586
957
|
|
|
1587
958
|
// lib/components/SchematicPortMouseTarget.tsx
|
|
1588
|
-
import { useCallback as useCallback5, useEffect as
|
|
1589
|
-
import { Fragment as Fragment2, jsx as
|
|
959
|
+
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";
|
|
1590
961
|
var areMeasurementsEqual2 = (a, b) => {
|
|
1591
962
|
if (!a && !b) return true;
|
|
1592
963
|
if (!a || !b) return false;
|
|
@@ -1603,7 +974,7 @@ var SchematicPortMouseTarget = ({
|
|
|
1603
974
|
circuitJsonKey
|
|
1604
975
|
}) => {
|
|
1605
976
|
const [measurement, setMeasurement] = useState4(null);
|
|
1606
|
-
const frameRef =
|
|
977
|
+
const frameRef = useRef5(null);
|
|
1607
978
|
const measure = useCallback5(() => {
|
|
1608
979
|
frameRef.current = null;
|
|
1609
980
|
const svgDiv = svgDivRef.current;
|
|
@@ -1644,10 +1015,10 @@ var SchematicPortMouseTarget = ({
|
|
|
1644
1015
|
if (frameRef.current !== null) return;
|
|
1645
1016
|
frameRef.current = window.requestAnimationFrame(measure);
|
|
1646
1017
|
}, [measure]);
|
|
1647
|
-
|
|
1018
|
+
useEffect8(() => {
|
|
1648
1019
|
scheduleMeasure();
|
|
1649
1020
|
}, [scheduleMeasure, circuitJsonKey]);
|
|
1650
|
-
|
|
1021
|
+
useEffect8(() => {
|
|
1651
1022
|
scheduleMeasure();
|
|
1652
1023
|
const svgDiv = svgDivRef.current;
|
|
1653
1024
|
const container = containerRef.current;
|
|
@@ -1692,7 +1063,7 @@ var SchematicPortMouseTarget = ({
|
|
|
1692
1063
|
bounds,
|
|
1693
1064
|
onClick: onPortClick ? handleClick : void 0
|
|
1694
1065
|
});
|
|
1695
|
-
|
|
1066
|
+
useEffect8(() => {
|
|
1696
1067
|
if (onHoverChange) {
|
|
1697
1068
|
onHoverChange(portId, hovering);
|
|
1698
1069
|
}
|
|
@@ -1701,8 +1072,8 @@ var SchematicPortMouseTarget = ({
|
|
|
1701
1072
|
return null;
|
|
1702
1073
|
}
|
|
1703
1074
|
const rect = measurement.rect;
|
|
1704
|
-
return /* @__PURE__ */
|
|
1705
|
-
/* @__PURE__ */
|
|
1075
|
+
return /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
1076
|
+
/* @__PURE__ */ jsx3(
|
|
1706
1077
|
"div",
|
|
1707
1078
|
{
|
|
1708
1079
|
style: {
|
|
@@ -1720,7 +1091,7 @@ var SchematicPortMouseTarget = ({
|
|
|
1720
1091
|
}
|
|
1721
1092
|
}
|
|
1722
1093
|
),
|
|
1723
|
-
hovering && portLabel && /* @__PURE__ */
|
|
1094
|
+
hovering && portLabel && /* @__PURE__ */ jsx3(
|
|
1724
1095
|
"div",
|
|
1725
1096
|
{
|
|
1726
1097
|
style: {
|
|
@@ -1746,10 +1117,10 @@ var SchematicPortMouseTarget = ({
|
|
|
1746
1117
|
|
|
1747
1118
|
// lib/components/SchematicSheetSelector.tsx
|
|
1748
1119
|
import { useState as useState5 } from "react";
|
|
1749
|
-
import * as
|
|
1750
|
-
import { Fragment as Fragment3, jsx as
|
|
1751
|
-
var
|
|
1752
|
-
var
|
|
1120
|
+
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
|
1121
|
+
import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1122
|
+
var FONT_FAMILY = 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
1123
|
+
var contentStyles = {
|
|
1753
1124
|
backgroundColor: "#ffffff",
|
|
1754
1125
|
color: "#111111",
|
|
1755
1126
|
borderRadius: 8,
|
|
@@ -1761,11 +1132,11 @@ var contentStyles2 = {
|
|
|
1761
1132
|
maxHeight: 320,
|
|
1762
1133
|
overflowY: "auto",
|
|
1763
1134
|
fontSize: 13,
|
|
1764
|
-
fontFamily:
|
|
1135
|
+
fontFamily: FONT_FAMILY,
|
|
1765
1136
|
outline: "none",
|
|
1766
1137
|
zIndex: zIndexMap.viewMenu
|
|
1767
1138
|
};
|
|
1768
|
-
var
|
|
1139
|
+
var itemStyles = {
|
|
1769
1140
|
display: "flex",
|
|
1770
1141
|
alignItems: "center",
|
|
1771
1142
|
gap: 8,
|
|
@@ -1776,9 +1147,9 @@ var itemStyles2 = {
|
|
|
1776
1147
|
userSelect: "none",
|
|
1777
1148
|
color: "#111111",
|
|
1778
1149
|
fontSize: 13,
|
|
1779
|
-
fontFamily:
|
|
1150
|
+
fontFamily: FONT_FAMILY
|
|
1780
1151
|
};
|
|
1781
|
-
var
|
|
1152
|
+
var iconSlotStyles = {
|
|
1782
1153
|
width: 16,
|
|
1783
1154
|
height: 16,
|
|
1784
1155
|
flexShrink: 0,
|
|
@@ -1797,7 +1168,7 @@ var MENU_CSS = `
|
|
|
1797
1168
|
.sv-sheet-chevron { transition: transform 0.2s ease; }
|
|
1798
1169
|
[data-state="open"] > .sv-sheet-chevron { transform: rotate(180deg); }
|
|
1799
1170
|
`;
|
|
1800
|
-
var
|
|
1171
|
+
var CheckIcon = () => /* @__PURE__ */ jsx4(
|
|
1801
1172
|
"svg",
|
|
1802
1173
|
{
|
|
1803
1174
|
width: "14",
|
|
@@ -1809,10 +1180,10 @@ var CheckIcon2 = () => /* @__PURE__ */ jsx8(
|
|
|
1809
1180
|
strokeLinecap: "round",
|
|
1810
1181
|
strokeLinejoin: "round",
|
|
1811
1182
|
"aria-hidden": "true",
|
|
1812
|
-
children: /* @__PURE__ */
|
|
1183
|
+
children: /* @__PURE__ */ jsx4("path", { d: "M20 6 9 17l-5-5" })
|
|
1813
1184
|
}
|
|
1814
1185
|
);
|
|
1815
|
-
var ChevronDownIcon = ({ className }) => /* @__PURE__ */
|
|
1186
|
+
var ChevronDownIcon = ({ className }) => /* @__PURE__ */ jsx4(
|
|
1816
1187
|
"svg",
|
|
1817
1188
|
{
|
|
1818
1189
|
className,
|
|
@@ -1826,7 +1197,7 @@ var ChevronDownIcon = ({ className }) => /* @__PURE__ */ jsx8(
|
|
|
1826
1197
|
strokeLinejoin: "round",
|
|
1827
1198
|
style: { opacity: 0.6, flexShrink: 0 },
|
|
1828
1199
|
"aria-hidden": "true",
|
|
1829
|
-
children: /* @__PURE__ */
|
|
1200
|
+
children: /* @__PURE__ */ jsx4("path", { d: "m6 9 6 6 6-6" })
|
|
1830
1201
|
}
|
|
1831
1202
|
);
|
|
1832
1203
|
var SchematicSheetSelector = ({
|
|
@@ -1840,10 +1211,10 @@ var SchematicSheetSelector = ({
|
|
|
1840
1211
|
(s) => s.schematic_sheet_id === selectedSheetId
|
|
1841
1212
|
);
|
|
1842
1213
|
const selectedLabel = selectedSheet?.name ?? "Select sheet";
|
|
1843
|
-
return /* @__PURE__ */
|
|
1844
|
-
/* @__PURE__ */
|
|
1845
|
-
/* @__PURE__ */
|
|
1846
|
-
/* @__PURE__ */
|
|
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(
|
|
1847
1218
|
"button",
|
|
1848
1219
|
{
|
|
1849
1220
|
type: "button",
|
|
@@ -1866,31 +1237,31 @@ var SchematicSheetSelector = ({
|
|
|
1866
1237
|
cursor: "pointer",
|
|
1867
1238
|
boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
|
|
1868
1239
|
fontSize: "13px",
|
|
1869
|
-
fontFamily:
|
|
1240
|
+
fontFamily: FONT_FAMILY,
|
|
1870
1241
|
zIndex: zIndexMap.viewMenuIcon
|
|
1871
1242
|
},
|
|
1872
1243
|
children: [
|
|
1873
|
-
/* @__PURE__ */
|
|
1874
|
-
/* @__PURE__ */
|
|
1875
|
-
/* @__PURE__ */
|
|
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" })
|
|
1876
1247
|
]
|
|
1877
1248
|
}
|
|
1878
1249
|
) }),
|
|
1879
|
-
/* @__PURE__ */
|
|
1880
|
-
|
|
1250
|
+
/* @__PURE__ */ jsx4(DropdownMenu.Portal, { children: /* @__PURE__ */ jsx4(
|
|
1251
|
+
DropdownMenu.Content,
|
|
1881
1252
|
{
|
|
1882
|
-
style:
|
|
1253
|
+
style: contentStyles,
|
|
1883
1254
|
side: "bottom",
|
|
1884
1255
|
align: "start",
|
|
1885
1256
|
sideOffset: 8,
|
|
1886
1257
|
collisionPadding: 10,
|
|
1887
1258
|
children: sheets.map((sheet) => {
|
|
1888
1259
|
const selected = sheet.schematic_sheet_id === selectedSheetId;
|
|
1889
|
-
return /* @__PURE__ */
|
|
1890
|
-
|
|
1260
|
+
return /* @__PURE__ */ jsxs2(
|
|
1261
|
+
DropdownMenu.Item,
|
|
1891
1262
|
{
|
|
1892
1263
|
className: "sv-sheet-item",
|
|
1893
|
-
style:
|
|
1264
|
+
style: itemStyles,
|
|
1894
1265
|
title: sheet.name,
|
|
1895
1266
|
onSelect: (e) => e.preventDefault(),
|
|
1896
1267
|
onPointerUp: () => {
|
|
@@ -1898,8 +1269,8 @@ var SchematicSheetSelector = ({
|
|
|
1898
1269
|
setOpen(false);
|
|
1899
1270
|
},
|
|
1900
1271
|
children: [
|
|
1901
|
-
/* @__PURE__ */
|
|
1902
|
-
/* @__PURE__ */
|
|
1272
|
+
/* @__PURE__ */ jsx4("span", { style: iconSlotStyles, children: selected && /* @__PURE__ */ jsx4(CheckIcon, {}) }),
|
|
1273
|
+
/* @__PURE__ */ jsx4("span", { style: { ...ellipsisStyles, minWidth: 0 }, children: sheet.name })
|
|
1903
1274
|
]
|
|
1904
1275
|
},
|
|
1905
1276
|
sheet.schematic_sheet_id
|
|
@@ -1911,29 +1282,292 @@ var SchematicSheetSelector = ({
|
|
|
1911
1282
|
] });
|
|
1912
1283
|
};
|
|
1913
1284
|
|
|
1285
|
+
// lib/components/ViewMenu.tsx
|
|
1286
|
+
import * as DropdownMenu2 from "@radix-ui/react-dropdown-menu";
|
|
1287
|
+
import { su as su3 } from "@tscircuit/soup-util";
|
|
1288
|
+
import { useMemo as useMemo3 } from "react";
|
|
1289
|
+
|
|
1290
|
+
// package.json
|
|
1291
|
+
var package_default = {
|
|
1292
|
+
name: "@tscircuit/schematic-viewer",
|
|
1293
|
+
version: "2.0.78",
|
|
1294
|
+
main: "dist/index.js",
|
|
1295
|
+
type: "module",
|
|
1296
|
+
scripts: {
|
|
1297
|
+
start: "cosmos",
|
|
1298
|
+
build: "tsup-node ./lib/index.ts --dts --format esm --sourcemap",
|
|
1299
|
+
"build:site": "cosmos-export",
|
|
1300
|
+
"vercel-build": "bun run build:site",
|
|
1301
|
+
format: "biome format --write .",
|
|
1302
|
+
"format:check": "biome format ."
|
|
1303
|
+
},
|
|
1304
|
+
files: [
|
|
1305
|
+
"dist"
|
|
1306
|
+
],
|
|
1307
|
+
devDependencies: {
|
|
1308
|
+
"@biomejs/biome": "^1.9.4",
|
|
1309
|
+
"@types/bun": "latest",
|
|
1310
|
+
"@types/debug": "^4.1.12",
|
|
1311
|
+
"@types/jsdom": "^21.1.7",
|
|
1312
|
+
"@types/react": "^19.0.1",
|
|
1313
|
+
"@types/react-dom": "^19.0.2",
|
|
1314
|
+
"@vitejs/plugin-react": "^4.3.4",
|
|
1315
|
+
jsdom: "^26.0.0",
|
|
1316
|
+
react: "^19.1.0",
|
|
1317
|
+
"react-cosmos": "^6.2.1",
|
|
1318
|
+
"react-cosmos-plugin-vite": "^6.2.0",
|
|
1319
|
+
"react-dom": "^19.1.0",
|
|
1320
|
+
"react-reconciler": "^0.31.0",
|
|
1321
|
+
semver: "^7.7.2",
|
|
1322
|
+
tscircuit: "^0.0.2112",
|
|
1323
|
+
tsup: "^8.3.5",
|
|
1324
|
+
vite: "^6.0.3"
|
|
1325
|
+
},
|
|
1326
|
+
peerDependencies: {
|
|
1327
|
+
typescript: "^5.0.0",
|
|
1328
|
+
tscircuit: "*"
|
|
1329
|
+
},
|
|
1330
|
+
dependencies: {
|
|
1331
|
+
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
1332
|
+
"circuit-json": "^0.0.465",
|
|
1333
|
+
"circuit-to-svg": "^0.0.393",
|
|
1334
|
+
debug: "^4.4.0",
|
|
1335
|
+
"performance-now": "^2.1.0",
|
|
1336
|
+
"use-mouse-matrix-transform": "^1.2.2"
|
|
1337
|
+
}
|
|
1338
|
+
};
|
|
1339
|
+
|
|
1340
|
+
// lib/components/ViewMenu.tsx
|
|
1341
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1342
|
+
var FONT_FAMILY2 = 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
1343
|
+
var contentStyles2 = {
|
|
1344
|
+
backgroundColor: "#262626",
|
|
1345
|
+
color: "#fafafa",
|
|
1346
|
+
borderRadius: 6,
|
|
1347
|
+
boxShadow: "0px 12px 48px -12px rgba(0, 0, 0, 0.5), 0px 8px 24px -8px rgba(0, 0, 0, 0.3)",
|
|
1348
|
+
border: "1px solid #333333",
|
|
1349
|
+
padding: 4,
|
|
1350
|
+
minWidth: 208,
|
|
1351
|
+
fontSize: 14,
|
|
1352
|
+
fontWeight: 400,
|
|
1353
|
+
fontFamily: FONT_FAMILY2,
|
|
1354
|
+
outline: "none",
|
|
1355
|
+
zIndex: zIndexMap.contextMenu
|
|
1356
|
+
};
|
|
1357
|
+
var itemStyles2 = {
|
|
1358
|
+
display: "flex",
|
|
1359
|
+
alignItems: "center",
|
|
1360
|
+
gap: 8,
|
|
1361
|
+
padding: "6px 8px",
|
|
1362
|
+
borderRadius: 6,
|
|
1363
|
+
cursor: "default",
|
|
1364
|
+
outline: "none",
|
|
1365
|
+
userSelect: "none",
|
|
1366
|
+
color: "#fafafa",
|
|
1367
|
+
fontSize: 14,
|
|
1368
|
+
fontWeight: 400,
|
|
1369
|
+
fontFamily: FONT_FAMILY2
|
|
1370
|
+
};
|
|
1371
|
+
var iconSlotStyles2 = {
|
|
1372
|
+
width: 16,
|
|
1373
|
+
height: 16,
|
|
1374
|
+
flexShrink: 0,
|
|
1375
|
+
display: "inline-flex",
|
|
1376
|
+
alignItems: "center",
|
|
1377
|
+
justifyContent: "center",
|
|
1378
|
+
color: "#fafafa"
|
|
1379
|
+
};
|
|
1380
|
+
var separatorStyles = {
|
|
1381
|
+
height: 1,
|
|
1382
|
+
backgroundColor: "#ffffff1a",
|
|
1383
|
+
margin: "4px 0"
|
|
1384
|
+
};
|
|
1385
|
+
var HIGHLIGHT_CSS = `
|
|
1386
|
+
.sv-vm-item[data-highlighted]:not([data-disabled]),
|
|
1387
|
+
.sv-vm-item:hover:not([data-disabled]) { background-color: #404040; }
|
|
1388
|
+
.sv-vm-item[data-disabled] { opacity: 0.45; cursor: not-allowed; }
|
|
1389
|
+
`;
|
|
1390
|
+
var CheckIcon2 = () => /* @__PURE__ */ jsx5(
|
|
1391
|
+
"svg",
|
|
1392
|
+
{
|
|
1393
|
+
width: "14",
|
|
1394
|
+
height: "14",
|
|
1395
|
+
viewBox: "0 0 24 24",
|
|
1396
|
+
fill: "none",
|
|
1397
|
+
stroke: "currentColor",
|
|
1398
|
+
strokeWidth: "2.5",
|
|
1399
|
+
strokeLinecap: "round",
|
|
1400
|
+
strokeLinejoin: "round",
|
|
1401
|
+
"aria-hidden": "true",
|
|
1402
|
+
children: /* @__PURE__ */ jsx5("path", { d: "M20 6 9 17l-5-5" })
|
|
1403
|
+
}
|
|
1404
|
+
);
|
|
1405
|
+
var ViewMenu = ({
|
|
1406
|
+
circuitJson,
|
|
1407
|
+
circuitJsonKey,
|
|
1408
|
+
menuRef,
|
|
1409
|
+
menuPos,
|
|
1410
|
+
onOpenChange,
|
|
1411
|
+
showGroups,
|
|
1412
|
+
onToggleGroups,
|
|
1413
|
+
showGrid,
|
|
1414
|
+
onToggleGrid,
|
|
1415
|
+
showPorts,
|
|
1416
|
+
onTogglePorts
|
|
1417
|
+
}) => {
|
|
1418
|
+
const hasGroups = useMemo3(() => {
|
|
1419
|
+
if (!circuitJson || circuitJson.length === 0) return false;
|
|
1420
|
+
try {
|
|
1421
|
+
const sourceGroups = su3(circuitJson).source_group?.list() || [];
|
|
1422
|
+
if (sourceGroups.length > 0) return true;
|
|
1423
|
+
const schematicComponents = su3(circuitJson).schematic_component?.list() || [];
|
|
1424
|
+
if (schematicComponents.length > 1) {
|
|
1425
|
+
const componentTypes = /* @__PURE__ */ new Set();
|
|
1426
|
+
for (const comp of schematicComponents) {
|
|
1427
|
+
const sourceComp = su3(circuitJson).source_component.get(
|
|
1428
|
+
comp.source_component_id
|
|
1429
|
+
);
|
|
1430
|
+
if (sourceComp?.ftype) {
|
|
1431
|
+
componentTypes.add(sourceComp.ftype);
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
return componentTypes.size > 1;
|
|
1435
|
+
}
|
|
1436
|
+
return false;
|
|
1437
|
+
} catch (error) {
|
|
1438
|
+
console.error("Error checking for groups:", error);
|
|
1439
|
+
return false;
|
|
1440
|
+
}
|
|
1441
|
+
}, [circuitJsonKey]);
|
|
1442
|
+
const hasPorts = useMemo3(() => {
|
|
1443
|
+
if (!circuitJson || circuitJson.length === 0) return false;
|
|
1444
|
+
try {
|
|
1445
|
+
return (su3(circuitJson).schematic_port?.list() || []).length > 0;
|
|
1446
|
+
} catch (error) {
|
|
1447
|
+
console.error("Error checking for schematic ports:", error);
|
|
1448
|
+
return false;
|
|
1449
|
+
}
|
|
1450
|
+
}, [circuitJsonKey]);
|
|
1451
|
+
return /* @__PURE__ */ jsx5(
|
|
1452
|
+
"div",
|
|
1453
|
+
{
|
|
1454
|
+
ref: menuRef,
|
|
1455
|
+
style: {
|
|
1456
|
+
position: "fixed",
|
|
1457
|
+
left: menuPos.x,
|
|
1458
|
+
top: menuPos.y,
|
|
1459
|
+
width: 0,
|
|
1460
|
+
height: 0
|
|
1461
|
+
},
|
|
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(
|
|
1465
|
+
DropdownMenu2.Content,
|
|
1466
|
+
{
|
|
1467
|
+
style: contentStyles2,
|
|
1468
|
+
align: "start",
|
|
1469
|
+
sideOffset: 0,
|
|
1470
|
+
collisionPadding: 10,
|
|
1471
|
+
avoidCollisions: true,
|
|
1472
|
+
children: [
|
|
1473
|
+
/* @__PURE__ */ jsx5("style", { children: HIGHLIGHT_CSS }),
|
|
1474
|
+
/* @__PURE__ */ jsxs3(
|
|
1475
|
+
DropdownMenu2.Item,
|
|
1476
|
+
{
|
|
1477
|
+
className: "sv-vm-item",
|
|
1478
|
+
style: itemStyles2,
|
|
1479
|
+
disabled: !hasPorts,
|
|
1480
|
+
title: hasPorts ? void 0 : "No ports found in this schematic",
|
|
1481
|
+
onSelect: (event) => event.preventDefault(),
|
|
1482
|
+
onPointerDown: (event) => {
|
|
1483
|
+
event.preventDefault();
|
|
1484
|
+
if (hasPorts) onTogglePorts(!showPorts);
|
|
1485
|
+
},
|
|
1486
|
+
children: [
|
|
1487
|
+
/* @__PURE__ */ jsx5("span", { style: iconSlotStyles2, children: showPorts && /* @__PURE__ */ jsx5(CheckIcon2, {}) }),
|
|
1488
|
+
/* @__PURE__ */ jsx5("span", { children: "Show Schematic Ports" })
|
|
1489
|
+
]
|
|
1490
|
+
}
|
|
1491
|
+
),
|
|
1492
|
+
/* @__PURE__ */ jsxs3(
|
|
1493
|
+
DropdownMenu2.Item,
|
|
1494
|
+
{
|
|
1495
|
+
className: "sv-vm-item",
|
|
1496
|
+
style: itemStyles2,
|
|
1497
|
+
disabled: !hasGroups,
|
|
1498
|
+
title: hasGroups ? void 0 : "No groups found in this schematic",
|
|
1499
|
+
onSelect: (event) => event.preventDefault(),
|
|
1500
|
+
onPointerDown: (event) => {
|
|
1501
|
+
event.preventDefault();
|
|
1502
|
+
if (hasGroups) onToggleGroups(!showGroups);
|
|
1503
|
+
},
|
|
1504
|
+
children: [
|
|
1505
|
+
/* @__PURE__ */ jsx5("span", { style: iconSlotStyles2, children: showGroups && /* @__PURE__ */ jsx5(CheckIcon2, {}) }),
|
|
1506
|
+
/* @__PURE__ */ jsx5("span", { children: "View Schematic Groups" })
|
|
1507
|
+
]
|
|
1508
|
+
}
|
|
1509
|
+
),
|
|
1510
|
+
/* @__PURE__ */ jsxs3(
|
|
1511
|
+
DropdownMenu2.Item,
|
|
1512
|
+
{
|
|
1513
|
+
className: "sv-vm-item",
|
|
1514
|
+
style: itemStyles2,
|
|
1515
|
+
onSelect: (event) => event.preventDefault(),
|
|
1516
|
+
onPointerDown: (event) => {
|
|
1517
|
+
event.preventDefault();
|
|
1518
|
+
onToggleGrid(!showGrid);
|
|
1519
|
+
},
|
|
1520
|
+
children: [
|
|
1521
|
+
/* @__PURE__ */ jsx5("span", { style: iconSlotStyles2, children: showGrid && /* @__PURE__ */ jsx5(CheckIcon2, {}) }),
|
|
1522
|
+
/* @__PURE__ */ jsx5("span", { children: "Show Grid" })
|
|
1523
|
+
]
|
|
1524
|
+
}
|
|
1525
|
+
),
|
|
1526
|
+
/* @__PURE__ */ jsx5(DropdownMenu2.Separator, { style: separatorStyles }),
|
|
1527
|
+
/* @__PURE__ */ jsxs3(
|
|
1528
|
+
"div",
|
|
1529
|
+
{
|
|
1530
|
+
style: {
|
|
1531
|
+
padding: "4px 8px 4px 32px",
|
|
1532
|
+
fontSize: 11,
|
|
1533
|
+
opacity: 0.35,
|
|
1534
|
+
color: "#a1a1aa",
|
|
1535
|
+
letterSpacing: "0.2px",
|
|
1536
|
+
fontFamily: FONT_FAMILY2
|
|
1537
|
+
},
|
|
1538
|
+
children: [
|
|
1539
|
+
"@tscircuit/schematic-viewer@",
|
|
1540
|
+
String(package_default?.version)
|
|
1541
|
+
]
|
|
1542
|
+
}
|
|
1543
|
+
)
|
|
1544
|
+
]
|
|
1545
|
+
}
|
|
1546
|
+
) })
|
|
1547
|
+
] })
|
|
1548
|
+
}
|
|
1549
|
+
);
|
|
1550
|
+
};
|
|
1551
|
+
|
|
1914
1552
|
// lib/components/SchematicViewer.tsx
|
|
1915
|
-
import { jsx as
|
|
1553
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1916
1554
|
var SchematicViewer = ({
|
|
1917
1555
|
circuitJson,
|
|
1918
1556
|
containerStyle,
|
|
1919
|
-
editEvents: unappliedEditEvents = [],
|
|
1920
|
-
onEditEvent,
|
|
1921
|
-
defaultEditMode = false,
|
|
1922
1557
|
debugGrid = false,
|
|
1923
|
-
|
|
1924
|
-
debug: debug3 = false,
|
|
1558
|
+
debug: debug2 = false,
|
|
1925
1559
|
clickToInteractEnabled = false,
|
|
1926
1560
|
colorOverrides,
|
|
1927
1561
|
disableGroups = false,
|
|
1928
1562
|
netHoverHighlightEnabled = true,
|
|
1929
1563
|
onSchematicComponentClicked,
|
|
1930
|
-
showSchematicPorts
|
|
1564
|
+
showSchematicPorts,
|
|
1931
1565
|
onSchematicPortClicked,
|
|
1932
1566
|
onSchematicSheetChange,
|
|
1933
1567
|
css,
|
|
1934
1568
|
className
|
|
1935
1569
|
}) => {
|
|
1936
|
-
if (
|
|
1570
|
+
if (debug2) {
|
|
1937
1571
|
enableDebug();
|
|
1938
1572
|
}
|
|
1939
1573
|
const getCircuitHash = (circuitJson2) => {
|
|
@@ -1962,7 +1596,7 @@ var SchematicViewer = ({
|
|
|
1962
1596
|
return defaultSheetId;
|
|
1963
1597
|
}
|
|
1964
1598
|
);
|
|
1965
|
-
|
|
1599
|
+
useEffect9(() => {
|
|
1966
1600
|
const stillExists = selectedSheetId !== void 0 && schematicSheets.some((s) => s.schematic_sheet_id === selectedSheetId);
|
|
1967
1601
|
if (!stillExists) {
|
|
1968
1602
|
setSelectedSheetId(defaultSheetId);
|
|
@@ -1977,20 +1611,25 @@ var SchematicViewer = ({
|
|
|
1977
1611
|
},
|
|
1978
1612
|
[onSchematicSheetChange]
|
|
1979
1613
|
);
|
|
1980
|
-
const [editModeEnabled, setEditModeEnabled] = useState6(defaultEditMode);
|
|
1981
|
-
const [snapToGrid, setSnapToGrid] = useState6(true);
|
|
1982
1614
|
const [showGridInternal, setShowGridInternal] = useState6(false);
|
|
1983
1615
|
const showGrid = debugGrid || showGridInternal;
|
|
1984
1616
|
const [isInteractionEnabled, setIsInteractionEnabled] = useState6(
|
|
1985
1617
|
!clickToInteractEnabled
|
|
1986
1618
|
);
|
|
1987
|
-
const [showViewMenu, setShowViewMenu] = useState6(false);
|
|
1988
1619
|
const [showSchematicGroups, setShowSchematicGroups] = useState6(() => {
|
|
1989
1620
|
if (disableGroups) return false;
|
|
1990
|
-
return getStoredBoolean(
|
|
1621
|
+
return getStoredBoolean(STORAGE_KEYS.IS_SHOWING_SCHEMATIC_GROUPS, false);
|
|
1991
1622
|
});
|
|
1623
|
+
const [showSchematicPortsInternal, setShowSchematicPortsInternal] = useState6(
|
|
1624
|
+
() => showSchematicPorts ?? getStoredBoolean(STORAGE_KEYS.IS_SHOWING_SCHEMATIC_PORTS, false)
|
|
1625
|
+
);
|
|
1626
|
+
useEffect9(() => {
|
|
1627
|
+
if (showSchematicPorts !== void 0) {
|
|
1628
|
+
setShowSchematicPortsInternal(showSchematicPorts);
|
|
1629
|
+
}
|
|
1630
|
+
}, [showSchematicPorts]);
|
|
1992
1631
|
const [isHoveringClickableComponent, setIsHoveringClickableComponent] = useState6(false);
|
|
1993
|
-
const hoveringComponentsRef =
|
|
1632
|
+
const hoveringComponentsRef = useRef6(/* @__PURE__ */ new Set());
|
|
1994
1633
|
const handleComponentHoverChange = useCallback6(
|
|
1995
1634
|
(componentId, isHovering) => {
|
|
1996
1635
|
if (isHovering) {
|
|
@@ -2003,7 +1642,7 @@ var SchematicViewer = ({
|
|
|
2003
1642
|
[]
|
|
2004
1643
|
);
|
|
2005
1644
|
const [isHoveringClickablePort, setIsHoveringClickablePort] = useState6(false);
|
|
2006
|
-
const hoveringPortsRef =
|
|
1645
|
+
const hoveringPortsRef = useRef6(/* @__PURE__ */ new Set());
|
|
2007
1646
|
const handlePortHoverChange = useCallback6(
|
|
2008
1647
|
(portId, isHovering) => {
|
|
2009
1648
|
if (isHovering) {
|
|
@@ -2015,11 +1654,11 @@ var SchematicViewer = ({
|
|
|
2015
1654
|
},
|
|
2016
1655
|
[]
|
|
2017
1656
|
);
|
|
2018
|
-
const svgDivRef =
|
|
2019
|
-
const touchStartRef =
|
|
1657
|
+
const svgDivRef = useRef6(null);
|
|
1658
|
+
const touchStartRef = useRef6(null);
|
|
2020
1659
|
const schematicComponentIds = useMemo4(() => {
|
|
2021
1660
|
try {
|
|
2022
|
-
const components =
|
|
1661
|
+
const components = su4(circuitJson).schematic_component?.list() ?? [];
|
|
2023
1662
|
return components.filter(
|
|
2024
1663
|
(component) => !activeSheetId || component.schematic_sheet_id === activeSheetId
|
|
2025
1664
|
).map((component) => component.schematic_component_id);
|
|
@@ -2029,14 +1668,14 @@ var SchematicViewer = ({
|
|
|
2029
1668
|
}
|
|
2030
1669
|
}, [circuitJsonKey, circuitJson, activeSheetId]);
|
|
2031
1670
|
const schematicPortsInfo = useMemo4(() => {
|
|
2032
|
-
if (!
|
|
1671
|
+
if (!showSchematicPortsInternal) return [];
|
|
2033
1672
|
try {
|
|
2034
|
-
const ports = (
|
|
1673
|
+
const ports = (su4(circuitJson).schematic_port?.list() ?? []).filter(
|
|
2035
1674
|
(port) => !activeSheetId || port.schematic_sheet_id === activeSheetId
|
|
2036
1675
|
);
|
|
2037
1676
|
return ports.map((port) => {
|
|
2038
|
-
const sourcePort =
|
|
2039
|
-
const sourceComponent = sourcePort?.source_component_id ?
|
|
1677
|
+
const sourcePort = su4(circuitJson).source_port.get(port.source_port_id);
|
|
1678
|
+
const sourceComponent = sourcePort?.source_component_id ? su4(circuitJson).source_component.get(sourcePort.source_component_id) : null;
|
|
2040
1679
|
const componentName = sourceComponent?.name ?? "?";
|
|
2041
1680
|
const pinLabel = port.display_pin_label ?? sourcePort?.pin_number ?? sourcePort?.name ?? "?";
|
|
2042
1681
|
return {
|
|
@@ -2048,7 +1687,7 @@ var SchematicViewer = ({
|
|
|
2048
1687
|
console.error("Failed to derive schematic port info", err);
|
|
2049
1688
|
return [];
|
|
2050
1689
|
}
|
|
2051
|
-
}, [circuitJsonKey, circuitJson,
|
|
1690
|
+
}, [circuitJsonKey, circuitJson, showSchematicPortsInternal, activeSheetId]);
|
|
2052
1691
|
const handleTouchStart = (e) => {
|
|
2053
1692
|
const touch = e.touches[0];
|
|
2054
1693
|
touchStartRef.current = {
|
|
@@ -2068,35 +1707,36 @@ var SchematicViewer = ({
|
|
|
2068
1707
|
}
|
|
2069
1708
|
touchStartRef.current = null;
|
|
2070
1709
|
};
|
|
2071
|
-
const
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
}
|
|
2080
|
-
}, [circuitJson]);
|
|
2081
|
-
const {
|
|
2082
|
-
ref: containerRef,
|
|
2083
|
-
cancelDrag,
|
|
2084
|
-
transform: svgToScreenProjection
|
|
2085
|
-
} = useMouseMatrixTransform({
|
|
1710
|
+
const shouldPanSchematic = useCallback6(
|
|
1711
|
+
(event) => {
|
|
1712
|
+
if (event.type !== "mousedown" || !("button" in event)) return true;
|
|
1713
|
+
return event.button !== 2 && !(event.button === 0 && event.ctrlKey);
|
|
1714
|
+
},
|
|
1715
|
+
[]
|
|
1716
|
+
);
|
|
1717
|
+
const { ref: containerRef } = useMouseMatrixTransform({
|
|
2086
1718
|
onSetTransform(transform) {
|
|
2087
1719
|
if (!svgDivRef.current) return;
|
|
2088
1720
|
svgDivRef.current.style.transform = transformToString(transform);
|
|
2089
1721
|
},
|
|
2090
1722
|
// @ts-ignore disabled is a valid prop but not typed
|
|
2091
|
-
enabled: isInteractionEnabled
|
|
1723
|
+
enabled: isInteractionEnabled,
|
|
1724
|
+
shouldDrag: shouldPanSchematic
|
|
2092
1725
|
});
|
|
1726
|
+
const {
|
|
1727
|
+
menuVisible,
|
|
1728
|
+
menuPos,
|
|
1729
|
+
menuRef,
|
|
1730
|
+
setMenuVisible,
|
|
1731
|
+
contextMenuEventHandlers
|
|
1732
|
+
} = useContextMenu({ containerRef });
|
|
2093
1733
|
const { containerWidth, containerHeight } = useResizeHandling(containerRef);
|
|
2094
1734
|
const svgString = useMemo4(() => {
|
|
2095
1735
|
if (!containerWidth || !containerHeight) return "";
|
|
2096
1736
|
return convertCircuitJsonToSchematicSvg(circuitJson, {
|
|
2097
1737
|
width: containerWidth,
|
|
2098
1738
|
height: containerHeight || 720,
|
|
2099
|
-
drawPorts:
|
|
1739
|
+
drawPorts: showSchematicPortsInternal,
|
|
2100
1740
|
schematicSheetId: activeSheetId,
|
|
2101
1741
|
grid: !showGrid ? void 0 : {
|
|
2102
1742
|
cellSize: 1,
|
|
@@ -2111,7 +1751,7 @@ var SchematicViewer = ({
|
|
|
2111
1751
|
containerWidth,
|
|
2112
1752
|
containerHeight,
|
|
2113
1753
|
showGrid,
|
|
2114
|
-
|
|
1754
|
+
showSchematicPortsInternal,
|
|
2115
1755
|
activeSheetId
|
|
2116
1756
|
]);
|
|
2117
1757
|
const containerBackgroundColor = useMemo4(() => {
|
|
@@ -2120,55 +1760,6 @@ var SchematicViewer = ({
|
|
|
2120
1760
|
);
|
|
2121
1761
|
return match?.[1] ?? "transparent";
|
|
2122
1762
|
}, [svgString]);
|
|
2123
|
-
const realToSvgProjection = useMemo4(() => {
|
|
2124
|
-
if (!svgString) return identity();
|
|
2125
|
-
const transformString = svgString.match(
|
|
2126
|
-
/data-real-to-screen-transform="([^"]+)"/
|
|
2127
|
-
)?.[1];
|
|
2128
|
-
try {
|
|
2129
|
-
return fromString(transformString);
|
|
2130
|
-
} catch (e) {
|
|
2131
|
-
console.error(e);
|
|
2132
|
-
return identity();
|
|
2133
|
-
}
|
|
2134
|
-
}, [svgString]);
|
|
2135
|
-
const handleEditEvent = (event) => {
|
|
2136
|
-
setInternalEditEvents((prev) => [...prev, event]);
|
|
2137
|
-
if (onEditEvent) {
|
|
2138
|
-
onEditEvent(event);
|
|
2139
|
-
}
|
|
2140
|
-
};
|
|
2141
|
-
const editEventsWithUnappliedEditEvents = useMemo4(() => {
|
|
2142
|
-
return [...unappliedEditEvents, ...internalEditEvents];
|
|
2143
|
-
}, [unappliedEditEvents, internalEditEvents]);
|
|
2144
|
-
const {
|
|
2145
|
-
handleMouseDown,
|
|
2146
|
-
handleTouchStart: handleComponentTouchStart,
|
|
2147
|
-
isDragging,
|
|
2148
|
-
activeEditEvent
|
|
2149
|
-
} = useComponentDragging({
|
|
2150
|
-
onEditEvent: handleEditEvent,
|
|
2151
|
-
cancelDrag,
|
|
2152
|
-
realToSvgProjection,
|
|
2153
|
-
svgToScreenProjection,
|
|
2154
|
-
circuitJson,
|
|
2155
|
-
editEvents: editEventsWithUnappliedEditEvents,
|
|
2156
|
-
enabled: editModeEnabled && isInteractionEnabled,
|
|
2157
|
-
snapToGrid
|
|
2158
|
-
});
|
|
2159
|
-
useChangeSchematicComponentLocationsInSvg({
|
|
2160
|
-
svgDivRef,
|
|
2161
|
-
editEvents: editEventsWithUnappliedEditEvents,
|
|
2162
|
-
realToSvgProjection,
|
|
2163
|
-
svgToScreenProjection,
|
|
2164
|
-
activeEditEvent
|
|
2165
|
-
});
|
|
2166
|
-
useChangeSchematicTracesForMovedComponents({
|
|
2167
|
-
svgDivRef,
|
|
2168
|
-
circuitJson,
|
|
2169
|
-
activeEditEvent,
|
|
2170
|
-
editEvents: editEventsWithUnappliedEditEvents
|
|
2171
|
-
});
|
|
2172
1763
|
useSchematicGroupsOverlay({
|
|
2173
1764
|
svgDivRef,
|
|
2174
1765
|
circuitJson,
|
|
@@ -2181,12 +1772,8 @@ var SchematicViewer = ({
|
|
|
2181
1772
|
circuitJsonKey: `${circuitJsonKey}_${activeSheetId ?? ""}`,
|
|
2182
1773
|
enabled: netHoverHighlightEnabled
|
|
2183
1774
|
});
|
|
2184
|
-
const handleComponentTouchStartRef = useRef8(handleComponentTouchStart);
|
|
2185
|
-
useEffect11(() => {
|
|
2186
|
-
handleComponentTouchStartRef.current = handleComponentTouchStart;
|
|
2187
|
-
}, [handleComponentTouchStart]);
|
|
2188
1775
|
const svgDiv = useMemo4(
|
|
2189
|
-
() => /* @__PURE__ */
|
|
1776
|
+
() => /* @__PURE__ */ jsx6(
|
|
2190
1777
|
"div",
|
|
2191
1778
|
{
|
|
2192
1779
|
ref: svgDivRef,
|
|
@@ -2195,22 +1782,17 @@ var SchematicViewer = ({
|
|
|
2195
1782
|
transformOrigin: "0 0"
|
|
2196
1783
|
},
|
|
2197
1784
|
className: onSchematicComponentClicked ? "schematic-component-clickable" : void 0,
|
|
2198
|
-
onTouchStart: (e) => {
|
|
2199
|
-
if (editModeEnabled && isInteractionEnabled) {
|
|
2200
|
-
handleComponentTouchStartRef.current(e);
|
|
2201
|
-
}
|
|
2202
|
-
},
|
|
2203
1785
|
dangerouslySetInnerHTML: { __html: svgString }
|
|
2204
1786
|
}
|
|
2205
1787
|
),
|
|
2206
|
-
[svgString, isInteractionEnabled, clickToInteractEnabled
|
|
1788
|
+
[svgString, isInteractionEnabled, clickToInteractEnabled]
|
|
2207
1789
|
);
|
|
2208
|
-
return /* @__PURE__ */
|
|
2209
|
-
netHoverHighlightEnabled && /* @__PURE__ */
|
|
1790
|
+
return /* @__PURE__ */ jsxs4(MouseTracker, { children: [
|
|
1791
|
+
netHoverHighlightEnabled && /* @__PURE__ */ jsx6("style", { children: `.sch-net-faded { opacity: 0.35; }
|
|
2210
1792
|
svg :is(g.trace, g.trace-overlays, g[data-schematic-component-id], [data-schematic-net-label-id]) { transition: opacity 0.12s ease-in-out; }` }),
|
|
2211
|
-
onSchematicComponentClicked && /* @__PURE__ */
|
|
2212
|
-
onSchematicPortClicked && /* @__PURE__ */
|
|
2213
|
-
/* @__PURE__ */
|
|
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(
|
|
2214
1796
|
"div",
|
|
2215
1797
|
{
|
|
2216
1798
|
ref: containerRef,
|
|
@@ -2218,29 +1800,34 @@ var SchematicViewer = ({
|
|
|
2218
1800
|
position: "relative",
|
|
2219
1801
|
backgroundColor: containerBackgroundColor,
|
|
2220
1802
|
overflow: "hidden",
|
|
2221
|
-
cursor:
|
|
1803
|
+
cursor: clickToInteractEnabled && !isInteractionEnabled ? "pointer" : isHoveringClickableComponent && onSchematicComponentClicked ? "pointer" : isHoveringClickablePort && onSchematicPortClicked ? "pointer" : "grab",
|
|
2222
1804
|
minHeight: "300px",
|
|
1805
|
+
userSelect: "none",
|
|
1806
|
+
WebkitUserSelect: "none",
|
|
1807
|
+
WebkitTouchCallout: "none",
|
|
2223
1808
|
...containerStyle
|
|
2224
1809
|
},
|
|
2225
|
-
onMouseDown: (e) => {
|
|
2226
|
-
if (clickToInteractEnabled && !isInteractionEnabled) {
|
|
2227
|
-
e.preventDefault();
|
|
2228
|
-
e.stopPropagation();
|
|
2229
|
-
return;
|
|
2230
|
-
}
|
|
2231
|
-
handleMouseDown(e);
|
|
2232
|
-
},
|
|
2233
1810
|
onMouseDownCapture: (e) => {
|
|
1811
|
+
contextMenuEventHandlers.onMouseDown(e);
|
|
2234
1812
|
if (clickToInteractEnabled && !isInteractionEnabled) {
|
|
2235
1813
|
e.preventDefault();
|
|
2236
1814
|
e.stopPropagation();
|
|
2237
1815
|
return;
|
|
2238
1816
|
}
|
|
2239
1817
|
},
|
|
2240
|
-
|
|
2241
|
-
|
|
1818
|
+
onContextMenu: contextMenuEventHandlers.onContextMenu,
|
|
1819
|
+
onTouchStart: (event) => {
|
|
1820
|
+
handleTouchStart(event);
|
|
1821
|
+
contextMenuEventHandlers.onTouchStart(event);
|
|
1822
|
+
},
|
|
1823
|
+
onTouchMove: contextMenuEventHandlers.onTouchMove,
|
|
1824
|
+
onTouchEnd: (event) => {
|
|
1825
|
+
handleTouchEnd(event);
|
|
1826
|
+
contextMenuEventHandlers.onTouchEnd();
|
|
1827
|
+
},
|
|
1828
|
+
onTouchCancel: contextMenuEventHandlers.onTouchCancel,
|
|
2242
1829
|
children: [
|
|
2243
|
-
!isInteractionEnabled && clickToInteractEnabled && /* @__PURE__ */
|
|
1830
|
+
!isInteractionEnabled && clickToInteractEnabled && /* @__PURE__ */ jsx6(
|
|
2244
1831
|
"div",
|
|
2245
1832
|
{
|
|
2246
1833
|
onClick: (e) => {
|
|
@@ -2259,7 +1846,7 @@ var SchematicViewer = ({
|
|
|
2259
1846
|
pointerEvents: "all",
|
|
2260
1847
|
touchAction: "pan-x pan-y pinch-zoom"
|
|
2261
1848
|
},
|
|
2262
|
-
children: /* @__PURE__ */
|
|
1849
|
+
children: /* @__PURE__ */ jsx6(
|
|
2263
1850
|
"div",
|
|
2264
1851
|
{
|
|
2265
1852
|
style: {
|
|
@@ -2276,39 +1863,34 @@ var SchematicViewer = ({
|
|
|
2276
1863
|
)
|
|
2277
1864
|
}
|
|
2278
1865
|
),
|
|
2279
|
-
|
|
2280
|
-
EditIcon,
|
|
2281
|
-
{
|
|
2282
|
-
active: editModeEnabled,
|
|
2283
|
-
onClick: () => setEditModeEnabled(!editModeEnabled)
|
|
2284
|
-
}
|
|
2285
|
-
),
|
|
2286
|
-
editingEnabled && editModeEnabled && /* @__PURE__ */ jsx9(
|
|
2287
|
-
GridIcon,
|
|
2288
|
-
{
|
|
2289
|
-
active: snapToGrid,
|
|
2290
|
-
onClick: () => setSnapToGrid(!snapToGrid)
|
|
2291
|
-
}
|
|
2292
|
-
),
|
|
2293
|
-
/* @__PURE__ */ jsx9(
|
|
1866
|
+
menuVisible && /* @__PURE__ */ jsx6(
|
|
2294
1867
|
ViewMenu,
|
|
2295
1868
|
{
|
|
2296
1869
|
circuitJson,
|
|
2297
1870
|
circuitJsonKey,
|
|
2298
|
-
|
|
2299
|
-
|
|
1871
|
+
menuRef,
|
|
1872
|
+
menuPos,
|
|
1873
|
+
onOpenChange: setMenuVisible,
|
|
1874
|
+
showPorts: showSchematicPortsInternal,
|
|
1875
|
+
onTogglePorts: (value) => {
|
|
1876
|
+
setShowSchematicPortsInternal(value);
|
|
1877
|
+
setStoredBoolean(STORAGE_KEYS.IS_SHOWING_SCHEMATIC_PORTS, value);
|
|
1878
|
+
},
|
|
2300
1879
|
showGroups: showSchematicGroups,
|
|
2301
1880
|
onToggleGroups: (value) => {
|
|
2302
1881
|
if (!disableGroups) {
|
|
2303
1882
|
setShowSchematicGroups(value);
|
|
2304
|
-
setStoredBoolean(
|
|
1883
|
+
setStoredBoolean(
|
|
1884
|
+
STORAGE_KEYS.IS_SHOWING_SCHEMATIC_GROUPS,
|
|
1885
|
+
value
|
|
1886
|
+
);
|
|
2305
1887
|
}
|
|
2306
1888
|
},
|
|
2307
1889
|
showGrid,
|
|
2308
1890
|
onToggleGrid: setShowGridInternal
|
|
2309
1891
|
}
|
|
2310
1892
|
),
|
|
2311
|
-
/* @__PURE__ */
|
|
1893
|
+
/* @__PURE__ */ jsx6(
|
|
2312
1894
|
SchematicSheetSelector,
|
|
2313
1895
|
{
|
|
2314
1896
|
sheets: schematicSheets,
|
|
@@ -2316,7 +1898,7 @@ var SchematicViewer = ({
|
|
|
2316
1898
|
onSelectSheet: handleSelectSheet
|
|
2317
1899
|
}
|
|
2318
1900
|
),
|
|
2319
|
-
onSchematicComponentClicked && schematicComponentIds.map((componentId) => /* @__PURE__ */
|
|
1901
|
+
onSchematicComponentClicked && schematicComponentIds.map((componentId) => /* @__PURE__ */ jsx6(
|
|
2320
1902
|
SchematicComponentMouseTarget,
|
|
2321
1903
|
{
|
|
2322
1904
|
componentId,
|
|
@@ -2335,7 +1917,7 @@ var SchematicViewer = ({
|
|
|
2335
1917
|
componentId
|
|
2336
1918
|
)),
|
|
2337
1919
|
svgDiv,
|
|
2338
|
-
|
|
1920
|
+
showSchematicPortsInternal && schematicPortsInfo.map(({ portId, label }) => /* @__PURE__ */ jsx6(
|
|
2339
1921
|
SchematicPortMouseTarget,
|
|
2340
1922
|
{
|
|
2341
1923
|
portId,
|
|
@@ -2365,7 +1947,7 @@ import {
|
|
|
2365
1947
|
convertCircuitJsonToSchematicSimulationSvg,
|
|
2366
1948
|
convertCircuitJsonToSimulationGraphSvg
|
|
2367
1949
|
} from "circuit-to-svg";
|
|
2368
|
-
import { useEffect as
|
|
1950
|
+
import { useEffect as useEffect10, useMemo as useMemo5, useRef as useRef7, useState as useState8 } from "react";
|
|
2369
1951
|
import { toString as transformToString2 } from "transformation-matrix";
|
|
2370
1952
|
import { useMouseMatrixTransform as useMouseMatrixTransform2 } from "use-mouse-matrix-transform";
|
|
2371
1953
|
|
|
@@ -2384,7 +1966,7 @@ var getAnalogSimulationBackgroundColor = (simulationSvg, colorOverrides) => getR
|
|
|
2384
1966
|
// lib/components/AnalogSimulationSelector.tsx
|
|
2385
1967
|
import * as DropdownMenu3 from "@radix-ui/react-dropdown-menu";
|
|
2386
1968
|
import { useState as useState7 } from "react";
|
|
2387
|
-
import { Fragment as Fragment4, jsx as
|
|
1969
|
+
import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2388
1970
|
var FONT_FAMILY3 = 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
2389
1971
|
var contentStyles3 = {
|
|
2390
1972
|
backgroundColor: "#ffffff",
|
|
@@ -2434,7 +2016,7 @@ var MENU_CSS2 = `
|
|
|
2434
2016
|
.sv-simulation-chevron { transition: transform 0.2s ease; }
|
|
2435
2017
|
[data-state="open"] > .sv-simulation-chevron { transform: rotate(180deg); }
|
|
2436
2018
|
`;
|
|
2437
|
-
var CheckIcon3 = () => /* @__PURE__ */
|
|
2019
|
+
var CheckIcon3 = () => /* @__PURE__ */ jsx7(
|
|
2438
2020
|
"svg",
|
|
2439
2021
|
{
|
|
2440
2022
|
width: "14",
|
|
@@ -2446,10 +2028,10 @@ var CheckIcon3 = () => /* @__PURE__ */ jsx10(
|
|
|
2446
2028
|
strokeLinecap: "round",
|
|
2447
2029
|
strokeLinejoin: "round",
|
|
2448
2030
|
"aria-hidden": "true",
|
|
2449
|
-
children: /* @__PURE__ */
|
|
2031
|
+
children: /* @__PURE__ */ jsx7("path", { d: "M20 6 9 17l-5-5" })
|
|
2450
2032
|
}
|
|
2451
2033
|
);
|
|
2452
|
-
var ChevronDownIcon2 = ({ className }) => /* @__PURE__ */
|
|
2034
|
+
var ChevronDownIcon2 = ({ className }) => /* @__PURE__ */ jsx7(
|
|
2453
2035
|
"svg",
|
|
2454
2036
|
{
|
|
2455
2037
|
className,
|
|
@@ -2463,7 +2045,7 @@ var ChevronDownIcon2 = ({ className }) => /* @__PURE__ */ jsx10(
|
|
|
2463
2045
|
strokeLinejoin: "round",
|
|
2464
2046
|
style: { opacity: 0.6, flexShrink: 0 },
|
|
2465
2047
|
"aria-hidden": "true",
|
|
2466
|
-
children: /* @__PURE__ */
|
|
2048
|
+
children: /* @__PURE__ */ jsx7("path", { d: "m6 9 6 6 6-6" })
|
|
2467
2049
|
}
|
|
2468
2050
|
);
|
|
2469
2051
|
var getSimulationLabels = (simulations) => {
|
|
@@ -2489,10 +2071,10 @@ var AnalogSimulationSelector = ({
|
|
|
2489
2071
|
({ simulation }) => simulation.simulation_experiment_id === selectedSimulationExperimentId
|
|
2490
2072
|
);
|
|
2491
2073
|
const selectedLabel = selectedSimulation?.label ?? "Select simulation";
|
|
2492
|
-
return /* @__PURE__ */
|
|
2493
|
-
/* @__PURE__ */
|
|
2494
|
-
/* @__PURE__ */
|
|
2495
|
-
/* @__PURE__ */
|
|
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(
|
|
2496
2078
|
"button",
|
|
2497
2079
|
{
|
|
2498
2080
|
type: "button",
|
|
@@ -2519,13 +2101,13 @@ var AnalogSimulationSelector = ({
|
|
|
2519
2101
|
zIndex: zIndexMap.viewMenuIcon
|
|
2520
2102
|
},
|
|
2521
2103
|
children: [
|
|
2522
|
-
/* @__PURE__ */
|
|
2523
|
-
/* @__PURE__ */
|
|
2524
|
-
/* @__PURE__ */
|
|
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" })
|
|
2525
2107
|
]
|
|
2526
2108
|
}
|
|
2527
2109
|
) }),
|
|
2528
|
-
/* @__PURE__ */
|
|
2110
|
+
/* @__PURE__ */ jsx7(DropdownMenu3.Portal, { children: /* @__PURE__ */ jsx7(
|
|
2529
2111
|
DropdownMenu3.Content,
|
|
2530
2112
|
{
|
|
2531
2113
|
style: contentStyles3,
|
|
@@ -2535,7 +2117,7 @@ var AnalogSimulationSelector = ({
|
|
|
2535
2117
|
collisionPadding: 10,
|
|
2536
2118
|
children: simulationLabels.map(({ simulation, label }) => {
|
|
2537
2119
|
const selected = simulation.simulation_experiment_id === selectedSimulationExperimentId;
|
|
2538
|
-
return /* @__PURE__ */
|
|
2120
|
+
return /* @__PURE__ */ jsxs5(
|
|
2539
2121
|
DropdownMenu3.Item,
|
|
2540
2122
|
{
|
|
2541
2123
|
className: "sv-simulation-item",
|
|
@@ -2547,8 +2129,8 @@ var AnalogSimulationSelector = ({
|
|
|
2547
2129
|
setOpen(false);
|
|
2548
2130
|
},
|
|
2549
2131
|
children: [
|
|
2550
|
-
/* @__PURE__ */
|
|
2551
|
-
/* @__PURE__ */
|
|
2132
|
+
/* @__PURE__ */ jsx7("span", { style: iconSlotStyles3, children: selected && /* @__PURE__ */ jsx7(CheckIcon3, {}) }),
|
|
2133
|
+
/* @__PURE__ */ jsx7("span", { style: { ...ellipsisStyles2, minWidth: 0 }, children: label })
|
|
2552
2134
|
]
|
|
2553
2135
|
},
|
|
2554
2136
|
simulation.simulation_experiment_id
|
|
@@ -2561,7 +2143,7 @@ var AnalogSimulationSelector = ({
|
|
|
2561
2143
|
};
|
|
2562
2144
|
|
|
2563
2145
|
// lib/components/AnalogSimulationViewer.tsx
|
|
2564
|
-
import { jsx as
|
|
2146
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2565
2147
|
var DEFAULT_RENDER_WIDTH = 1200;
|
|
2566
2148
|
var DEFAULT_COMBINED_RENDER_ASPECT_RATIO = 1;
|
|
2567
2149
|
var DEFAULT_GRAPH_ONLY_RENDER_ASPECT_RATIO = 2;
|
|
@@ -2580,8 +2162,8 @@ var AnalogSimulationViewer = ({
|
|
|
2580
2162
|
const [isLoading, setIsLoading] = useState8(true);
|
|
2581
2163
|
const [error, setError] = useState8(null);
|
|
2582
2164
|
const [svgObjectUrl, setSvgObjectUrl] = useState8(null);
|
|
2583
|
-
const containerRef =
|
|
2584
|
-
const imgRef =
|
|
2165
|
+
const containerRef = useRef7(null);
|
|
2166
|
+
const imgRef = useRef7(null);
|
|
2585
2167
|
const { containerWidth } = useResizeHandling(
|
|
2586
2168
|
containerRef
|
|
2587
2169
|
);
|
|
@@ -2601,7 +2183,7 @@ var AnalogSimulationViewer = ({
|
|
|
2601
2183
|
const renderAspectRatio = width && height ? width / height : defaultRenderAspectRatio;
|
|
2602
2184
|
const effectiveWidth = width || (height ? height * renderAspectRatio : containerWidth) || DEFAULT_RENDER_WIDTH;
|
|
2603
2185
|
const effectiveHeight = height || effectiveWidth / renderAspectRatio;
|
|
2604
|
-
|
|
2186
|
+
useEffect10(() => {
|
|
2605
2187
|
setIsLoading(true);
|
|
2606
2188
|
setError(null);
|
|
2607
2189
|
setCircuitJson(inputCircuitJson);
|
|
@@ -2617,7 +2199,7 @@ var AnalogSimulationViewer = ({
|
|
|
2617
2199
|
const simulationExperimentId = (selectedSimulationExperimentId && simulationExperiments.some(
|
|
2618
2200
|
(simulation) => simulation.simulation_experiment_id === selectedSimulationExperimentId
|
|
2619
2201
|
) ? selectedSimulationExperimentId : simulationExperiments[0]?.simulation_experiment_id) ?? null;
|
|
2620
|
-
|
|
2202
|
+
useEffect10(() => {
|
|
2621
2203
|
if (simulationExperimentId !== selectedSimulationExperimentId) {
|
|
2622
2204
|
setSelectedSimulationExperimentId(simulationExperimentId);
|
|
2623
2205
|
}
|
|
@@ -2654,7 +2236,7 @@ var AnalogSimulationViewer = ({
|
|
|
2654
2236
|
simulationExperimentId,
|
|
2655
2237
|
acSweepView
|
|
2656
2238
|
]);
|
|
2657
|
-
|
|
2239
|
+
useEffect10(() => {
|
|
2658
2240
|
if (!simulationSvg) {
|
|
2659
2241
|
setSvgObjectUrl(null);
|
|
2660
2242
|
return;
|
|
@@ -2680,7 +2262,7 @@ var AnalogSimulationViewer = ({
|
|
|
2680
2262
|
const handleTouchStart = (_e) => {
|
|
2681
2263
|
setIsDragging(true);
|
|
2682
2264
|
};
|
|
2683
|
-
|
|
2265
|
+
useEffect10(() => {
|
|
2684
2266
|
const handleMouseUp = () => {
|
|
2685
2267
|
setIsDragging(false);
|
|
2686
2268
|
};
|
|
@@ -2695,7 +2277,7 @@ var AnalogSimulationViewer = ({
|
|
|
2695
2277
|
};
|
|
2696
2278
|
}, []);
|
|
2697
2279
|
if (isLoading) {
|
|
2698
|
-
return /* @__PURE__ */
|
|
2280
|
+
return /* @__PURE__ */ jsx8(
|
|
2699
2281
|
"div",
|
|
2700
2282
|
{
|
|
2701
2283
|
style: {
|
|
@@ -2715,7 +2297,7 @@ var AnalogSimulationViewer = ({
|
|
|
2715
2297
|
);
|
|
2716
2298
|
}
|
|
2717
2299
|
if (error) {
|
|
2718
|
-
return /* @__PURE__ */
|
|
2300
|
+
return /* @__PURE__ */ jsx8(
|
|
2719
2301
|
"div",
|
|
2720
2302
|
{
|
|
2721
2303
|
style: {
|
|
@@ -2730,15 +2312,15 @@ var AnalogSimulationViewer = ({
|
|
|
2730
2312
|
...containerStyle
|
|
2731
2313
|
},
|
|
2732
2314
|
className,
|
|
2733
|
-
children: /* @__PURE__ */
|
|
2734
|
-
/* @__PURE__ */
|
|
2735
|
-
/* @__PURE__ */
|
|
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 })
|
|
2736
2318
|
] })
|
|
2737
2319
|
}
|
|
2738
2320
|
);
|
|
2739
2321
|
}
|
|
2740
2322
|
if (!simulationSvg) {
|
|
2741
|
-
return /* @__PURE__ */
|
|
2323
|
+
return /* @__PURE__ */ jsxs6(
|
|
2742
2324
|
"div",
|
|
2743
2325
|
{
|
|
2744
2326
|
style: {
|
|
@@ -2754,11 +2336,11 @@ var AnalogSimulationViewer = ({
|
|
|
2754
2336
|
},
|
|
2755
2337
|
className,
|
|
2756
2338
|
children: [
|
|
2757
|
-
/* @__PURE__ */
|
|
2758
|
-
/* @__PURE__ */
|
|
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: [
|
|
2759
2341
|
"Use",
|
|
2760
2342
|
" ",
|
|
2761
|
-
/* @__PURE__ */
|
|
2343
|
+
/* @__PURE__ */ jsx8(
|
|
2762
2344
|
"code",
|
|
2763
2345
|
{
|
|
2764
2346
|
style: {
|
|
@@ -2778,7 +2360,7 @@ var AnalogSimulationViewer = ({
|
|
|
2778
2360
|
}
|
|
2779
2361
|
);
|
|
2780
2362
|
}
|
|
2781
|
-
return /* @__PURE__ */
|
|
2363
|
+
return /* @__PURE__ */ jsxs6(
|
|
2782
2364
|
"div",
|
|
2783
2365
|
{
|
|
2784
2366
|
ref: (node) => {
|
|
@@ -2797,7 +2379,7 @@ var AnalogSimulationViewer = ({
|
|
|
2797
2379
|
onMouseDown: handleMouseDown,
|
|
2798
2380
|
onTouchStart: handleTouchStart,
|
|
2799
2381
|
children: [
|
|
2800
|
-
/* @__PURE__ */
|
|
2382
|
+
/* @__PURE__ */ jsx8(
|
|
2801
2383
|
AnalogSimulationSelector,
|
|
2802
2384
|
{
|
|
2803
2385
|
simulations: simulationExperiments,
|
|
@@ -2805,7 +2387,7 @@ var AnalogSimulationViewer = ({
|
|
|
2805
2387
|
onSelectSimulation: handleSelectSimulation
|
|
2806
2388
|
}
|
|
2807
2389
|
),
|
|
2808
|
-
svgObjectUrl ? /* @__PURE__ */
|
|
2390
|
+
svgObjectUrl ? /* @__PURE__ */ jsx8(
|
|
2809
2391
|
"img",
|
|
2810
2392
|
{
|
|
2811
2393
|
ref: imgRef,
|
|
@@ -2819,7 +2401,7 @@ var AnalogSimulationViewer = ({
|
|
|
2819
2401
|
objectFit: "contain"
|
|
2820
2402
|
}
|
|
2821
2403
|
}
|
|
2822
|
-
) : /* @__PURE__ */
|
|
2404
|
+
) : /* @__PURE__ */ jsx8(
|
|
2823
2405
|
"div",
|
|
2824
2406
|
{
|
|
2825
2407
|
style: {
|