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