@tscircuit/schematic-viewer 2.0.56 → 2.0.57

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.
Files changed (69) hide show
  1. package/dist/index.js +4 -1
  2. package/dist/index.js.map +1 -1
  3. package/package.json +4 -1
  4. package/.github/workflows/bun-formatcheck.yml +0 -26
  5. package/.github/workflows/bun-pver-release.yml +0 -59
  6. package/.github/workflows/bun-typecheck.yml +0 -26
  7. package/.github/workflows/on-merge-inform-release-tracker.yml +0 -24
  8. package/CLAUDE.md +0 -1
  9. package/biome.json +0 -56
  10. package/bun.lockb +0 -0
  11. package/cosmos.config.json +0 -3
  12. package/cosmos.decorator.tsx +0 -3
  13. package/docs/circuit-to-svg-metadata.md +0 -151
  14. package/docs/dragndrop-spec.md +0 -39
  15. package/examples/example1-resistor-and-capacitor.fixture.tsx +0 -16
  16. package/examples/example10-groups-view-schematic-groups.fixture.tsx +0 -76
  17. package/examples/example11-automatic-grouping-view-schematic-groups.fixture.tsx +0 -109
  18. package/examples/example12-spice-boost-converter.fixture.tsx +0 -78
  19. package/examples/example13-disablegroups.fixture.tsx +0 -30
  20. package/examples/example14-schematic-component-click.fixture.tsx +0 -46
  21. package/examples/example15-analog-simulation-viewer.fixture.tsx +0 -145
  22. package/examples/example16-no-analog-simulation.fixture.tsx +0 -13
  23. package/examples/example17-schematic-ports.fixture.tsx +0 -49
  24. package/examples/example18-live-toggle.fixture.tsx +0 -60
  25. package/examples/example2-small-circuit.fixture.tsx +0 -48
  26. package/examples/example3-small-circuit-without-debug-grid.fixture.tsx +0 -44
  27. package/examples/example4-reset-edit-events.fixture.tsx +0 -57
  28. package/examples/example5-circuit-json-rerender.fixture.tsx +0 -110
  29. package/examples/example6-click-to-interact.fixture.tsx +0 -36
  30. package/examples/example7-schematic-viewer-fix-snapping.fixture.tsx +0 -123
  31. package/examples/example8-color-overrides.fixture.tsx +0 -52
  32. package/examples/example9-spice-rc-charging-voltage-divider.fixture.tsx +0 -77
  33. package/index.html +0 -12
  34. package/lib/components/AnalogSimulationViewer.tsx +0 -300
  35. package/lib/components/ControlledSchematicViewer.tsx +0 -40
  36. package/lib/components/EditIcon.tsx +0 -46
  37. package/lib/components/GridIcon.tsx +0 -45
  38. package/lib/components/MouseTracker.tsx +0 -257
  39. package/lib/components/SchematicComponentMouseTarget.tsx +0 -189
  40. package/lib/components/SchematicPortMouseTarget.tsx +0 -224
  41. package/lib/components/SchematicViewer.tsx +0 -583
  42. package/lib/components/SpiceIcon.tsx +0 -14
  43. package/lib/components/SpicePlot.tsx +0 -221
  44. package/lib/components/SpiceSimulationIcon.tsx +0 -32
  45. package/lib/components/SpiceSimulationOverlay.tsx +0 -250
  46. package/lib/components/ViewMenu.tsx +0 -218
  47. package/lib/components/ViewMenuIcon.tsx +0 -47
  48. package/lib/dev/render-to-circuit-json.ts +0 -8
  49. package/lib/hooks/use-resize-handling.ts +0 -35
  50. package/lib/hooks/useChangeSchematicComponentLocationsInSvg.ts +0 -117
  51. package/lib/hooks/useChangeSchematicTracesForMovedComponents.ts +0 -121
  52. package/lib/hooks/useComponentDragging.ts +0 -251
  53. package/lib/hooks/useLocalStorage.ts +0 -63
  54. package/lib/hooks/useMouseEventsOverBoundingBox.ts +0 -74
  55. package/lib/hooks/useSchematicGroupsOverlay.ts +0 -364
  56. package/lib/hooks/useSpiceSimulation.ts +0 -149
  57. package/lib/index.ts +0 -4
  58. package/lib/types/edit-events.ts +0 -16
  59. package/lib/types/eecircuit-engine.d.ts +0 -147
  60. package/lib/utils/debug.ts +0 -9
  61. package/lib/utils/get-component-offset-due-to-events.ts +0 -43
  62. package/lib/utils/spice-utils.ts +0 -128
  63. package/lib/utils/z-index-map.ts +0 -11
  64. package/lib/workers/spice-simulation.worker.ts +0 -51
  65. package/scripts/build-worker-blob-url.ts +0 -55
  66. package/src/main.tsx +0 -21
  67. package/tsconfig.json +0 -33
  68. package/tsup-webworker.config.ts +0 -13
  69. package/vite.config.js +0 -15
@@ -1,583 +0,0 @@
1
- import {
2
- convertCircuitJsonToSchematicSvg,
3
- type ColorOverrides,
4
- } from "circuit-to-svg"
5
- import { su } from "@tscircuit/soup-util"
6
- import { useChangeSchematicComponentLocationsInSvg } from "lib/hooks/useChangeSchematicComponentLocationsInSvg"
7
- import { useChangeSchematicTracesForMovedComponents } from "lib/hooks/useChangeSchematicTracesForMovedComponents"
8
- import { useSchematicGroupsOverlay } from "lib/hooks/useSchematicGroupsOverlay"
9
- import { enableDebug } from "lib/utils/debug"
10
- import { useCallback, useEffect, useMemo, useRef, useState } from "react"
11
- import {
12
- fromString,
13
- identity,
14
- toString as transformToString,
15
- } from "transformation-matrix"
16
- import { useMouseMatrixTransform } from "use-mouse-matrix-transform"
17
- import { useResizeHandling } from "../hooks/use-resize-handling"
18
- import { useComponentDragging } from "../hooks/useComponentDragging"
19
- import type { ManualEditEvent } from "../types/edit-events"
20
- import { EditIcon } from "./EditIcon"
21
- import { GridIcon } from "./GridIcon"
22
- import { ViewMenuIcon } from "./ViewMenuIcon"
23
- import { ViewMenu } from "./ViewMenu"
24
- import type { CircuitJson } from "circuit-json"
25
- import { SpiceSimulationIcon } from "./SpiceSimulationIcon"
26
- import { SpiceSimulationOverlay } from "./SpiceSimulationOverlay"
27
- import { zIndexMap } from "../utils/z-index-map"
28
- import { useSpiceSimulation } from "../hooks/useSpiceSimulation"
29
- import { getSpiceFromCircuitJson } from "../utils/spice-utils"
30
- import { getStoredBoolean, setStoredBoolean } from "lib/hooks/useLocalStorage"
31
- import { MouseTracker } from "./MouseTracker"
32
- import { SchematicComponentMouseTarget } from "./SchematicComponentMouseTarget"
33
- import { SchematicPortMouseTarget } from "./SchematicPortMouseTarget"
34
-
35
- interface Props {
36
- circuitJson: CircuitJson
37
- containerStyle?: React.CSSProperties
38
- editEvents?: ManualEditEvent[]
39
- onEditEvent?: (event: ManualEditEvent) => void
40
- defaultEditMode?: boolean
41
- debugGrid?: boolean
42
- editingEnabled?: boolean
43
- debug?: boolean
44
- clickToInteractEnabled?: boolean
45
- colorOverrides?: ColorOverrides
46
- spiceSimulationEnabled?: boolean
47
- disableGroups?: boolean
48
- onSchematicComponentClicked?: (options: {
49
- schematicComponentId: string
50
- event: MouseEvent
51
- }) => void
52
- showSchematicPorts?: boolean
53
- onSchematicPortClicked?: (options: {
54
- schematicPortId: string
55
- event: MouseEvent
56
- }) => void
57
- }
58
-
59
- export const SchematicViewer = ({
60
- circuitJson,
61
- containerStyle,
62
- editEvents: unappliedEditEvents = [],
63
- onEditEvent,
64
- defaultEditMode = false,
65
- debugGrid = false,
66
- editingEnabled = false,
67
- debug = false,
68
- clickToInteractEnabled = false,
69
- colorOverrides,
70
- spiceSimulationEnabled = false,
71
- disableGroups = false,
72
- onSchematicComponentClicked,
73
- showSchematicPorts = false,
74
- onSchematicPortClicked,
75
- }: Props) => {
76
- if (debug) {
77
- enableDebug()
78
- }
79
- const [showSpiceOverlay, setShowSpiceOverlay] = useState(false)
80
- const [spiceSimOptions, setSpiceSimOptions] = useState({
81
- showVoltage: true,
82
- showCurrent: false,
83
- startTime: 0, // in ms
84
- duration: 20, // in ms
85
- })
86
-
87
- const getCircuitHash = (circuitJson: CircuitJson) => {
88
- return `${circuitJson?.length || 0}_${(circuitJson as any)?.editCount || 0}`
89
- }
90
-
91
- const circuitJsonKey = useMemo(
92
- () => getCircuitHash(circuitJson),
93
- [circuitJson],
94
- )
95
-
96
- const spiceString = useMemo(() => {
97
- if (!spiceSimulationEnabled) return null
98
- try {
99
- return getSpiceFromCircuitJson(circuitJson, spiceSimOptions)
100
- } catch (e) {
101
- console.error("Failed to generate SPICE string", e)
102
- return null
103
- }
104
- }, [
105
- circuitJsonKey,
106
- spiceSimulationEnabled,
107
- spiceSimOptions.startTime,
108
- spiceSimOptions.duration,
109
- ])
110
-
111
- const [hasSpiceSimRun, setHasSpiceSimRun] = useState(false)
112
-
113
- useEffect(() => {
114
- setHasSpiceSimRun(false)
115
- }, [circuitJsonKey])
116
-
117
- const {
118
- plotData,
119
- nodes,
120
- isLoading: isSpiceSimLoading,
121
- error: spiceSimError,
122
- } = useSpiceSimulation(hasSpiceSimRun ? spiceString : null)
123
-
124
- const [editModeEnabled, setEditModeEnabled] = useState(defaultEditMode)
125
- const [snapToGrid, setSnapToGrid] = useState(true)
126
- const [showGridInternal, setShowGridInternal] = useState(false)
127
- const showGrid = debugGrid || showGridInternal
128
- const [isInteractionEnabled, setIsInteractionEnabled] = useState<boolean>(
129
- !clickToInteractEnabled,
130
- )
131
- const [showViewMenu, setShowViewMenu] = useState(false)
132
- const [showSchematicGroups, setShowSchematicGroups] = useState(() => {
133
- if (disableGroups) return false
134
- return getStoredBoolean("schematic_viewer_show_groups", false)
135
- })
136
- const [isHoveringClickableComponent, setIsHoveringClickableComponent] =
137
- useState(false)
138
- const hoveringComponentsRef = useRef<Set<string>>(new Set())
139
-
140
- const handleComponentHoverChange = useCallback(
141
- (componentId: string, isHovering: boolean) => {
142
- if (isHovering) {
143
- hoveringComponentsRef.current.add(componentId)
144
- } else {
145
- hoveringComponentsRef.current.delete(componentId)
146
- }
147
- setIsHoveringClickableComponent(hoveringComponentsRef.current.size > 0)
148
- },
149
- [],
150
- )
151
-
152
- const [isHoveringClickablePort, setIsHoveringClickablePort] = useState(false)
153
- const hoveringPortsRef = useRef<Set<string>>(new Set())
154
-
155
- const handlePortHoverChange = useCallback(
156
- (portId: string, isHovering: boolean) => {
157
- if (isHovering) {
158
- hoveringPortsRef.current.add(portId)
159
- } else {
160
- hoveringPortsRef.current.delete(portId)
161
- }
162
- setIsHoveringClickablePort(hoveringPortsRef.current.size > 0)
163
- },
164
- [],
165
- )
166
-
167
- const svgDivRef = useRef<HTMLDivElement>(null)
168
- const touchStartRef = useRef<{ x: number; y: number } | null>(null)
169
-
170
- const schematicComponentIds = useMemo(() => {
171
- try {
172
- return (
173
- su(circuitJson)
174
- .schematic_component?.list()
175
- ?.map((component) => component.schematic_component_id as string) ?? []
176
- )
177
- } catch (err) {
178
- console.error("Failed to derive schematic component ids", err)
179
- return []
180
- }
181
- }, [circuitJsonKey, circuitJson])
182
-
183
- const schematicPortsInfo = useMemo(() => {
184
- if (!showSchematicPorts) return []
185
- try {
186
- const ports = su(circuitJson).schematic_port?.list() ?? []
187
- return ports.map((port) => {
188
- const sourcePort = su(circuitJson).source_port.get(port.source_port_id)
189
- const sourceComponent = sourcePort?.source_component_id
190
- ? su(circuitJson).source_component.get(sourcePort.source_component_id)
191
- : null
192
- const componentName = sourceComponent?.name ?? "?"
193
- const pinLabel =
194
- port.display_pin_label ??
195
- (sourcePort as any)?.pin_number ??
196
- (sourcePort as any)?.name ??
197
- "?"
198
- return {
199
- portId: port.source_port_id as string,
200
- label: `${componentName}.${pinLabel}`,
201
- }
202
- })
203
- } catch (err) {
204
- console.error("Failed to derive schematic port info", err)
205
- return []
206
- }
207
- }, [circuitJsonKey, circuitJson, showSchematicPorts])
208
-
209
- const handleTouchStart = (e: React.TouchEvent) => {
210
- const touch = e.touches[0]
211
- touchStartRef.current = {
212
- x: touch.clientX,
213
- y: touch.clientY,
214
- }
215
- }
216
-
217
- const handleTouchEnd = (e: React.TouchEvent) => {
218
- const touch = e.changedTouches[0]
219
- const start = touchStartRef.current
220
- if (!start) return
221
-
222
- const deltaX = Math.abs(touch.clientX - start.x)
223
- const deltaY = Math.abs(touch.clientY - start.y)
224
-
225
- if (deltaX < 10 && deltaY < 10) {
226
- e.preventDefault()
227
- setIsInteractionEnabled(true)
228
- }
229
-
230
- touchStartRef.current = null
231
- }
232
-
233
- const [internalEditEvents, setInternalEditEvents] = useState<
234
- ManualEditEvent[]
235
- >([])
236
- const circuitJsonRef = useRef<CircuitJson>(circuitJson)
237
-
238
- useEffect(() => {
239
- const circuitHash = getCircuitHash(circuitJson)
240
- const circuitHashRef = getCircuitHash(circuitJsonRef.current)
241
-
242
- if (circuitHash !== circuitHashRef) {
243
- setInternalEditEvents([])
244
- circuitJsonRef.current = circuitJson
245
- }
246
- }, [circuitJson])
247
-
248
- const {
249
- ref: containerRef,
250
- cancelDrag,
251
- transform: svgToScreenProjection,
252
- } = useMouseMatrixTransform({
253
- onSetTransform(transform) {
254
- if (!svgDivRef.current) return
255
- svgDivRef.current.style.transform = transformToString(transform)
256
- },
257
- // @ts-ignore disabled is a valid prop but not typed
258
- enabled: isInteractionEnabled && !showSpiceOverlay,
259
- })
260
-
261
- const { containerWidth, containerHeight } = useResizeHandling(containerRef)
262
- const svgString = useMemo(() => {
263
- if (!containerWidth || !containerHeight) return ""
264
-
265
- return convertCircuitJsonToSchematicSvg(circuitJson as any, {
266
- width: containerWidth,
267
- height: containerHeight || 720,
268
- grid: !showGrid
269
- ? undefined
270
- : {
271
- cellSize: 1,
272
- labelCells: true,
273
- },
274
- colorOverrides,
275
- })
276
- }, [circuitJsonKey, containerWidth, containerHeight, showGrid])
277
-
278
- const containerBackgroundColor = useMemo(() => {
279
- const match = svgString.match(
280
- /<svg[^>]*style="[^"]*background-color:\s*([^;\"]+)/i,
281
- )
282
- return match?.[1] ?? "transparent"
283
- }, [svgString])
284
-
285
- const realToSvgProjection = useMemo(() => {
286
- if (!svgString) return identity()
287
- const transformString = svgString.match(
288
- /data-real-to-screen-transform="([^"]+)"/,
289
- )?.[1]!
290
-
291
- try {
292
- return fromString(transformString)
293
- } catch (e) {
294
- console.error(e)
295
- return identity()
296
- }
297
- }, [svgString])
298
-
299
- const handleEditEvent = (event: ManualEditEvent) => {
300
- setInternalEditEvents((prev) => [...prev, event])
301
- if (onEditEvent) {
302
- onEditEvent(event)
303
- }
304
- }
305
-
306
- const editEventsWithUnappliedEditEvents = useMemo(() => {
307
- return [...unappliedEditEvents, ...internalEditEvents]
308
- }, [unappliedEditEvents, internalEditEvents])
309
-
310
- const {
311
- handleMouseDown,
312
- handleTouchStart: handleComponentTouchStart,
313
- isDragging,
314
- activeEditEvent,
315
- } = useComponentDragging({
316
- onEditEvent: handleEditEvent,
317
- cancelDrag,
318
- realToSvgProjection,
319
- svgToScreenProjection,
320
- circuitJson,
321
- editEvents: editEventsWithUnappliedEditEvents,
322
- enabled: editModeEnabled && isInteractionEnabled && !showSpiceOverlay,
323
- snapToGrid,
324
- })
325
-
326
- useChangeSchematicComponentLocationsInSvg({
327
- svgDivRef,
328
- editEvents: editEventsWithUnappliedEditEvents,
329
- realToSvgProjection,
330
- svgToScreenProjection,
331
- activeEditEvent,
332
- })
333
-
334
- useChangeSchematicTracesForMovedComponents({
335
- svgDivRef,
336
- circuitJson,
337
- activeEditEvent,
338
- editEvents: editEventsWithUnappliedEditEvents,
339
- })
340
-
341
- // Add group overlays when enabled
342
- useSchematicGroupsOverlay({
343
- svgDivRef,
344
- circuitJson,
345
- circuitJsonKey,
346
- showGroups: showSchematicGroups && !disableGroups,
347
- })
348
-
349
- // keep the latest touch handler without re-rendering the svg div
350
- const handleComponentTouchStartRef = useRef(handleComponentTouchStart)
351
- useEffect(() => {
352
- handleComponentTouchStartRef.current = handleComponentTouchStart
353
- }, [handleComponentTouchStart])
354
-
355
- const svgDiv = useMemo(
356
- () => (
357
- <div
358
- ref={svgDivRef}
359
- style={{
360
- pointerEvents: clickToInteractEnabled
361
- ? isInteractionEnabled
362
- ? "auto"
363
- : "none"
364
- : "auto",
365
- transformOrigin: "0 0",
366
- }}
367
- className={
368
- onSchematicComponentClicked
369
- ? "schematic-component-clickable"
370
- : undefined
371
- }
372
- onTouchStart={(e) => {
373
- if (editModeEnabled && isInteractionEnabled && !showSpiceOverlay) {
374
- handleComponentTouchStartRef.current(e)
375
- }
376
- }}
377
- // biome-ignore lint/security/noDangerouslySetInnerHtml: <explanation>
378
- dangerouslySetInnerHTML={{ __html: svgString }}
379
- />
380
- ),
381
- [
382
- svgString,
383
- isInteractionEnabled,
384
- clickToInteractEnabled,
385
- editModeEnabled,
386
- showSpiceOverlay,
387
- ],
388
- )
389
-
390
- return (
391
- <MouseTracker>
392
- {onSchematicComponentClicked && (
393
- <style>
394
- {`.schematic-component-clickable [data-schematic-component-id]:hover { cursor: pointer !important; }`}
395
- </style>
396
- )}
397
- {onSchematicPortClicked && (
398
- <style>
399
- {`[data-schematic-port-id]:hover { cursor: pointer !important; }`}
400
- </style>
401
- )}
402
- <div
403
- ref={containerRef}
404
- style={{
405
- position: "relative",
406
- backgroundColor: containerBackgroundColor,
407
- overflow: "hidden",
408
- cursor: showSpiceOverlay
409
- ? "auto"
410
- : isDragging
411
- ? "grabbing"
412
- : clickToInteractEnabled && !isInteractionEnabled
413
- ? "pointer"
414
- : isHoveringClickableComponent && onSchematicComponentClicked
415
- ? "pointer"
416
- : isHoveringClickablePort && onSchematicPortClicked
417
- ? "pointer"
418
- : "grab",
419
- minHeight: "300px",
420
- ...containerStyle,
421
- }}
422
- onWheelCapture={(e) => {
423
- if (showSpiceOverlay) {
424
- e.stopPropagation()
425
- }
426
- }}
427
- onMouseDown={(e) => {
428
- if (clickToInteractEnabled && !isInteractionEnabled) {
429
- e.preventDefault()
430
- e.stopPropagation()
431
- return
432
- }
433
- handleMouseDown(e)
434
- }}
435
- onMouseDownCapture={(e) => {
436
- if (clickToInteractEnabled && !isInteractionEnabled) {
437
- e.preventDefault()
438
- e.stopPropagation()
439
- return
440
- }
441
- }}
442
- onTouchStart={(e) => {
443
- if (showSpiceOverlay) return
444
- handleTouchStart(e)
445
- }}
446
- onTouchEnd={(e) => {
447
- if (showSpiceOverlay) return
448
- handleTouchEnd(e)
449
- }}
450
- >
451
- {!isInteractionEnabled && clickToInteractEnabled && (
452
- <div
453
- onClick={(e) => {
454
- e.preventDefault()
455
- e.stopPropagation()
456
- setIsInteractionEnabled(true)
457
- }}
458
- style={{
459
- position: "absolute",
460
- inset: 0,
461
- cursor: "pointer",
462
- zIndex: zIndexMap.clickToInteractOverlay,
463
- display: "flex",
464
- alignItems: "center",
465
- justifyContent: "center",
466
- pointerEvents: "all",
467
- touchAction: "pan-x pan-y pinch-zoom",
468
- }}
469
- >
470
- <div
471
- style={{
472
- backgroundColor: "rgba(0, 0, 0, 0.8)",
473
- color: "white",
474
- padding: "12px 24px",
475
- borderRadius: "8px",
476
- fontSize: "16px",
477
- fontFamily: "sans-serif",
478
- pointerEvents: "none",
479
- }}
480
- >
481
- {typeof window !== "undefined" &&
482
- ("ontouchstart" in window || navigator.maxTouchPoints > 0)
483
- ? "Touch to Interact"
484
- : "Click to Interact"}
485
- </div>
486
- </div>
487
- )}
488
- <ViewMenuIcon
489
- active={showViewMenu}
490
- onClick={() => setShowViewMenu(!showViewMenu)}
491
- />
492
- {editingEnabled && (
493
- <EditIcon
494
- active={editModeEnabled}
495
- onClick={() => setEditModeEnabled(!editModeEnabled)}
496
- />
497
- )}
498
- {editingEnabled && editModeEnabled && (
499
- <GridIcon
500
- active={snapToGrid}
501
- onClick={() => setSnapToGrid(!snapToGrid)}
502
- />
503
- )}
504
- <ViewMenu
505
- circuitJson={circuitJson}
506
- circuitJsonKey={circuitJsonKey}
507
- isVisible={showViewMenu}
508
- onClose={() => setShowViewMenu(false)}
509
- showGroups={showSchematicGroups}
510
- onToggleGroups={(value) => {
511
- if (!disableGroups) {
512
- setShowSchematicGroups(value)
513
- setStoredBoolean("schematic_viewer_show_groups", value)
514
- }
515
- }}
516
- showGrid={showGrid}
517
- onToggleGrid={setShowGridInternal}
518
- />
519
- {spiceSimulationEnabled && (
520
- <SpiceSimulationIcon onClick={() => setShowSpiceOverlay(true)} />
521
- )}
522
- {showSpiceOverlay && (
523
- <SpiceSimulationOverlay
524
- spiceString={spiceString}
525
- onClose={() => setShowSpiceOverlay(false)}
526
- plotData={plotData}
527
- nodes={nodes}
528
- isLoading={isSpiceSimLoading}
529
- error={spiceSimError}
530
- simOptions={spiceSimOptions}
531
- onSimOptionsChange={(options) => {
532
- setHasSpiceSimRun(true)
533
- setSpiceSimOptions(options)
534
- }}
535
- hasRun={hasSpiceSimRun}
536
- />
537
- )}
538
- {onSchematicComponentClicked &&
539
- schematicComponentIds.map((componentId) => (
540
- <SchematicComponentMouseTarget
541
- key={componentId}
542
- componentId={componentId}
543
- svgDivRef={svgDivRef}
544
- containerRef={containerRef}
545
- showOutline={true}
546
- circuitJsonKey={circuitJsonKey}
547
- onHoverChange={handleComponentHoverChange}
548
- onComponentClick={(id, event) => {
549
- onSchematicComponentClicked?.({
550
- schematicComponentId: id,
551
- event,
552
- })
553
- }}
554
- />
555
- ))}
556
- {svgDiv}
557
- {showSchematicPorts &&
558
- schematicPortsInfo.map(({ portId, label }) => (
559
- <SchematicPortMouseTarget
560
- key={portId}
561
- portId={portId}
562
- portLabel={label}
563
- svgDivRef={svgDivRef}
564
- containerRef={containerRef}
565
- showOutline={true}
566
- circuitJsonKey={circuitJsonKey}
567
- onHoverChange={handlePortHoverChange}
568
- onPortClick={
569
- onSchematicPortClicked
570
- ? (id, event) => {
571
- onSchematicPortClicked?.({
572
- schematicPortId: id,
573
- event,
574
- })
575
- }
576
- : undefined
577
- }
578
- />
579
- ))}
580
- </div>
581
- </MouseTracker>
582
- )
583
- }
@@ -1,14 +0,0 @@
1
- export const SpiceIcon = () => (
2
- <svg
3
- width="16"
4
- height="16"
5
- viewBox="0 0 24 24"
6
- fill="none"
7
- stroke="currentColor"
8
- strokeWidth="2"
9
- strokeLinecap="round"
10
- strokeLinejoin="round"
11
- >
12
- <path d="M3 12h2.5l2.5-9 4 18 4-9h5.5" />
13
- </svg>
14
- )