@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/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 useEffect8, useMemo as useMemo3, useRef as useRef4, useState as useState5 } from "react";
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.41",
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 jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
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] = useState5(false);
1799
- const [spiceSimOptions, setSpiceSimOptions] = useState5({
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 = useMemo3(
2154
+ const circuitJsonKey = useMemo5(
1811
2155
  () => getCircuitHash(circuitJson),
1812
2156
  [circuitJson]
1813
2157
  );
1814
- const spiceString = useMemo3(() => {
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] = useState5(false);
1829
- useEffect8(() => {
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] = useState5(defaultEditMode);
1839
- const [snapToGrid, setSnapToGrid] = useState5(true);
1840
- const [isInteractionEnabled, setIsInteractionEnabled] = useState5(
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] = useState5(false);
1844
- const [showSchematicGroups, setShowSchematicGroups] = useState5(() => {
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 = useRef4(null);
1849
- const touchStartRef = useRef4(null);
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] = useState5([]);
1870
- const circuitJsonRef = useRef4(circuitJson);
1871
- useEffect8(() => {
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 = useMemo3(() => {
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 = useMemo3(() => {
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 = useMemo3(() => {
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 = useMemo3(() => {
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 = useRef4(handleComponentTouchStart);
1966
- useEffect8(() => {
2317
+ const handleComponentTouchStartRef = useRef7(handleComponentTouchStart);
2318
+ useEffect11(() => {
1967
2319
  handleComponentTouchStartRef.current = handleComponentTouchStart;
1968
2320
  }, [handleComponentTouchStart]);
1969
- const svgDiv = useMemo3(
1970
- () => /* @__PURE__ */ jsx9(
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__ */ jsx9(
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__ */ jsx9(
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__ */ jsx9(
2423
+ /* @__PURE__ */ jsx11(
2072
2424
  ViewMenuIcon,
2073
2425
  {
2074
2426
  active: showViewMenu,
2075
2427
  onClick: () => setShowViewMenu(!showViewMenu)
2076
2428
  }
2077
2429
  ),
2078
- editingEnabled && /* @__PURE__ */ jsx9(
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__ */ jsx9(
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__ */ jsx9(
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__ */ jsx9(SpiceSimulationIcon, { onClick: () => setShowSpiceOverlay(true) }),
2109
- showSpiceOverlay && /* @__PURE__ */ jsx9(
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
- SchematicViewer
2501
+ MouseTracker,
2502
+ SchematicViewer,
2503
+ useMouseEventsOverBoundingBox
2133
2504
  };
2134
2505
  //# sourceMappingURL=index.js.map