@tscircuit/schematic-viewer 1.4.0 → 1.4.2
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/biome.json +45 -0
- package/dist/index.css +7 -0
- package/dist/index.css.map +1 -0
- package/dist/index.js +158 -106
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
- package/src/Schematic.tsx +9 -6
- package/src/lib/render-context/index.ts +1 -1
- package/src/lib/types/source-component.ts +1 -1
- package/src/lib/utils/collect-element-refs.ts +4 -4
- package/src/lib/utils/colors.ts +215 -216
- package/src/lib/utils/direction-to-vec.ts +3 -3
- package/src/pages/style.css +5 -0
- package/src/schematic-components/SVGPathComponent.tsx +121 -63
- package/src/schematic-components/SchematicChip.tsx +128 -109
- package/src/schematic-components/SchematicComponent.tsx +17 -8
- package/src/schematic-components/SchematicComponentFromSymbol.tsx +3 -1
- package/src/schematic-components/SchematicNetLabel.tsx +3 -0
- package/src/schematic-components/SchematicText.tsx +4 -6
- package/src/schematic-components/SchematicTrace.tsx +5 -6
- package/src/schematic-components/TableViewer.tsx +1 -1
- package/src/schematic-components/index.tsx +0 -1
- package/src/stories/basics/schematic-net-label.stories.tsx +2 -0
- package/src/stories/bug-connections.stories.tsx +18 -16
- package/src/stories/bug-high-port-numbers.stories.tsx +22 -9
- package/src/stories/bug-one-sided.stories.tsx +17 -15
- package/src/stories/bug-pin-spacing.stories.tsx +19 -17
- package/src/stories/bugs/bug1-y-flip.stories.tsx +7 -5
- package/src/stories/bugs/bug5-diode.stories.tsx +3 -1
- package/src/stories/bugs/bug6-trace-scaling.stories.tsx +5 -41
- package/src/stories/led-circuit-react.stories.tsx +3 -8
- package/src/stories/rotated-resistor.stories.tsx +10 -8
- package/src/stories/three-sided-bug.stories.tsx +17 -15
|
@@ -1,37 +1,55 @@
|
|
|
1
|
-
import { useGlobalStore } from "lib/render-context"
|
|
2
|
-
import getSVGPathBounds from "lib/utils/get-svg-path-bounds"
|
|
3
|
-
import { useState } from "react"
|
|
4
|
-
import {
|
|
5
|
-
|
|
1
|
+
import { useGlobalStore } from "lib/render-context"
|
|
2
|
+
import getSVGPathBounds from "lib/utils/get-svg-path-bounds"
|
|
3
|
+
import { useState } from "react"
|
|
4
|
+
import {
|
|
5
|
+
applyToPoint,
|
|
6
|
+
compose,
|
|
7
|
+
scale,
|
|
8
|
+
toSVG,
|
|
9
|
+
translate,
|
|
10
|
+
} from "transformation-matrix"
|
|
11
|
+
import "../pages/style.css"
|
|
6
12
|
interface PathProps {
|
|
7
|
-
type?:
|
|
8
|
-
strokeWidth: number
|
|
9
|
-
stroke: string
|
|
10
|
-
fill?: string
|
|
11
|
-
d: string
|
|
13
|
+
type?: "path"
|
|
14
|
+
strokeWidth: number
|
|
15
|
+
stroke: string
|
|
16
|
+
fill?: string
|
|
17
|
+
d: string
|
|
12
18
|
}
|
|
13
19
|
|
|
14
20
|
interface CircleProps {
|
|
15
|
-
type:
|
|
16
|
-
cx: number
|
|
17
|
-
cy: number
|
|
18
|
-
r: number
|
|
19
|
-
strokeWidth: number
|
|
20
|
-
stroke: string
|
|
21
|
-
fill?: string
|
|
21
|
+
type: "circle"
|
|
22
|
+
cx: number
|
|
23
|
+
cy: number
|
|
24
|
+
r: number
|
|
25
|
+
strokeWidth: number
|
|
26
|
+
stroke: string
|
|
27
|
+
fill?: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface TextProps {
|
|
31
|
+
type: "text"
|
|
32
|
+
cx: number
|
|
33
|
+
cy: number
|
|
34
|
+
text: string
|
|
35
|
+
fontSize?: number
|
|
36
|
+
fill: string
|
|
37
|
+
anchor?: "start" | "middle" | "end"
|
|
38
|
+
rotation?: number
|
|
39
|
+
stroke?: string
|
|
22
40
|
}
|
|
23
41
|
|
|
24
|
-
export type SVGElement = PathProps | CircleProps
|
|
42
|
+
export type SVGElement = PathProps | CircleProps | TextProps
|
|
25
43
|
|
|
26
44
|
interface Props {
|
|
27
|
-
rotation: number
|
|
28
|
-
center: { x: number; y: number }
|
|
29
|
-
size: { width: number; height: number }
|
|
30
|
-
invertY?: boolean
|
|
31
|
-
shiftToBottom?: boolean
|
|
32
|
-
paths: SVGElement[]
|
|
33
|
-
zIndex?: number
|
|
34
|
-
hoverContent?: any
|
|
45
|
+
rotation: number
|
|
46
|
+
center: { x: number; y: number }
|
|
47
|
+
size: { width: number; height: number }
|
|
48
|
+
invertY?: boolean
|
|
49
|
+
shiftToBottom?: boolean
|
|
50
|
+
paths: SVGElement[]
|
|
51
|
+
zIndex?: number
|
|
52
|
+
hoverContent?: any
|
|
35
53
|
}
|
|
36
54
|
|
|
37
55
|
export const SVGPathComponent = ({
|
|
@@ -44,41 +62,50 @@ export const SVGPathComponent = ({
|
|
|
44
62
|
shiftToBottom,
|
|
45
63
|
hoverContent,
|
|
46
64
|
}: Props) => {
|
|
47
|
-
const ct = useGlobalStore((s) => s.camera_transform)
|
|
48
|
-
const pathBounds = getSVGPathBounds(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
65
|
+
const ct = useGlobalStore((s) => s.camera_transform)
|
|
66
|
+
const pathBounds = getSVGPathBounds(
|
|
67
|
+
paths
|
|
68
|
+
.filter((p): p is PathProps => p.type !== "circle" && p.type !== "text")
|
|
69
|
+
.map((p) => p.d),
|
|
70
|
+
)
|
|
71
|
+
const padding = { x: 0, y: 0 }
|
|
72
|
+
const absoluteCenter = applyToPoint(ct, center)
|
|
52
73
|
const innerSize = {
|
|
53
74
|
width: size.width * ct.a,
|
|
54
75
|
height: size.height * Math.abs(ct.d),
|
|
55
|
-
}
|
|
76
|
+
}
|
|
56
77
|
const fullSize = {
|
|
57
78
|
width: innerSize.width + padding.x * 2,
|
|
58
79
|
height: innerSize.height + padding.y * 2,
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
? innerSize.height / pathBounds.height
|
|
68
|
-
: innerSize.width / pathBounds.width;
|
|
69
|
-
|
|
80
|
+
}
|
|
81
|
+
const [hovering, setHovering] = useState(false)
|
|
82
|
+
const svgLeft = absoluteCenter.x - fullSize.width / 2
|
|
83
|
+
const svgTop = absoluteCenter.y - fullSize.height / 2
|
|
84
|
+
const preferredRatio =
|
|
85
|
+
pathBounds.width === 0
|
|
86
|
+
? innerSize.height / pathBounds.height
|
|
87
|
+
: innerSize.width / pathBounds.width
|
|
70
88
|
const svgToScreen = compose(
|
|
71
89
|
scale(
|
|
72
|
-
pathBounds.width === 0
|
|
73
|
-
|
|
90
|
+
pathBounds.width === 0
|
|
91
|
+
? preferredRatio
|
|
92
|
+
: fullSize.width / pathBounds.width,
|
|
93
|
+
pathBounds.height === 0
|
|
94
|
+
? preferredRatio
|
|
95
|
+
: fullSize.height / pathBounds.height,
|
|
74
96
|
),
|
|
75
97
|
translate(-pathBounds.minX, -pathBounds.minY),
|
|
76
|
-
)
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
const baseFontSize = 0.15 // Fixed base font size in schematic units
|
|
77
101
|
|
|
78
102
|
return (
|
|
103
|
+
// biome-ignore lint/a11y/noSvgWithoutTitle: <explanation>
|
|
79
104
|
<svg
|
|
80
105
|
onMouseOver={() => setHovering(Boolean(hoverContent))}
|
|
106
|
+
onFocus={() => setHovering(Boolean(hoverContent))}
|
|
81
107
|
onMouseOut={() => setHovering(false)}
|
|
108
|
+
onBlur={() => setHovering(false)}
|
|
82
109
|
style={{
|
|
83
110
|
position: "absolute",
|
|
84
111
|
cursor: hovering ? "pointer" : undefined,
|
|
@@ -95,20 +122,51 @@ export const SVGPathComponent = ({
|
|
|
95
122
|
width={fullSize.width}
|
|
96
123
|
height={fullSize.height}
|
|
97
124
|
>
|
|
98
|
-
{paths.map((p, i) =>
|
|
99
|
-
p.type ===
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
125
|
+
{paths.map((p, i) => {
|
|
126
|
+
if (p.type === "circle") {
|
|
127
|
+
return (
|
|
128
|
+
<circle
|
|
129
|
+
key={`${p.type}-${i}`}
|
|
130
|
+
transform={toSVG(compose(scale(1, 1), svgToScreen))}
|
|
131
|
+
cx={p.cx}
|
|
132
|
+
cy={p.cy}
|
|
133
|
+
r={p.r}
|
|
134
|
+
fill={"none"}
|
|
135
|
+
strokeWidth={2.25 * (p.strokeWidth || 1)}
|
|
136
|
+
stroke={p.stroke || "red"}
|
|
137
|
+
/>
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
if (p.type === "text") {
|
|
141
|
+
const transformedPos = applyToPoint(svgToScreen, { x: p.cx, y: p.cy })
|
|
142
|
+
const scaleFactor = fullSize.width / pathBounds.width || 1
|
|
143
|
+
|
|
144
|
+
return (
|
|
145
|
+
<g key={`${p.type}-${i}`}>
|
|
146
|
+
<text
|
|
147
|
+
className="schematic-text"
|
|
148
|
+
x={transformedPos.x}
|
|
149
|
+
y={transformedPos.y}
|
|
150
|
+
fill={p.fill}
|
|
151
|
+
fontSize={baseFontSize * scaleFactor}
|
|
152
|
+
textAnchor={p.anchor || "middle"}
|
|
153
|
+
dominantBaseline="middle"
|
|
154
|
+
transform={`scale(1,-1) rotate(${p.rotation || 0})`}
|
|
155
|
+
style={{
|
|
156
|
+
transformBox: "fill-box",
|
|
157
|
+
transformOrigin: "center",
|
|
158
|
+
}}
|
|
159
|
+
stroke={p.stroke}
|
|
160
|
+
>
|
|
161
|
+
{p.text}
|
|
162
|
+
</text>
|
|
163
|
+
</g>
|
|
164
|
+
)
|
|
165
|
+
}
|
|
166
|
+
// Handle the "path" type directly
|
|
167
|
+
return (
|
|
110
168
|
<path
|
|
111
|
-
key={i}
|
|
169
|
+
key={`${p.type}-${i}`}
|
|
112
170
|
transform={toSVG(svgToScreen)}
|
|
113
171
|
fill={p.fill ?? "none"}
|
|
114
172
|
strokeLinecap="round"
|
|
@@ -117,9 +175,9 @@ export const SVGPathComponent = ({
|
|
|
117
175
|
d={p.d || ""}
|
|
118
176
|
/>
|
|
119
177
|
)
|
|
120
|
-
)}
|
|
178
|
+
})}
|
|
121
179
|
</svg>
|
|
122
|
-
)
|
|
123
|
-
}
|
|
180
|
+
)
|
|
181
|
+
}
|
|
124
182
|
|
|
125
|
-
export default SVGPathComponent
|
|
183
|
+
export default SVGPathComponent
|
|
@@ -1,130 +1,161 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import
|
|
1
|
+
import type {
|
|
2
|
+
AnyCircuitElement,
|
|
3
|
+
SchematicPort as OriginalSchematicPort,
|
|
4
|
+
SchematicComponent,
|
|
5
|
+
} from "circuit-json"
|
|
6
|
+
import type * as Type from "lib/types"
|
|
7
|
+
import { colorMap } from "lib/utils/colors"
|
|
8
|
+
import type React from "react"
|
|
9
|
+
import SVGPathComponent from "./SVGPathComponent"
|
|
10
|
+
import SchematicText from "./SchematicText"
|
|
7
11
|
|
|
8
12
|
interface Props {
|
|
9
13
|
component: {
|
|
10
|
-
source: Type.SimpleBug
|
|
11
|
-
schematic: SchematicComponent
|
|
12
|
-
allElements: AnyCircuitElement[]
|
|
14
|
+
source: Type.SimpleBug
|
|
15
|
+
schematic: SchematicComponent
|
|
16
|
+
allElements: AnyCircuitElement[]
|
|
13
17
|
}
|
|
14
18
|
}
|
|
15
19
|
|
|
16
|
-
type ExtendedCenter = OriginalSchematicPort[
|
|
17
|
-
side: "left" | "right" | "top" | "bottom"
|
|
18
|
-
pinNumber: number
|
|
19
|
-
distanceFromEdge: number
|
|
20
|
-
trueIndex: number
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
type SchematicPort = Omit<OriginalSchematicPort, 'center'> & {
|
|
24
|
-
center: ExtendedCenter;
|
|
25
|
-
};
|
|
20
|
+
type ExtendedCenter = OriginalSchematicPort["center"] & {
|
|
21
|
+
side: "left" | "right" | "top" | "bottom" | "center"
|
|
22
|
+
pinNumber: number
|
|
23
|
+
distanceFromEdge: number
|
|
24
|
+
trueIndex: number
|
|
25
|
+
}
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const chipWidth = size.width;
|
|
31
|
-
const chipHeight = size.height;
|
|
27
|
+
type SchematicPort = Omit<OriginalSchematicPort, "center"> & {
|
|
28
|
+
center: ExtendedCenter
|
|
29
|
+
}
|
|
32
30
|
|
|
33
|
-
|
|
31
|
+
export const SchematicChip: React.FC<Props> = ({
|
|
32
|
+
component: { source, schematic, allElements },
|
|
33
|
+
}) => {
|
|
34
|
+
const { center, size, rotation, schematic_component_id } = schematic
|
|
35
|
+
const { manufacturerPartNumber, name } = source
|
|
36
|
+
const chipWidth = size.width
|
|
37
|
+
const chipHeight = size.height
|
|
38
|
+
|
|
39
|
+
const paths: Array<{
|
|
40
|
+
type: "path" | "circle" | "text"
|
|
41
|
+
strokeWidth: number
|
|
42
|
+
stroke: string
|
|
43
|
+
fill?: string
|
|
44
|
+
d?: string
|
|
45
|
+
cx?: number
|
|
46
|
+
cy?: number
|
|
47
|
+
r?: number
|
|
48
|
+
text?: string
|
|
49
|
+
anchor?: string
|
|
50
|
+
rotation?: number
|
|
51
|
+
}> = []
|
|
34
52
|
|
|
35
53
|
// Main chip rectangle
|
|
36
54
|
paths.push({
|
|
37
|
-
type:
|
|
55
|
+
type: "path",
|
|
38
56
|
strokeWidth: 0.02,
|
|
39
57
|
stroke: colorMap.schematic.component_outline,
|
|
40
58
|
fill: colorMap.schematic.component_body,
|
|
41
59
|
d: `M ${-chipWidth / 2},${-chipHeight / 2} h ${chipWidth} v ${chipHeight} h ${-chipWidth} Z`,
|
|
42
|
-
})
|
|
60
|
+
})
|
|
43
61
|
|
|
44
62
|
const schematicPorts = allElements.filter(
|
|
45
|
-
(item): item is SchematicPort =>
|
|
46
|
-
item.type === "schematic_port" &&
|
|
47
|
-
item.schematic_component_id === schematic_component_id
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
const portLength = 0.
|
|
51
|
-
const circleRadius = 0.
|
|
52
|
-
const labelOffset = 0.1
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
let
|
|
59
|
-
let
|
|
60
|
-
let
|
|
63
|
+
(item): item is SchematicPort =>
|
|
64
|
+
item.type === "schematic_port" &&
|
|
65
|
+
item.schematic_component_id === schematic_component_id,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
const portLength = 0.5
|
|
69
|
+
const circleRadius = 0.04
|
|
70
|
+
const labelOffset = 0.1
|
|
71
|
+
|
|
72
|
+
for (const port of schematicPorts) {
|
|
73
|
+
const { side, pinNumber, distanceFromEdge } = port.center
|
|
74
|
+
let x = 0
|
|
75
|
+
let y = 0
|
|
76
|
+
let endX = 0
|
|
77
|
+
let endY = 0
|
|
78
|
+
let pinX = 0
|
|
79
|
+
let pinY = 0
|
|
80
|
+
let textAnchor = "middle"
|
|
81
|
+
let rotation = 0
|
|
82
|
+
|
|
83
|
+
if (side === "center") {
|
|
84
|
+
continue
|
|
85
|
+
}
|
|
61
86
|
|
|
62
87
|
switch (side) {
|
|
63
88
|
case "left":
|
|
64
|
-
x = -chipWidth / 2
|
|
65
|
-
y = -chipHeight / 2 + distanceFromEdge
|
|
66
|
-
endX = x - portLength
|
|
67
|
-
endY = y
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
textAnchor = "
|
|
71
|
-
break
|
|
89
|
+
x = -chipWidth / 2
|
|
90
|
+
y = -chipHeight / 2 + distanceFromEdge
|
|
91
|
+
endX = x - portLength
|
|
92
|
+
endY = y
|
|
93
|
+
pinX = x - portLength / 2
|
|
94
|
+
pinY = y + labelOffset
|
|
95
|
+
textAnchor = "middle"
|
|
96
|
+
break
|
|
72
97
|
case "right":
|
|
73
|
-
x = chipWidth / 2
|
|
74
|
-
y = chipHeight / 2 - distanceFromEdge
|
|
75
|
-
endX = x + portLength
|
|
76
|
-
endY = y
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
textAnchor = "start"
|
|
80
|
-
break
|
|
98
|
+
x = chipWidth / 2
|
|
99
|
+
y = chipHeight / 2 - distanceFromEdge
|
|
100
|
+
endX = x + portLength
|
|
101
|
+
endY = y
|
|
102
|
+
pinX = x + portLength / 2 - labelOffset
|
|
103
|
+
pinY = y + labelOffset
|
|
104
|
+
textAnchor = "start"
|
|
105
|
+
break
|
|
81
106
|
case "bottom":
|
|
82
|
-
x = -chipWidth / 2 + distanceFromEdge
|
|
83
|
-
y = -chipHeight / 2
|
|
84
|
-
endX = x
|
|
85
|
-
endY = y - portLength
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
107
|
+
x = -chipWidth / 2 + distanceFromEdge
|
|
108
|
+
y = -chipHeight / 2
|
|
109
|
+
endX = x
|
|
110
|
+
endY = y - portLength
|
|
111
|
+
pinX = x - labelOffset
|
|
112
|
+
pinY = y - portLength / 2
|
|
113
|
+
rotation = -90
|
|
114
|
+
break
|
|
89
115
|
case "top":
|
|
90
|
-
x = chipWidth / 2 - distanceFromEdge
|
|
91
|
-
y = chipHeight / 2
|
|
92
|
-
endX = x
|
|
93
|
-
endY = y + portLength
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
116
|
+
x = chipWidth / 2 - distanceFromEdge
|
|
117
|
+
y = chipHeight / 2
|
|
118
|
+
endX = x
|
|
119
|
+
endY = y + portLength
|
|
120
|
+
pinX = x - labelOffset
|
|
121
|
+
pinY = y + portLength / 2
|
|
122
|
+
rotation = -90
|
|
123
|
+
break
|
|
97
124
|
}
|
|
98
125
|
|
|
99
126
|
// Port line
|
|
100
127
|
paths.push({
|
|
101
|
-
type:
|
|
102
|
-
strokeWidth: 0.
|
|
128
|
+
type: "path",
|
|
129
|
+
strokeWidth: 0.015,
|
|
103
130
|
stroke: colorMap.schematic.component_outline,
|
|
104
131
|
d: `M ${x},${y} L ${endX},${endY}`,
|
|
105
|
-
})
|
|
132
|
+
})
|
|
106
133
|
|
|
107
134
|
// Port circle at the end of the line
|
|
108
135
|
paths.push({
|
|
109
|
-
type:
|
|
136
|
+
type: "circle",
|
|
110
137
|
cx: endX,
|
|
111
138
|
cy: endY,
|
|
112
139
|
r: circleRadius,
|
|
113
|
-
strokeWidth: 0.
|
|
140
|
+
strokeWidth: 0.005,
|
|
114
141
|
stroke: colorMap.schematic.component_outline,
|
|
115
142
|
fill: colorMap.schematic.component_outline,
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
// Add pin
|
|
119
|
-
if(pinNumber !== undefined) {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
// Add pin number
|
|
146
|
+
if (pinNumber !== undefined) {
|
|
147
|
+
paths.push({
|
|
148
|
+
type: "text",
|
|
149
|
+
cx: pinX,
|
|
150
|
+
cy: pinY,
|
|
123
151
|
text: `${pinNumber}`,
|
|
124
|
-
anchor: textAnchor
|
|
125
|
-
|
|
152
|
+
anchor: textAnchor,
|
|
153
|
+
rotation: rotation,
|
|
154
|
+
strokeWidth: 0.005,
|
|
155
|
+
stroke: colorMap.schematic.pin_number,
|
|
156
|
+
})
|
|
126
157
|
}
|
|
127
|
-
}
|
|
158
|
+
}
|
|
128
159
|
|
|
129
160
|
return (
|
|
130
161
|
<>
|
|
@@ -134,25 +165,10 @@ export const SchematicChip: React.FC<Props> = ({ component: { source, schematic,
|
|
|
134
165
|
size={size}
|
|
135
166
|
paths={paths as any}
|
|
136
167
|
/>
|
|
137
|
-
{pinLabels.map((label, index) => (
|
|
138
|
-
<SchematicText
|
|
139
|
-
key={index}
|
|
140
|
-
schematic_text={{
|
|
141
|
-
anchor: label.anchor as any,
|
|
142
|
-
position: {
|
|
143
|
-
x: center.x + label.x,
|
|
144
|
-
y: center.y + label.y,
|
|
145
|
-
},
|
|
146
|
-
schematic_component_id: "SYNTHETIC",
|
|
147
|
-
schematic_text_id: `PIN_LABEL_${index}`,
|
|
148
|
-
text: label.text,
|
|
149
|
-
type: "schematic_text",
|
|
150
|
-
}}
|
|
151
|
-
/>
|
|
152
|
-
))}
|
|
153
168
|
<SchematicText
|
|
154
169
|
schematic_text={{
|
|
155
|
-
anchor: "
|
|
170
|
+
anchor: "right",
|
|
171
|
+
rotation: 0,
|
|
156
172
|
position: {
|
|
157
173
|
x: center.x,
|
|
158
174
|
y: center.y - chipHeight / 2 - 0.2,
|
|
@@ -161,11 +177,13 @@ export const SchematicChip: React.FC<Props> = ({ component: { source, schematic,
|
|
|
161
177
|
schematic_text_id: "SYNTHETIC_MPN",
|
|
162
178
|
text: manufacturerPartNumber,
|
|
163
179
|
type: "schematic_text",
|
|
180
|
+
color: colorMap.schematic.reference,
|
|
164
181
|
}}
|
|
165
182
|
/>
|
|
166
183
|
<SchematicText
|
|
167
184
|
schematic_text={{
|
|
168
|
-
anchor: "
|
|
185
|
+
anchor: "right",
|
|
186
|
+
rotation: 0,
|
|
169
187
|
position: {
|
|
170
188
|
x: center.x,
|
|
171
189
|
y: center.y + chipHeight / 2 + 0.2,
|
|
@@ -174,10 +192,11 @@ export const SchematicChip: React.FC<Props> = ({ component: { source, schematic,
|
|
|
174
192
|
schematic_text_id: "SYNTHETIC_NAME",
|
|
175
193
|
text: name,
|
|
176
194
|
type: "schematic_text",
|
|
195
|
+
color: colorMap.schematic.reference,
|
|
177
196
|
}}
|
|
178
197
|
/>
|
|
179
198
|
</>
|
|
180
|
-
)
|
|
181
|
-
}
|
|
199
|
+
)
|
|
200
|
+
}
|
|
182
201
|
|
|
183
|
-
export default SchematicChip
|
|
202
|
+
export default SchematicChip
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type {
|
|
2
|
+
AnyCircuitElement,
|
|
3
|
+
SchematicComponent as SchematicComponentType,
|
|
4
|
+
} from "circuit-json"
|
|
2
5
|
import * as Component from "./"
|
|
3
6
|
|
|
4
7
|
interface Props {
|
|
@@ -19,19 +22,25 @@ export const SchematicComponent = ({ component }: Props) => {
|
|
|
19
22
|
if (!source.ftype) return null
|
|
20
23
|
|
|
21
24
|
switch (source.ftype) {
|
|
22
|
-
case "simple_resistor":
|
|
25
|
+
case "simple_resistor":
|
|
23
26
|
case "simple_capacitor":
|
|
24
27
|
case "simple_power_source":
|
|
25
28
|
case "simple_ground":
|
|
26
29
|
case "simple_inductor":
|
|
27
|
-
case "simple_diode":
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
case "simple_diode": {
|
|
31
|
+
return (
|
|
32
|
+
<Component.SchematicComponentFromSymbol
|
|
33
|
+
component={{ source, schematic }}
|
|
34
|
+
/>
|
|
35
|
+
)
|
|
30
36
|
}
|
|
31
37
|
case "simple_chip":
|
|
32
|
-
case "simple_bug":
|
|
33
|
-
|
|
34
|
-
|
|
38
|
+
case "simple_bug": {
|
|
39
|
+
return (
|
|
40
|
+
<Component.SchematicChip
|
|
41
|
+
component={{ source, schematic, allElements }}
|
|
42
|
+
/>
|
|
43
|
+
)
|
|
35
44
|
}
|
|
36
45
|
default: {
|
|
37
46
|
return <div>unknown ftype: {component.source.ftype}</div>
|
|
@@ -10,7 +10,9 @@ interface Props {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export const SchematicComponentFromSymbol = ({
|
|
13
|
+
export const SchematicComponentFromSymbol = ({
|
|
14
|
+
component: { source, schematic },
|
|
15
|
+
}: Props) => {
|
|
14
16
|
const { center, rotation } = schematic
|
|
15
17
|
// Get the resistor symbol paths
|
|
16
18
|
const symbol = symbols[schematic.symbol_name]
|
|
@@ -3,6 +3,7 @@ import SVGPathComponent from "./SVGPathComponent"
|
|
|
3
3
|
import SchematicText from "./SchematicText"
|
|
4
4
|
import { getRotationFromAnchorSide } from "lib/utils/get-rotation-from-anchor-side"
|
|
5
5
|
import { getVecFromAnchorSide } from "lib/utils/get-vec-from-anchor-side"
|
|
6
|
+
import { colorMap } from "lib/utils/colors"
|
|
6
7
|
|
|
7
8
|
export const SchematicNetLabel = ({
|
|
8
9
|
net_label,
|
|
@@ -44,6 +45,7 @@ export const SchematicNetLabel = ({
|
|
|
44
45
|
/>
|
|
45
46
|
<SchematicText
|
|
46
47
|
schematic_text={{
|
|
48
|
+
rotation: is_vertical ? 0 : getRotationFromAnchorSide(anchor_side),
|
|
47
49
|
anchor: is_vertical ? "center" : anchor_side,
|
|
48
50
|
position: {
|
|
49
51
|
x: net_label.center.x + anchor_vec.x,
|
|
@@ -53,6 +55,7 @@ export const SchematicNetLabel = ({
|
|
|
53
55
|
schematic_text_id: "SYNTHETIC",
|
|
54
56
|
text: net_label.text,
|
|
55
57
|
type: "schematic_text",
|
|
58
|
+
color: colorMap.schematic.net_name,
|
|
56
59
|
}}
|
|
57
60
|
/>
|
|
58
61
|
</>
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import SVGPathComponent from "./SVGPathComponent"
|
|
3
|
-
import Path from "svg-path-generator"
|
|
4
|
-
import getSVGPathBounds from "lib/utils/get-svg-path-bounds"
|
|
1
|
+
import type { SchematicText as SchematicTextType } from "circuit-json"
|
|
5
2
|
import { useGlobalStore } from "lib/render-context"
|
|
6
|
-
import { applyToPoint } from "transformation-matrix"
|
|
7
3
|
import useMeasure from "react-use-measure"
|
|
4
|
+
import { applyToPoint } from "transformation-matrix"
|
|
8
5
|
|
|
9
6
|
interface Props {
|
|
10
|
-
schematic_text:
|
|
7
|
+
schematic_text: SchematicTextType
|
|
11
8
|
}
|
|
12
9
|
|
|
13
10
|
export const SchematicText = ({ schematic_text }: Props) => {
|
|
@@ -36,6 +33,7 @@ export const SchematicText = ({ schematic_text }: Props) => {
|
|
|
36
33
|
fontSize: projectedTextSize,
|
|
37
34
|
left: tPos.x + offset[0],
|
|
38
35
|
top: tPos.y + offset[1],
|
|
36
|
+
color: schematic_text.color,
|
|
39
37
|
}}
|
|
40
38
|
>
|
|
41
39
|
{text}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import * as Type from "lib/types"
|
|
2
|
-
import
|
|
3
|
-
import Path from "svg-path-generator"
|
|
1
|
+
import type * as Type from "lib/types"
|
|
2
|
+
import { colorMap } from "lib/utils/colors"
|
|
4
3
|
import getSVGPathBounds from "lib/utils/get-svg-path-bounds"
|
|
4
|
+
import Path from "svg-path-generator"
|
|
5
5
|
import RenderError from "./RenderError"
|
|
6
|
-
import
|
|
7
|
-
import { colorMap } from "lib/utils/colors"
|
|
6
|
+
import SVGPathComponent from "./SVGPathComponent"
|
|
8
7
|
|
|
9
8
|
interface Props {
|
|
10
9
|
trace: {
|
|
@@ -40,7 +39,7 @@ export const SchematicTrace = ({ trace: { source, schematic } }: Props) => {
|
|
|
40
39
|
size={pathBounds}
|
|
41
40
|
paths={[
|
|
42
41
|
{
|
|
43
|
-
stroke:colorMap.schematic.wire,
|
|
42
|
+
stroke: colorMap.schematic.wire,
|
|
44
43
|
strokeWidth: 0.01,
|
|
45
44
|
d,
|
|
46
45
|
},
|