@tscircuit/schematic-viewer 2.0.42 → 2.0.44
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/.github/workflows/bun-pver-release.yml +20 -2
- package/dist/index.d.ts +25 -2
- package/dist/index.js +411 -40
- package/dist/index.js.map +1 -1
- package/examples/example14-schematic-component-click.fixture.tsx +46 -0
- package/lib/components/ControlledSchematicViewer.tsx +6 -0
- package/lib/components/MouseTracker.tsx +227 -0
- package/lib/components/SchematicComponentMouseTarget.tsx +182 -0
- package/lib/components/SchematicViewer.tsx +162 -122
- package/lib/hooks/useMouseEventsOverBoundingBox.ts +74 -0
- package/lib/index.ts +2 -0
- package/lib/utils/z-index-map.ts +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
convertCircuitJsonToSchematicSvg
|
|
4
4
|
} from "circuit-to-svg";
|
|
5
|
+
import { su as su6 } from "@tscircuit/soup-util";
|
|
5
6
|
|
|
6
7
|
// lib/hooks/useChangeSchematicComponentLocationsInSvg.ts
|
|
7
8
|
import "@tscircuit/soup-util";
|
|
@@ -469,7 +470,7 @@ var enableDebug = () => {
|
|
|
469
470
|
var debug_default = debug;
|
|
470
471
|
|
|
471
472
|
// lib/components/SchematicViewer.tsx
|
|
472
|
-
import { useEffect as
|
|
473
|
+
import { useEffect as useEffect11, useMemo as useMemo5, useRef as useRef7, useState as useState6 } from "react";
|
|
473
474
|
import {
|
|
474
475
|
fromString,
|
|
475
476
|
identity,
|
|
@@ -691,7 +692,8 @@ var zIndexMap = {
|
|
|
691
692
|
viewMenuIcon: 48,
|
|
692
693
|
viewMenu: 55,
|
|
693
694
|
viewMenuBackdrop: 54,
|
|
694
|
-
clickToInteractOverlay: 100
|
|
695
|
+
clickToInteractOverlay: 100,
|
|
696
|
+
schematicComponentHoverOutline: 47
|
|
695
697
|
};
|
|
696
698
|
|
|
697
699
|
// lib/components/EditIcon.tsx
|
|
@@ -846,7 +848,7 @@ import { su as su5 } from "@tscircuit/soup-util";
|
|
|
846
848
|
// package.json
|
|
847
849
|
var package_default = {
|
|
848
850
|
name: "@tscircuit/schematic-viewer",
|
|
849
|
-
version: "2.0.
|
|
851
|
+
version: "2.0.43",
|
|
850
852
|
main: "dist/index.js",
|
|
851
853
|
type: "module",
|
|
852
854
|
scripts: {
|
|
@@ -1776,8 +1778,349 @@ var setStoredBoolean = (key, value) => {
|
|
|
1776
1778
|
}
|
|
1777
1779
|
};
|
|
1778
1780
|
|
|
1781
|
+
// lib/components/MouseTracker.tsx
|
|
1782
|
+
import {
|
|
1783
|
+
createContext,
|
|
1784
|
+
useCallback as useCallback3,
|
|
1785
|
+
useContext,
|
|
1786
|
+
useEffect as useEffect8,
|
|
1787
|
+
useMemo as useMemo3,
|
|
1788
|
+
useRef as useRef4
|
|
1789
|
+
} from "react";
|
|
1790
|
+
import { Fragment as Fragment2, jsx as jsx9 } from "react/jsx-runtime";
|
|
1791
|
+
var MouseTrackerContext = createContext(null);
|
|
1792
|
+
var boundsAreEqual = (a, b) => {
|
|
1793
|
+
if (!a && !b) return true;
|
|
1794
|
+
if (!a || !b) return false;
|
|
1795
|
+
return a.minX === b.minX && a.maxX === b.maxX && a.minY === b.minY && a.maxY === b.maxY;
|
|
1796
|
+
};
|
|
1797
|
+
var MouseTracker = ({ children }) => {
|
|
1798
|
+
const existingContext = useContext(MouseTrackerContext);
|
|
1799
|
+
if (existingContext) {
|
|
1800
|
+
return /* @__PURE__ */ jsx9(Fragment2, { children });
|
|
1801
|
+
}
|
|
1802
|
+
const storeRef = useRef4({
|
|
1803
|
+
pointer: null,
|
|
1804
|
+
boundingBoxes: /* @__PURE__ */ new Map(),
|
|
1805
|
+
hoveringIds: /* @__PURE__ */ new Set(),
|
|
1806
|
+
subscribers: /* @__PURE__ */ new Set()
|
|
1807
|
+
});
|
|
1808
|
+
const notifySubscribers = useCallback3(() => {
|
|
1809
|
+
for (const callback of storeRef.current.subscribers) {
|
|
1810
|
+
callback();
|
|
1811
|
+
}
|
|
1812
|
+
}, []);
|
|
1813
|
+
const updateHovering = useCallback3(() => {
|
|
1814
|
+
const pointer = storeRef.current.pointer;
|
|
1815
|
+
const newHovering = /* @__PURE__ */ new Set();
|
|
1816
|
+
if (pointer) {
|
|
1817
|
+
for (const [id, registration] of storeRef.current.boundingBoxes) {
|
|
1818
|
+
const bounds = registration.bounds;
|
|
1819
|
+
if (!bounds) continue;
|
|
1820
|
+
if (pointer.x >= bounds.minX && pointer.x <= bounds.maxX && pointer.y >= bounds.minY && pointer.y <= bounds.maxY) {
|
|
1821
|
+
newHovering.add(id);
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
const prevHovering = storeRef.current.hoveringIds;
|
|
1826
|
+
if (newHovering.size === prevHovering.size && [...newHovering].every((id) => prevHovering.has(id))) {
|
|
1827
|
+
return;
|
|
1828
|
+
}
|
|
1829
|
+
storeRef.current.hoveringIds = newHovering;
|
|
1830
|
+
notifySubscribers();
|
|
1831
|
+
}, [notifySubscribers]);
|
|
1832
|
+
const registerBoundingBox = useCallback3(
|
|
1833
|
+
(id, registration) => {
|
|
1834
|
+
storeRef.current.boundingBoxes.set(id, registration);
|
|
1835
|
+
updateHovering();
|
|
1836
|
+
},
|
|
1837
|
+
[updateHovering]
|
|
1838
|
+
);
|
|
1839
|
+
const updateBoundingBox = useCallback3(
|
|
1840
|
+
(id, registration) => {
|
|
1841
|
+
const existing = storeRef.current.boundingBoxes.get(id);
|
|
1842
|
+
if (existing && boundsAreEqual(existing.bounds, registration.bounds) && existing.onClick === registration.onClick) {
|
|
1843
|
+
return;
|
|
1844
|
+
}
|
|
1845
|
+
storeRef.current.boundingBoxes.set(id, registration);
|
|
1846
|
+
updateHovering();
|
|
1847
|
+
},
|
|
1848
|
+
[updateHovering]
|
|
1849
|
+
);
|
|
1850
|
+
const unregisterBoundingBox = useCallback3(
|
|
1851
|
+
(id) => {
|
|
1852
|
+
const removed = storeRef.current.boundingBoxes.delete(id);
|
|
1853
|
+
if (removed) {
|
|
1854
|
+
updateHovering();
|
|
1855
|
+
}
|
|
1856
|
+
},
|
|
1857
|
+
[updateHovering]
|
|
1858
|
+
);
|
|
1859
|
+
const subscribe = useCallback3((listener) => {
|
|
1860
|
+
storeRef.current.subscribers.add(listener);
|
|
1861
|
+
return () => {
|
|
1862
|
+
storeRef.current.subscribers.delete(listener);
|
|
1863
|
+
};
|
|
1864
|
+
}, []);
|
|
1865
|
+
const isHovering = useCallback3((id) => {
|
|
1866
|
+
return storeRef.current.hoveringIds.has(id);
|
|
1867
|
+
}, []);
|
|
1868
|
+
useEffect8(() => {
|
|
1869
|
+
const handlePointerPosition = (event) => {
|
|
1870
|
+
const { clientX, clientY } = event;
|
|
1871
|
+
const pointer = storeRef.current.pointer;
|
|
1872
|
+
if (pointer && pointer.x === clientX && pointer.y === clientY) {
|
|
1873
|
+
return;
|
|
1874
|
+
}
|
|
1875
|
+
storeRef.current.pointer = { x: clientX, y: clientY };
|
|
1876
|
+
updateHovering();
|
|
1877
|
+
};
|
|
1878
|
+
const handlePointerLeave = () => {
|
|
1879
|
+
if (storeRef.current.pointer === null) return;
|
|
1880
|
+
storeRef.current.pointer = null;
|
|
1881
|
+
updateHovering();
|
|
1882
|
+
};
|
|
1883
|
+
const handleClick = (event) => {
|
|
1884
|
+
const { clientX, clientY } = event;
|
|
1885
|
+
for (const registration of storeRef.current.boundingBoxes.values()) {
|
|
1886
|
+
const bounds = registration.bounds;
|
|
1887
|
+
if (!bounds) continue;
|
|
1888
|
+
if (clientX >= bounds.minX && clientX <= bounds.maxX && clientY >= bounds.minY && clientY <= bounds.maxY) {
|
|
1889
|
+
registration.onClick?.(event);
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
};
|
|
1893
|
+
window.addEventListener("pointermove", handlePointerPosition, {
|
|
1894
|
+
passive: true
|
|
1895
|
+
});
|
|
1896
|
+
window.addEventListener("pointerdown", handlePointerPosition, {
|
|
1897
|
+
passive: true
|
|
1898
|
+
});
|
|
1899
|
+
window.addEventListener("pointerup", handlePointerPosition, {
|
|
1900
|
+
passive: true
|
|
1901
|
+
});
|
|
1902
|
+
window.addEventListener("pointerleave", handlePointerLeave);
|
|
1903
|
+
window.addEventListener("pointercancel", handlePointerLeave);
|
|
1904
|
+
window.addEventListener("blur", handlePointerLeave);
|
|
1905
|
+
window.addEventListener("click", handleClick, { passive: true });
|
|
1906
|
+
return () => {
|
|
1907
|
+
window.removeEventListener("pointermove", handlePointerPosition);
|
|
1908
|
+
window.removeEventListener("pointerdown", handlePointerPosition);
|
|
1909
|
+
window.removeEventListener("pointerup", handlePointerPosition);
|
|
1910
|
+
window.removeEventListener("pointerleave", handlePointerLeave);
|
|
1911
|
+
window.removeEventListener("pointercancel", handlePointerLeave);
|
|
1912
|
+
window.removeEventListener("blur", handlePointerLeave);
|
|
1913
|
+
window.removeEventListener("click", handleClick);
|
|
1914
|
+
};
|
|
1915
|
+
}, [updateHovering]);
|
|
1916
|
+
const value = useMemo3(
|
|
1917
|
+
() => ({
|
|
1918
|
+
registerBoundingBox,
|
|
1919
|
+
updateBoundingBox,
|
|
1920
|
+
unregisterBoundingBox,
|
|
1921
|
+
subscribe,
|
|
1922
|
+
isHovering
|
|
1923
|
+
}),
|
|
1924
|
+
[
|
|
1925
|
+
registerBoundingBox,
|
|
1926
|
+
updateBoundingBox,
|
|
1927
|
+
unregisterBoundingBox,
|
|
1928
|
+
subscribe,
|
|
1929
|
+
isHovering
|
|
1930
|
+
]
|
|
1931
|
+
);
|
|
1932
|
+
return /* @__PURE__ */ jsx9(MouseTrackerContext.Provider, { value, children });
|
|
1933
|
+
};
|
|
1934
|
+
|
|
1935
|
+
// lib/components/SchematicComponentMouseTarget.tsx
|
|
1936
|
+
import { useCallback as useCallback4, useEffect as useEffect10, useRef as useRef6, useState as useState5 } from "react";
|
|
1937
|
+
|
|
1938
|
+
// lib/hooks/useMouseEventsOverBoundingBox.ts
|
|
1939
|
+
import {
|
|
1940
|
+
useContext as useContext2,
|
|
1941
|
+
useEffect as useEffect9,
|
|
1942
|
+
useId,
|
|
1943
|
+
useMemo as useMemo4,
|
|
1944
|
+
useRef as useRef5,
|
|
1945
|
+
useSyncExternalStore
|
|
1946
|
+
} from "react";
|
|
1947
|
+
var useMouseEventsOverBoundingBox = (options) => {
|
|
1948
|
+
const context = useContext2(MouseTrackerContext);
|
|
1949
|
+
if (!context) {
|
|
1950
|
+
throw new Error(
|
|
1951
|
+
"useMouseEventsOverBoundingBox must be used within a MouseTracker"
|
|
1952
|
+
);
|
|
1953
|
+
}
|
|
1954
|
+
const id = useId();
|
|
1955
|
+
const latestOptionsRef = useRef5(options);
|
|
1956
|
+
latestOptionsRef.current = options;
|
|
1957
|
+
const handleClick = useMemo4(
|
|
1958
|
+
() => (event) => {
|
|
1959
|
+
latestOptionsRef.current.onClick?.(event);
|
|
1960
|
+
},
|
|
1961
|
+
[]
|
|
1962
|
+
);
|
|
1963
|
+
useEffect9(() => {
|
|
1964
|
+
context.registerBoundingBox(id, {
|
|
1965
|
+
bounds: latestOptionsRef.current.bounds,
|
|
1966
|
+
onClick: latestOptionsRef.current.onClick ? handleClick : void 0
|
|
1967
|
+
});
|
|
1968
|
+
return () => {
|
|
1969
|
+
context.unregisterBoundingBox(id);
|
|
1970
|
+
};
|
|
1971
|
+
}, [context, handleClick, id]);
|
|
1972
|
+
useEffect9(() => {
|
|
1973
|
+
context.updateBoundingBox(id, {
|
|
1974
|
+
bounds: latestOptionsRef.current.bounds,
|
|
1975
|
+
onClick: latestOptionsRef.current.onClick ? handleClick : void 0
|
|
1976
|
+
});
|
|
1977
|
+
}, [
|
|
1978
|
+
context,
|
|
1979
|
+
handleClick,
|
|
1980
|
+
id,
|
|
1981
|
+
options.bounds?.minX,
|
|
1982
|
+
options.bounds?.maxX,
|
|
1983
|
+
options.bounds?.minY,
|
|
1984
|
+
options.bounds?.maxY,
|
|
1985
|
+
options.onClick
|
|
1986
|
+
]);
|
|
1987
|
+
const hovering = useSyncExternalStore(
|
|
1988
|
+
context.subscribe,
|
|
1989
|
+
() => context.isHovering(id),
|
|
1990
|
+
() => false
|
|
1991
|
+
);
|
|
1992
|
+
return { hovering };
|
|
1993
|
+
};
|
|
1994
|
+
|
|
1995
|
+
// lib/components/SchematicComponentMouseTarget.tsx
|
|
1996
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
1997
|
+
var areMeasurementsEqual = (a, b) => {
|
|
1998
|
+
if (!a && !b) return true;
|
|
1999
|
+
if (!a || !b) return false;
|
|
2000
|
+
return Math.abs(a.bounds.minX - b.bounds.minX) < 0.5 && Math.abs(a.bounds.maxX - b.bounds.maxX) < 0.5 && Math.abs(a.bounds.minY - b.bounds.minY) < 0.5 && Math.abs(a.bounds.maxY - b.bounds.maxY) < 0.5 && Math.abs(a.rect.left - b.rect.left) < 0.5 && Math.abs(a.rect.top - b.rect.top) < 0.5 && Math.abs(a.rect.width - b.rect.width) < 0.5 && Math.abs(a.rect.height - b.rect.height) < 0.5;
|
|
2001
|
+
};
|
|
2002
|
+
var SchematicComponentMouseTarget = ({
|
|
2003
|
+
componentId,
|
|
2004
|
+
svgDivRef,
|
|
2005
|
+
containerRef,
|
|
2006
|
+
onComponentClick,
|
|
2007
|
+
showOutline,
|
|
2008
|
+
circuitJsonKey
|
|
2009
|
+
}) => {
|
|
2010
|
+
const [measurement, setMeasurement] = useState5(null);
|
|
2011
|
+
const frameRef = useRef6(null);
|
|
2012
|
+
const measure = useCallback4(() => {
|
|
2013
|
+
frameRef.current = null;
|
|
2014
|
+
const svgDiv = svgDivRef.current;
|
|
2015
|
+
const container = containerRef.current;
|
|
2016
|
+
if (!svgDiv || !container) {
|
|
2017
|
+
setMeasurement((prev) => prev ? null : prev);
|
|
2018
|
+
return;
|
|
2019
|
+
}
|
|
2020
|
+
const element = svgDiv.querySelector(
|
|
2021
|
+
`[data-schematic-component-id="${componentId}"]`
|
|
2022
|
+
);
|
|
2023
|
+
if (!element) {
|
|
2024
|
+
setMeasurement((prev) => prev ? null : prev);
|
|
2025
|
+
return;
|
|
2026
|
+
}
|
|
2027
|
+
const elementRect = element.getBoundingClientRect();
|
|
2028
|
+
const containerRect = container.getBoundingClientRect();
|
|
2029
|
+
const nextMeasurement = {
|
|
2030
|
+
bounds: {
|
|
2031
|
+
minX: elementRect.left,
|
|
2032
|
+
maxX: elementRect.right,
|
|
2033
|
+
minY: elementRect.top,
|
|
2034
|
+
maxY: elementRect.bottom
|
|
2035
|
+
},
|
|
2036
|
+
rect: {
|
|
2037
|
+
left: elementRect.left - containerRect.left,
|
|
2038
|
+
top: elementRect.top - containerRect.top,
|
|
2039
|
+
width: elementRect.width,
|
|
2040
|
+
height: elementRect.height
|
|
2041
|
+
}
|
|
2042
|
+
};
|
|
2043
|
+
setMeasurement(
|
|
2044
|
+
(prev) => areMeasurementsEqual(prev, nextMeasurement) ? prev : nextMeasurement
|
|
2045
|
+
);
|
|
2046
|
+
}, [componentId, containerRef, svgDivRef]);
|
|
2047
|
+
const scheduleMeasure = useCallback4(() => {
|
|
2048
|
+
if (frameRef.current !== null) return;
|
|
2049
|
+
frameRef.current = window.requestAnimationFrame(measure);
|
|
2050
|
+
}, [measure]);
|
|
2051
|
+
useEffect10(() => {
|
|
2052
|
+
scheduleMeasure();
|
|
2053
|
+
}, [scheduleMeasure, circuitJsonKey]);
|
|
2054
|
+
useEffect10(() => {
|
|
2055
|
+
scheduleMeasure();
|
|
2056
|
+
const svgDiv = svgDivRef.current;
|
|
2057
|
+
const container = containerRef.current;
|
|
2058
|
+
if (!svgDiv || !container) return;
|
|
2059
|
+
const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
2060
|
+
scheduleMeasure();
|
|
2061
|
+
}) : null;
|
|
2062
|
+
resizeObserver?.observe(container);
|
|
2063
|
+
resizeObserver?.observe(svgDiv);
|
|
2064
|
+
const mutationObserver = typeof MutationObserver !== "undefined" ? new MutationObserver(() => {
|
|
2065
|
+
scheduleMeasure();
|
|
2066
|
+
}) : null;
|
|
2067
|
+
mutationObserver?.observe(svgDiv, {
|
|
2068
|
+
attributes: true,
|
|
2069
|
+
attributeFilter: ["style", "transform"],
|
|
2070
|
+
subtree: true,
|
|
2071
|
+
childList: true
|
|
2072
|
+
});
|
|
2073
|
+
window.addEventListener("scroll", scheduleMeasure, true);
|
|
2074
|
+
window.addEventListener("resize", scheduleMeasure);
|
|
2075
|
+
return () => {
|
|
2076
|
+
resizeObserver?.disconnect();
|
|
2077
|
+
mutationObserver?.disconnect();
|
|
2078
|
+
window.removeEventListener("scroll", scheduleMeasure, true);
|
|
2079
|
+
window.removeEventListener("resize", scheduleMeasure);
|
|
2080
|
+
if (frameRef.current !== null) {
|
|
2081
|
+
cancelAnimationFrame(frameRef.current);
|
|
2082
|
+
frameRef.current = null;
|
|
2083
|
+
}
|
|
2084
|
+
};
|
|
2085
|
+
}, [scheduleMeasure, svgDivRef, containerRef]);
|
|
2086
|
+
const handleClick = useCallback4(
|
|
2087
|
+
(event) => {
|
|
2088
|
+
if (onComponentClick) {
|
|
2089
|
+
onComponentClick(componentId, event);
|
|
2090
|
+
}
|
|
2091
|
+
},
|
|
2092
|
+
[componentId, onComponentClick]
|
|
2093
|
+
);
|
|
2094
|
+
const bounds = measurement?.bounds ?? null;
|
|
2095
|
+
const { hovering } = useMouseEventsOverBoundingBox({
|
|
2096
|
+
bounds,
|
|
2097
|
+
onClick: onComponentClick ? handleClick : void 0
|
|
2098
|
+
});
|
|
2099
|
+
if (!measurement || !hovering || !showOutline) {
|
|
2100
|
+
return null;
|
|
2101
|
+
}
|
|
2102
|
+
const rect = measurement.rect;
|
|
2103
|
+
return /* @__PURE__ */ jsx10(
|
|
2104
|
+
"div",
|
|
2105
|
+
{
|
|
2106
|
+
style: {
|
|
2107
|
+
position: "absolute",
|
|
2108
|
+
left: rect.left,
|
|
2109
|
+
top: rect.top,
|
|
2110
|
+
width: rect.width,
|
|
2111
|
+
height: rect.height,
|
|
2112
|
+
border: "1.5px solid rgba(51, 153, 255, 0.9)",
|
|
2113
|
+
borderRadius: "6px",
|
|
2114
|
+
pointerEvents: "none",
|
|
2115
|
+
zIndex: zIndexMap.schematicComponentHoverOutline,
|
|
2116
|
+
boxShadow: "0 0 6px rgba(51, 153, 255, 0.35)"
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
);
|
|
2120
|
+
};
|
|
2121
|
+
|
|
1779
2122
|
// lib/components/SchematicViewer.tsx
|
|
1780
|
-
import { jsx as
|
|
2123
|
+
import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1781
2124
|
var SchematicViewer = ({
|
|
1782
2125
|
circuitJson,
|
|
1783
2126
|
containerStyle,
|
|
@@ -1790,13 +2133,14 @@ var SchematicViewer = ({
|
|
|
1790
2133
|
clickToInteractEnabled = false,
|
|
1791
2134
|
colorOverrides,
|
|
1792
2135
|
spiceSimulationEnabled = false,
|
|
1793
|
-
disableGroups = false
|
|
2136
|
+
disableGroups = false,
|
|
2137
|
+
onSchematicComponentClicked
|
|
1794
2138
|
}) => {
|
|
1795
2139
|
if (debug3) {
|
|
1796
2140
|
enableDebug();
|
|
1797
2141
|
}
|
|
1798
|
-
const [showSpiceOverlay, setShowSpiceOverlay] =
|
|
1799
|
-
const [spiceSimOptions, setSpiceSimOptions] =
|
|
2142
|
+
const [showSpiceOverlay, setShowSpiceOverlay] = useState6(false);
|
|
2143
|
+
const [spiceSimOptions, setSpiceSimOptions] = useState6({
|
|
1800
2144
|
showVoltage: true,
|
|
1801
2145
|
showCurrent: false,
|
|
1802
2146
|
startTime: 0,
|
|
@@ -1807,11 +2151,11 @@ var SchematicViewer = ({
|
|
|
1807
2151
|
const getCircuitHash = (circuitJson2) => {
|
|
1808
2152
|
return `${circuitJson2?.length || 0}_${circuitJson2?.editCount || 0}`;
|
|
1809
2153
|
};
|
|
1810
|
-
const circuitJsonKey =
|
|
2154
|
+
const circuitJsonKey = useMemo5(
|
|
1811
2155
|
() => getCircuitHash(circuitJson),
|
|
1812
2156
|
[circuitJson]
|
|
1813
2157
|
);
|
|
1814
|
-
const spiceString =
|
|
2158
|
+
const spiceString = useMemo5(() => {
|
|
1815
2159
|
if (!spiceSimulationEnabled) return null;
|
|
1816
2160
|
try {
|
|
1817
2161
|
return getSpiceFromCircuitJson(circuitJson, spiceSimOptions);
|
|
@@ -1825,8 +2169,8 @@ var SchematicViewer = ({
|
|
|
1825
2169
|
spiceSimOptions.startTime,
|
|
1826
2170
|
spiceSimOptions.duration
|
|
1827
2171
|
]);
|
|
1828
|
-
const [hasSpiceSimRun, setHasSpiceSimRun] =
|
|
1829
|
-
|
|
2172
|
+
const [hasSpiceSimRun, setHasSpiceSimRun] = useState6(false);
|
|
2173
|
+
useEffect11(() => {
|
|
1830
2174
|
setHasSpiceSimRun(false);
|
|
1831
2175
|
}, [circuitJsonKey]);
|
|
1832
2176
|
const {
|
|
@@ -1835,18 +2179,26 @@ var SchematicViewer = ({
|
|
|
1835
2179
|
isLoading: isSpiceSimLoading,
|
|
1836
2180
|
error: spiceSimError
|
|
1837
2181
|
} = useSpiceSimulation(hasSpiceSimRun ? spiceString : null);
|
|
1838
|
-
const [editModeEnabled, setEditModeEnabled] =
|
|
1839
|
-
const [snapToGrid, setSnapToGrid] =
|
|
1840
|
-
const [isInteractionEnabled, setIsInteractionEnabled] =
|
|
2182
|
+
const [editModeEnabled, setEditModeEnabled] = useState6(defaultEditMode);
|
|
2183
|
+
const [snapToGrid, setSnapToGrid] = useState6(true);
|
|
2184
|
+
const [isInteractionEnabled, setIsInteractionEnabled] = useState6(
|
|
1841
2185
|
!clickToInteractEnabled
|
|
1842
2186
|
);
|
|
1843
|
-
const [showViewMenu, setShowViewMenu] =
|
|
1844
|
-
const [showSchematicGroups, setShowSchematicGroups] =
|
|
2187
|
+
const [showViewMenu, setShowViewMenu] = useState6(false);
|
|
2188
|
+
const [showSchematicGroups, setShowSchematicGroups] = useState6(() => {
|
|
1845
2189
|
if (disableGroups) return false;
|
|
1846
2190
|
return getStoredBoolean("schematic_viewer_show_groups", false);
|
|
1847
2191
|
});
|
|
1848
|
-
const svgDivRef =
|
|
1849
|
-
const touchStartRef =
|
|
2192
|
+
const svgDivRef = useRef7(null);
|
|
2193
|
+
const touchStartRef = useRef7(null);
|
|
2194
|
+
const schematicComponentIds = useMemo5(() => {
|
|
2195
|
+
try {
|
|
2196
|
+
return su6(circuitJson).schematic_component?.list()?.map((component) => component.schematic_component_id) ?? [];
|
|
2197
|
+
} catch (err) {
|
|
2198
|
+
console.error("Failed to derive schematic component ids", err);
|
|
2199
|
+
return [];
|
|
2200
|
+
}
|
|
2201
|
+
}, [circuitJsonKey, circuitJson]);
|
|
1850
2202
|
const handleTouchStart = (e) => {
|
|
1851
2203
|
const touch = e.touches[0];
|
|
1852
2204
|
touchStartRef.current = {
|
|
@@ -1866,9 +2218,9 @@ var SchematicViewer = ({
|
|
|
1866
2218
|
}
|
|
1867
2219
|
touchStartRef.current = null;
|
|
1868
2220
|
};
|
|
1869
|
-
const [internalEditEvents, setInternalEditEvents] =
|
|
1870
|
-
const circuitJsonRef =
|
|
1871
|
-
|
|
2221
|
+
const [internalEditEvents, setInternalEditEvents] = useState6([]);
|
|
2222
|
+
const circuitJsonRef = useRef7(circuitJson);
|
|
2223
|
+
useEffect11(() => {
|
|
1872
2224
|
const circuitHash = getCircuitHash(circuitJson);
|
|
1873
2225
|
const circuitHashRef = getCircuitHash(circuitJsonRef.current);
|
|
1874
2226
|
if (circuitHash !== circuitHashRef) {
|
|
@@ -1889,7 +2241,7 @@ var SchematicViewer = ({
|
|
|
1889
2241
|
enabled: isInteractionEnabled && !showSpiceOverlay
|
|
1890
2242
|
});
|
|
1891
2243
|
const { containerWidth, containerHeight } = useResizeHandling(containerRef);
|
|
1892
|
-
const svgString =
|
|
2244
|
+
const svgString = useMemo5(() => {
|
|
1893
2245
|
if (!containerWidth || !containerHeight) return "";
|
|
1894
2246
|
return convertCircuitJsonToSchematicSvg(circuitJson, {
|
|
1895
2247
|
width: containerWidth,
|
|
@@ -1901,13 +2253,13 @@ var SchematicViewer = ({
|
|
|
1901
2253
|
colorOverrides
|
|
1902
2254
|
});
|
|
1903
2255
|
}, [circuitJsonKey, containerWidth, containerHeight]);
|
|
1904
|
-
const containerBackgroundColor =
|
|
2256
|
+
const containerBackgroundColor = useMemo5(() => {
|
|
1905
2257
|
const match = svgString.match(
|
|
1906
2258
|
/<svg[^>]*style="[^"]*background-color:\s*([^;\"]+)/i
|
|
1907
2259
|
);
|
|
1908
2260
|
return match?.[1] ?? "transparent";
|
|
1909
2261
|
}, [svgString]);
|
|
1910
|
-
const realToSvgProjection =
|
|
2262
|
+
const realToSvgProjection = useMemo5(() => {
|
|
1911
2263
|
if (!svgString) return identity();
|
|
1912
2264
|
const transformString = svgString.match(
|
|
1913
2265
|
/data-real-to-screen-transform="([^"]+)"/
|
|
@@ -1925,7 +2277,7 @@ var SchematicViewer = ({
|
|
|
1925
2277
|
onEditEvent(event);
|
|
1926
2278
|
}
|
|
1927
2279
|
};
|
|
1928
|
-
const editEventsWithUnappliedEditEvents =
|
|
2280
|
+
const editEventsWithUnappliedEditEvents = useMemo5(() => {
|
|
1929
2281
|
return [...unappliedEditEvents, ...internalEditEvents];
|
|
1930
2282
|
}, [unappliedEditEvents, internalEditEvents]);
|
|
1931
2283
|
const {
|
|
@@ -1962,12 +2314,12 @@ var SchematicViewer = ({
|
|
|
1962
2314
|
circuitJsonKey,
|
|
1963
2315
|
showGroups: showSchematicGroups && !disableGroups
|
|
1964
2316
|
});
|
|
1965
|
-
const handleComponentTouchStartRef =
|
|
1966
|
-
|
|
2317
|
+
const handleComponentTouchStartRef = useRef7(handleComponentTouchStart);
|
|
2318
|
+
useEffect11(() => {
|
|
1967
2319
|
handleComponentTouchStartRef.current = handleComponentTouchStart;
|
|
1968
2320
|
}, [handleComponentTouchStart]);
|
|
1969
|
-
const svgDiv =
|
|
1970
|
-
() => /* @__PURE__ */
|
|
2321
|
+
const svgDiv = useMemo5(
|
|
2322
|
+
() => /* @__PURE__ */ jsx11(
|
|
1971
2323
|
"div",
|
|
1972
2324
|
{
|
|
1973
2325
|
ref: svgDivRef,
|
|
@@ -1991,7 +2343,7 @@ var SchematicViewer = ({
|
|
|
1991
2343
|
showSpiceOverlay
|
|
1992
2344
|
]
|
|
1993
2345
|
);
|
|
1994
|
-
return /* @__PURE__ */ jsxs6(
|
|
2346
|
+
return /* @__PURE__ */ jsx11(MouseTracker, { children: /* @__PURE__ */ jsxs6(
|
|
1995
2347
|
"div",
|
|
1996
2348
|
{
|
|
1997
2349
|
ref: containerRef,
|
|
@@ -2032,7 +2384,7 @@ var SchematicViewer = ({
|
|
|
2032
2384
|
handleTouchEnd(e);
|
|
2033
2385
|
},
|
|
2034
2386
|
children: [
|
|
2035
|
-
!isInteractionEnabled && clickToInteractEnabled && /* @__PURE__ */
|
|
2387
|
+
!isInteractionEnabled && clickToInteractEnabled && /* @__PURE__ */ jsx11(
|
|
2036
2388
|
"div",
|
|
2037
2389
|
{
|
|
2038
2390
|
onClick: (e) => {
|
|
@@ -2051,7 +2403,7 @@ var SchematicViewer = ({
|
|
|
2051
2403
|
pointerEvents: "all",
|
|
2052
2404
|
touchAction: "pan-x pan-y pinch-zoom"
|
|
2053
2405
|
},
|
|
2054
|
-
children: /* @__PURE__ */
|
|
2406
|
+
children: /* @__PURE__ */ jsx11(
|
|
2055
2407
|
"div",
|
|
2056
2408
|
{
|
|
2057
2409
|
style: {
|
|
@@ -2068,28 +2420,28 @@ var SchematicViewer = ({
|
|
|
2068
2420
|
)
|
|
2069
2421
|
}
|
|
2070
2422
|
),
|
|
2071
|
-
/* @__PURE__ */
|
|
2423
|
+
/* @__PURE__ */ jsx11(
|
|
2072
2424
|
ViewMenuIcon,
|
|
2073
2425
|
{
|
|
2074
2426
|
active: showViewMenu,
|
|
2075
2427
|
onClick: () => setShowViewMenu(!showViewMenu)
|
|
2076
2428
|
}
|
|
2077
2429
|
),
|
|
2078
|
-
editingEnabled && /* @__PURE__ */
|
|
2430
|
+
editingEnabled && /* @__PURE__ */ jsx11(
|
|
2079
2431
|
EditIcon,
|
|
2080
2432
|
{
|
|
2081
2433
|
active: editModeEnabled,
|
|
2082
2434
|
onClick: () => setEditModeEnabled(!editModeEnabled)
|
|
2083
2435
|
}
|
|
2084
2436
|
),
|
|
2085
|
-
editingEnabled && editModeEnabled && /* @__PURE__ */
|
|
2437
|
+
editingEnabled && editModeEnabled && /* @__PURE__ */ jsx11(
|
|
2086
2438
|
GridIcon,
|
|
2087
2439
|
{
|
|
2088
2440
|
active: snapToGrid,
|
|
2089
2441
|
onClick: () => setSnapToGrid(!snapToGrid)
|
|
2090
2442
|
}
|
|
2091
2443
|
),
|
|
2092
|
-
/* @__PURE__ */
|
|
2444
|
+
/* @__PURE__ */ jsx11(
|
|
2093
2445
|
ViewMenu,
|
|
2094
2446
|
{
|
|
2095
2447
|
circuitJson,
|
|
@@ -2105,8 +2457,8 @@ var SchematicViewer = ({
|
|
|
2105
2457
|
}
|
|
2106
2458
|
}
|
|
2107
2459
|
),
|
|
2108
|
-
spiceSimulationEnabled && /* @__PURE__ */
|
|
2109
|
-
showSpiceOverlay && /* @__PURE__ */
|
|
2460
|
+
spiceSimulationEnabled && /* @__PURE__ */ jsx11(SpiceSimulationIcon, { onClick: () => setShowSpiceOverlay(true) }),
|
|
2461
|
+
showSpiceOverlay && /* @__PURE__ */ jsx11(
|
|
2110
2462
|
SpiceSimulationOverlay,
|
|
2111
2463
|
{
|
|
2112
2464
|
spiceString,
|
|
@@ -2123,12 +2475,31 @@ var SchematicViewer = ({
|
|
|
2123
2475
|
hasRun: hasSpiceSimRun
|
|
2124
2476
|
}
|
|
2125
2477
|
),
|
|
2478
|
+
onSchematicComponentClicked && schematicComponentIds.map((componentId) => /* @__PURE__ */ jsx11(
|
|
2479
|
+
SchematicComponentMouseTarget,
|
|
2480
|
+
{
|
|
2481
|
+
componentId,
|
|
2482
|
+
svgDivRef,
|
|
2483
|
+
containerRef,
|
|
2484
|
+
showOutline: true,
|
|
2485
|
+
circuitJsonKey,
|
|
2486
|
+
onComponentClick: (id, event) => {
|
|
2487
|
+
onSchematicComponentClicked?.({
|
|
2488
|
+
schematicComponentId: id,
|
|
2489
|
+
event
|
|
2490
|
+
});
|
|
2491
|
+
}
|
|
2492
|
+
},
|
|
2493
|
+
componentId
|
|
2494
|
+
)),
|
|
2126
2495
|
svgDiv
|
|
2127
2496
|
]
|
|
2128
2497
|
}
|
|
2129
|
-
);
|
|
2498
|
+
) });
|
|
2130
2499
|
};
|
|
2131
2500
|
export {
|
|
2132
|
-
|
|
2501
|
+
MouseTracker,
|
|
2502
|
+
SchematicViewer,
|
|
2503
|
+
useMouseEventsOverBoundingBox
|
|
2133
2504
|
};
|
|
2134
2505
|
//# sourceMappingURL=index.js.map
|