@tscircuit/schematic-viewer 1.3.0 → 1.4.0
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/README.md +1 -1
- package/dist/index.d.ts +3 -4
- package/dist/index.js +694 -687
- package/dist/index.js.map +1 -1
- package/package.json +5 -6
- package/src/Schematic.tsx +139 -65
- package/src/lib/types/core.ts +14 -49
- package/src/lib/types/source-component.ts +5 -0
- package/src/lib/utils/collect-element-refs.ts +1 -0
- package/src/lib/utils/colors.ts +236 -0
- package/src/schematic-components/SVGPathComponent.tsx +84 -144
- package/src/schematic-components/SchematicChip.tsx +183 -0
- package/src/schematic-components/SchematicComponent.tsx +18 -24
- package/src/schematic-components/SchematicComponentFromSymbol.tsx +44 -0
- package/src/schematic-components/SchematicElement.tsx +0 -28
- package/src/schematic-components/SchematicTrace.tsx +4 -3
- package/src/schematic-components/index.tsx +7 -14
- package/src/stories/basics/schematic-net-labels-2.stories.tsx +22 -20
- package/src/stories/bug-connections.stories.tsx +3 -0
- package/src/stories/bug-high-port-numbers.stories.tsx +99 -85
- package/src/stories/bugs/bug3-scaling-trace.stories.tsx +11 -5
- package/src/stories/bugs/bug4-schematic-line.stories.tsx +0 -1
- package/src/stories/bugs/bug5-diode.stories.tsx +0 -1
- package/src/stories/bugs/bug8-autolayout.stories.tsx +20 -29
- package/src/stories/circuit-components/diode.stories.tsx +3 -1
- package/src/stories/circuit-components/resistor.stories.tsx +3 -1
- package/src/stories/led-circuit-react.stories.tsx +40 -48
- package/src/pages/led-circuit.tsx +0 -96
- package/src/schematic-components/ProjectComponent.tsx +0 -70
- package/src/schematic-components/SchematicBox.tsx +0 -29
- package/src/schematic-components/SchematicBug.tsx +0 -107
- package/src/schematic-components/SchematicLine.tsx +0 -48
- package/src/schematic-components/SchematicPath.tsx +0 -51
- package/src/schematic-components/SchematicPort.tsx +0 -63
- package/src/schematic-components/SimpleCapacitor.tsx +0 -29
- package/src/schematic-components/SimpleDiode.tsx +0 -42
- package/src/schematic-components/SimpleGround.tsx +0 -30
- package/src/schematic-components/SimpleInductor.tsx +0 -29
- package/src/schematic-components/SimplePowerSource.tsx +0 -43
- package/src/schematic-components/SimpleResistor.tsx +0 -28
- package/src/stories/led-circuit-builder.stories.tsx +0 -104
|
@@ -1,30 +1,37 @@
|
|
|
1
|
-
import { useGlobalStore } from "lib/render-context"
|
|
2
|
-
import getSVGPathBounds from "lib/utils/get-svg-path-bounds"
|
|
3
|
-
import {
|
|
1
|
+
import { useGlobalStore } from "lib/render-context";
|
|
2
|
+
import getSVGPathBounds from "lib/utils/get-svg-path-bounds";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { applyToPoint, compose, scale, toSVG, translate } from "transformation-matrix";
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
interface PathProps {
|
|
7
|
+
type?: 'path';
|
|
8
|
+
strokeWidth: number;
|
|
9
|
+
stroke: string;
|
|
10
|
+
fill?: string;
|
|
11
|
+
d: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface CircleProps {
|
|
15
|
+
type: 'circle';
|
|
16
|
+
cx: number;
|
|
17
|
+
cy: number;
|
|
18
|
+
r: number;
|
|
19
|
+
strokeWidth: number;
|
|
20
|
+
stroke: string;
|
|
21
|
+
fill?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type SVGElement = PathProps | CircleProps;
|
|
13
25
|
|
|
14
26
|
interface Props {
|
|
15
|
-
rotation: number
|
|
16
|
-
center: { x: number; y: number }
|
|
17
|
-
size: { width: number; height: number }
|
|
18
|
-
invertY?: boolean
|
|
19
|
-
shiftToBottom?: boolean
|
|
20
|
-
paths:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
fill?: string
|
|
24
|
-
d: string
|
|
25
|
-
}>
|
|
26
|
-
zIndex?: number
|
|
27
|
-
hoverContent?: any
|
|
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;
|
|
28
35
|
}
|
|
29
36
|
|
|
30
37
|
export const SVGPathComponent = ({
|
|
@@ -37,136 +44,69 @@ export const SVGPathComponent = ({
|
|
|
37
44
|
shiftToBottom,
|
|
38
45
|
hoverContent,
|
|
39
46
|
}: Props) => {
|
|
40
|
-
const ct = useGlobalStore((s) => s.camera_transform)
|
|
41
|
-
const pathBounds = getSVGPathBounds(paths.
|
|
42
|
-
// Margin in SVG Space
|
|
43
|
-
const badRatio =
|
|
44
|
-
Math.abs(pathBounds.width / pathBounds.height - size.width / size.height) >
|
|
45
|
-
0.01
|
|
46
|
-
if (badRatio) {
|
|
47
|
-
// console.warn(
|
|
48
|
-
// `Ratio doesn't match for component. ${pathBounds.width}:${pathBounds.height} is not close to ${size.width}:${size.height}`
|
|
49
|
-
// )
|
|
50
|
-
}
|
|
51
|
-
// pathBounds.height = Math.max(pathBounds.height, 0.01)
|
|
52
|
-
// pathBounds.width = Math.max(pathBounds.width, 0.01)
|
|
53
|
-
|
|
54
|
-
// Three sizes:
|
|
55
|
-
// pathBound size (the size of the path in "d")
|
|
56
|
-
// innerSize (the screen-space size of the path)
|
|
57
|
-
// fullSize (the screen-space size of the svg element, innerSize plus padding)
|
|
58
|
-
|
|
59
|
-
const padding = {
|
|
60
|
-
x: 0,
|
|
61
|
-
y: 0,
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const absoluteCenter = applyToPoint(ct, center)
|
|
47
|
+
const ct = useGlobalStore((s) => s.camera_transform);
|
|
48
|
+
const pathBounds = getSVGPathBounds(paths.filter((p): p is PathProps => p.type !== 'circle').map(p => p.d));
|
|
65
49
|
|
|
50
|
+
const padding = { x: 0, y: 0 };
|
|
51
|
+
const absoluteCenter = applyToPoint(ct, center);
|
|
66
52
|
const innerSize = {
|
|
67
53
|
width: size.width * ct.a,
|
|
68
54
|
height: size.height * Math.abs(ct.d),
|
|
69
|
-
}
|
|
70
|
-
|
|
55
|
+
};
|
|
71
56
|
const fullSize = {
|
|
72
57
|
width: innerSize.width + padding.x * 2,
|
|
73
58
|
height: innerSize.height + padding.y * 2,
|
|
74
|
-
}
|
|
59
|
+
};
|
|
75
60
|
|
|
76
|
-
const [hovering, setHovering] = useState(false)
|
|
61
|
+
const [hovering, setHovering] = useState(false);
|
|
77
62
|
|
|
78
|
-
const svgLeft = absoluteCenter.x - fullSize.width / 2
|
|
79
|
-
const svgTop = absoluteCenter.y - fullSize.height / 2
|
|
63
|
+
const svgLeft = absoluteCenter.x - fullSize.width / 2;
|
|
64
|
+
const svgTop = absoluteCenter.y - fullSize.height / 2;
|
|
80
65
|
|
|
81
|
-
|
|
82
|
-
|
|
66
|
+
const preferredRatio = pathBounds.width === 0
|
|
67
|
+
? innerSize.height / pathBounds.height
|
|
68
|
+
: innerSize.width / pathBounds.width;
|
|
83
69
|
|
|
84
|
-
// console.log(
|
|
85
|
-
// pathBounds,
|
|
86
|
-
// fullSize,
|
|
87
|
-
// fullSize.width / pathBounds.width,
|
|
88
|
-
// fullSize.height / pathBounds.height
|
|
89
|
-
// )
|
|
90
|
-
const preferredRatio =
|
|
91
|
-
pathBounds.width === 0
|
|
92
|
-
? innerSize.height / pathBounds.height
|
|
93
|
-
: innerSize.width / pathBounds.width
|
|
94
70
|
const svgToScreen = compose(
|
|
95
|
-
// translate(0, 0)
|
|
96
71
|
scale(
|
|
97
|
-
pathBounds.width === 0
|
|
98
|
-
|
|
99
|
-
: fullSize.width / pathBounds.width,
|
|
100
|
-
pathBounds.height === 0
|
|
101
|
-
? preferredRatio
|
|
102
|
-
: fullSize.height / pathBounds.height
|
|
72
|
+
pathBounds.width === 0 ? preferredRatio : fullSize.width / pathBounds.width,
|
|
73
|
+
pathBounds.height === 0 ? preferredRatio : fullSize.height / pathBounds.height,
|
|
103
74
|
),
|
|
104
|
-
translate(-pathBounds.minX, -pathBounds.minY)
|
|
105
|
-
|
|
106
|
-
)
|
|
107
|
-
// console.log(svgToScreen)
|
|
108
|
-
// console.log(toSVG(svgToScreen))
|
|
109
|
-
// console.log(paths[0].d)
|
|
110
|
-
// translate(..., ...),
|
|
75
|
+
translate(-pathBounds.minX, -pathBounds.minY),
|
|
76
|
+
);
|
|
111
77
|
|
|
112
78
|
return (
|
|
113
|
-
|
|
114
|
-
{
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
79
|
+
<svg
|
|
80
|
+
onMouseOver={() => setHovering(Boolean(hoverContent))}
|
|
81
|
+
onMouseOut={() => setHovering(false)}
|
|
82
|
+
style={{
|
|
83
|
+
position: "absolute",
|
|
84
|
+
cursor: hovering ? "pointer" : undefined,
|
|
85
|
+
zIndex,
|
|
86
|
+
transform: [
|
|
87
|
+
invertY ? "scale(1, 1)" : "scale(1, -1)",
|
|
88
|
+
shiftToBottom ? "translate(0, 100%)" : "",
|
|
89
|
+
rotation === 0 ? "" : `rotate(${rotation}deg)`,
|
|
90
|
+
].join(" "),
|
|
91
|
+
left: svgLeft,
|
|
92
|
+
top: svgTop,
|
|
93
|
+
}}
|
|
94
|
+
overflow="visible"
|
|
95
|
+
width={fullSize.width}
|
|
96
|
+
height={fullSize.height}
|
|
97
|
+
>
|
|
98
|
+
{paths.map((p, i) =>
|
|
99
|
+
p.type === 'circle' ? (
|
|
100
|
+
<circle
|
|
101
|
+
key={i}
|
|
102
|
+
cx={p.cx}
|
|
103
|
+
cy={p.cy}
|
|
104
|
+
r={p.r}
|
|
105
|
+
fill={p.fill ?? "none"}
|
|
106
|
+
strokeWidth={1.5 * (p.strokeWidth || 1)}
|
|
107
|
+
stroke={p.stroke || "red"}
|
|
128
108
|
/>
|
|
129
|
-
|
|
130
|
-
style={{
|
|
131
|
-
position: "absolute",
|
|
132
|
-
left: svgLeft + fullSize.width + 10,
|
|
133
|
-
pointerEvents: "none",
|
|
134
|
-
zIndex: 1000,
|
|
135
|
-
color: "red",
|
|
136
|
-
mixBlendMode: "difference",
|
|
137
|
-
top: svgTop,
|
|
138
|
-
fontFamily: "monospace",
|
|
139
|
-
fontSize: 14,
|
|
140
|
-
}}
|
|
141
|
-
>
|
|
142
|
-
{hoverContent}
|
|
143
|
-
</div>
|
|
144
|
-
</>
|
|
145
|
-
)}
|
|
146
|
-
<svg
|
|
147
|
-
onMouseOver={() => setHovering(Boolean(hoverContent))}
|
|
148
|
-
onMouseOut={() => setHovering(false)}
|
|
149
|
-
style={{
|
|
150
|
-
position: "absolute",
|
|
151
|
-
// backgroundColor: hovering ? "rgba(0, 0, 255, 0.5)" : "transparent",
|
|
152
|
-
cursor: hovering ? "pointer" : undefined,
|
|
153
|
-
zIndex,
|
|
154
|
-
transform: [
|
|
155
|
-
invertY ? "scale(1, 1)" : "scale(1, -1)", // TODO based on ct.d
|
|
156
|
-
shiftToBottom ? "translate(0, 100%)" : "",
|
|
157
|
-
rotation === 0 ? "" : `rotate(${rotation}rad)`,
|
|
158
|
-
].join(" "),
|
|
159
|
-
left: svgLeft,
|
|
160
|
-
top: svgTop,
|
|
161
|
-
// overflow: "hidden",
|
|
162
|
-
// backgroundColor: badRatio ? "rgba(255, 0, 0, 0.1)" : "transparent",
|
|
163
|
-
// backgroundColor: "rgba(255, 0, 0, 0.1)",
|
|
164
|
-
}}
|
|
165
|
-
overflow="visible"
|
|
166
|
-
width={fullSize.width}
|
|
167
|
-
height={fullSize.height}
|
|
168
|
-
>
|
|
169
|
-
{paths.map((p, i) => (
|
|
109
|
+
) : (
|
|
170
110
|
<path
|
|
171
111
|
key={i}
|
|
172
112
|
transform={toSVG(svgToScreen)}
|
|
@@ -174,12 +114,12 @@ export const SVGPathComponent = ({
|
|
|
174
114
|
strokeLinecap="round"
|
|
175
115
|
strokeWidth={1.5 * (p.strokeWidth || 1)}
|
|
176
116
|
stroke={p.stroke || "red"}
|
|
177
|
-
d={p.d}
|
|
117
|
+
d={p.d || ""}
|
|
178
118
|
/>
|
|
179
|
-
)
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
)
|
|
183
|
-
}
|
|
119
|
+
)
|
|
120
|
+
)}
|
|
121
|
+
</svg>
|
|
122
|
+
);
|
|
123
|
+
};
|
|
184
124
|
|
|
185
|
-
export default SVGPathComponent
|
|
125
|
+
export default SVGPathComponent;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { AnyCircuitElement, SchematicPort as OriginalSchematicPort, SchematicComponent } from "circuit-json";
|
|
2
|
+
import * as Type from "lib/types";
|
|
3
|
+
import { colorMap } from "lib/utils/colors";
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import SVGPathComponent from "./SVGPathComponent";
|
|
6
|
+
import SchematicText from "./SchematicText";
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
component: {
|
|
10
|
+
source: Type.SimpleBug;
|
|
11
|
+
schematic: SchematicComponent;
|
|
12
|
+
allElements: AnyCircuitElement[];
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type ExtendedCenter = OriginalSchematicPort['center'] & {
|
|
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
|
+
};
|
|
26
|
+
|
|
27
|
+
export const SchematicChip: React.FC<Props> = ({ component: { source, schematic, allElements } }) => {
|
|
28
|
+
const { center, size, rotation, schematic_component_id } = schematic;
|
|
29
|
+
const { manufacturerPartNumber, name } = source;
|
|
30
|
+
const chipWidth = size.width;
|
|
31
|
+
const chipHeight = size.height;
|
|
32
|
+
|
|
33
|
+
const paths: Array<{type?: 'path' | 'circle', strokeWidth: number, stroke: string, fill?: string, d?: string, cx?: number, cy?: number, r?: number}> = [];
|
|
34
|
+
|
|
35
|
+
// Main chip rectangle
|
|
36
|
+
paths.push({
|
|
37
|
+
type: 'path',
|
|
38
|
+
strokeWidth: 0.02,
|
|
39
|
+
stroke: colorMap.schematic.component_outline,
|
|
40
|
+
fill: colorMap.schematic.component_body,
|
|
41
|
+
d: `M ${-chipWidth / 2},${-chipHeight / 2} h ${chipWidth} v ${chipHeight} h ${-chipWidth} Z`,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
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.2;
|
|
51
|
+
const circleRadius = 0.05;
|
|
52
|
+
const labelOffset = 0.1;
|
|
53
|
+
|
|
54
|
+
const pinLabels: Array<{x: number, y: number, text: string, anchor: string}> = [];
|
|
55
|
+
|
|
56
|
+
schematicPorts.forEach((port) => {
|
|
57
|
+
const { side, pinNumber, distanceFromEdge } = port.center;
|
|
58
|
+
let x = 0, y = 0, endX = 0, endY = 0;
|
|
59
|
+
let labelX = 0, labelY = 0;
|
|
60
|
+
let textAnchor = "middle";
|
|
61
|
+
|
|
62
|
+
switch (side) {
|
|
63
|
+
case "left":
|
|
64
|
+
x = -chipWidth / 2;
|
|
65
|
+
y = -chipHeight / 2 + distanceFromEdge;
|
|
66
|
+
endX = x - portLength;
|
|
67
|
+
endY = y;
|
|
68
|
+
labelX = endX;
|
|
69
|
+
labelY = y + labelOffset;
|
|
70
|
+
textAnchor = "end";
|
|
71
|
+
break;
|
|
72
|
+
case "right":
|
|
73
|
+
x = chipWidth / 2;
|
|
74
|
+
y = chipHeight / 2 - distanceFromEdge;
|
|
75
|
+
endX = x + portLength;
|
|
76
|
+
endY = y;
|
|
77
|
+
labelX = endX - labelOffset;
|
|
78
|
+
labelY = y + labelOffset;
|
|
79
|
+
textAnchor = "start";
|
|
80
|
+
break;
|
|
81
|
+
case "bottom":
|
|
82
|
+
x = -chipWidth / 2 + distanceFromEdge;
|
|
83
|
+
y = -chipHeight / 2;
|
|
84
|
+
endX = x;
|
|
85
|
+
endY = y - portLength;
|
|
86
|
+
labelX = x;
|
|
87
|
+
labelY = endY + labelOffset;
|
|
88
|
+
break;
|
|
89
|
+
case "top":
|
|
90
|
+
x = chipWidth / 2 - distanceFromEdge;
|
|
91
|
+
y = chipHeight / 2;
|
|
92
|
+
endX = x;
|
|
93
|
+
endY = y + portLength;
|
|
94
|
+
labelX = x;
|
|
95
|
+
labelY = endY + labelOffset;
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Port line
|
|
100
|
+
paths.push({
|
|
101
|
+
type: 'path',
|
|
102
|
+
strokeWidth: 0.02,
|
|
103
|
+
stroke: colorMap.schematic.component_outline,
|
|
104
|
+
d: `M ${x},${y} L ${endX},${endY}`,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Port circle at the end of the line
|
|
108
|
+
paths.push({
|
|
109
|
+
type: 'circle',
|
|
110
|
+
cx: endX,
|
|
111
|
+
cy: endY,
|
|
112
|
+
r: circleRadius,
|
|
113
|
+
strokeWidth: 0.01,
|
|
114
|
+
stroke: colorMap.schematic.component_outline,
|
|
115
|
+
fill: colorMap.schematic.component_outline,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Add pin label
|
|
119
|
+
if(pinNumber !== undefined) {
|
|
120
|
+
pinLabels.push({
|
|
121
|
+
x: labelX,
|
|
122
|
+
y: labelY,
|
|
123
|
+
text: `${pinNumber}`,
|
|
124
|
+
anchor: textAnchor
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<>
|
|
131
|
+
<SVGPathComponent
|
|
132
|
+
rotation={rotation}
|
|
133
|
+
center={center}
|
|
134
|
+
size={size}
|
|
135
|
+
paths={paths as any}
|
|
136
|
+
/>
|
|
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
|
+
<SchematicText
|
|
154
|
+
schematic_text={{
|
|
155
|
+
anchor: "center",
|
|
156
|
+
position: {
|
|
157
|
+
x: center.x,
|
|
158
|
+
y: center.y - chipHeight / 2 - 0.2,
|
|
159
|
+
},
|
|
160
|
+
schematic_component_id: "SYNTHETIC",
|
|
161
|
+
schematic_text_id: "SYNTHETIC_MPN",
|
|
162
|
+
text: manufacturerPartNumber,
|
|
163
|
+
type: "schematic_text",
|
|
164
|
+
}}
|
|
165
|
+
/>
|
|
166
|
+
<SchematicText
|
|
167
|
+
schematic_text={{
|
|
168
|
+
anchor: "center",
|
|
169
|
+
position: {
|
|
170
|
+
x: center.x,
|
|
171
|
+
y: center.y + chipHeight / 2 + 0.2,
|
|
172
|
+
},
|
|
173
|
+
schematic_component_id: "SYNTHETIC",
|
|
174
|
+
schematic_text_id: "SYNTHETIC_NAME",
|
|
175
|
+
text: name,
|
|
176
|
+
type: "schematic_text",
|
|
177
|
+
}}
|
|
178
|
+
/>
|
|
179
|
+
</>
|
|
180
|
+
);
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export default SchematicChip;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { AnyCircuitElement, SchematicComponent as SchematicComponentType } from "circuit-json"
|
|
2
2
|
import * as Component from "./"
|
|
3
3
|
|
|
4
4
|
interface Props {
|
|
5
5
|
component: {
|
|
6
|
-
source:
|
|
7
|
-
schematic:
|
|
6
|
+
source: any
|
|
7
|
+
schematic: SchematicComponentType
|
|
8
8
|
schematic_children: any[]
|
|
9
|
+
allElements: AnyCircuitElement[]
|
|
9
10
|
}
|
|
10
11
|
}
|
|
11
12
|
|
|
@@ -14,30 +15,23 @@ interface Props {
|
|
|
14
15
|
* generating schematic lines directly
|
|
15
16
|
*/
|
|
16
17
|
export const SchematicComponent = ({ component }: Props) => {
|
|
17
|
-
const { source, schematic } = component
|
|
18
|
+
const { source, schematic, allElements } = component
|
|
18
19
|
if (!source.ftype) return null
|
|
19
20
|
|
|
20
21
|
switch (source.ftype) {
|
|
21
|
-
case "simple_resistor":
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
case "
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return <Component.
|
|
29
|
-
}
|
|
30
|
-
case "
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return <Component.SimpleInductor component={{ source, schematic }} />
|
|
35
|
-
}
|
|
36
|
-
case "simple_bug": {
|
|
37
|
-
return <Component.SchematicBug component={{ source, schematic }} />
|
|
38
|
-
}
|
|
39
|
-
case "simple_diode": {
|
|
40
|
-
return <Component.SimpleDiode component={{ source, schematic }} />
|
|
22
|
+
case "simple_resistor":
|
|
23
|
+
case "simple_capacitor":
|
|
24
|
+
case "simple_power_source":
|
|
25
|
+
case "simple_ground":
|
|
26
|
+
case "simple_inductor":
|
|
27
|
+
case "simple_diode":
|
|
28
|
+
{
|
|
29
|
+
return <Component.SchematicComponentFromSymbol component={{ source, schematic }} />
|
|
30
|
+
}
|
|
31
|
+
case "simple_chip":
|
|
32
|
+
case "simple_bug":
|
|
33
|
+
{
|
|
34
|
+
return <Component.SchematicChip component={{ source, schematic, allElements }} />
|
|
41
35
|
}
|
|
42
36
|
default: {
|
|
43
37
|
return <div>unknown ftype: {component.source.ftype}</div>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { SchematicComponent, SourceSimpleResistor } from "circuit-json"
|
|
2
|
+
import { colorMap } from "lib/utils/colors"
|
|
3
|
+
import { symbols } from "schematic-symbols"
|
|
4
|
+
import SVGPathComponent from "./SVGPathComponent"
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
component: {
|
|
8
|
+
source: SourceSimpleResistor
|
|
9
|
+
schematic: SchematicComponent
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const SchematicComponentFromSymbol = ({ component: { source, schematic } }: Props) => {
|
|
14
|
+
const { center, rotation } = schematic
|
|
15
|
+
// Get the resistor symbol paths
|
|
16
|
+
const symbol = symbols[schematic.symbol_name]
|
|
17
|
+
const paths = symbol.primitives
|
|
18
|
+
.filter((p: any) => p.type === "path")
|
|
19
|
+
.map((p: any) => ({
|
|
20
|
+
stroke: colorMap.schematic.component_outline,
|
|
21
|
+
strokeWidth: 0.02,
|
|
22
|
+
d: p.points.reduce(
|
|
23
|
+
(acc: string, point: { x: number; y: number }, index: number) => {
|
|
24
|
+
const command = index === 0 ? "M" : "L"
|
|
25
|
+
return `${acc} ${command} ${point.x} ${point.y}`
|
|
26
|
+
},
|
|
27
|
+
"",
|
|
28
|
+
),
|
|
29
|
+
}))
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<SVGPathComponent
|
|
33
|
+
rotation={rotation}
|
|
34
|
+
center={center}
|
|
35
|
+
size={{
|
|
36
|
+
width: symbol?.size.width,
|
|
37
|
+
height: symbol?.size.height,
|
|
38
|
+
}}
|
|
39
|
+
paths={paths}
|
|
40
|
+
/>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default SchematicComponentFromSymbol
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { AnyCircuitElement } from "circuit-json"
|
|
2
2
|
import { collectElementRefs } from "lib/utils/collect-element-refs"
|
|
3
|
-
import SchematicBox from "./SchematicBox"
|
|
4
3
|
import SchematicComponent from "./SchematicComponent"
|
|
5
|
-
import SchematicLine from "./SchematicLine"
|
|
6
4
|
import { SchematicNetLabel } from "./SchematicNetLabel"
|
|
7
|
-
import SchematicPath from "./SchematicPath"
|
|
8
|
-
import SchematicPort from "./SchematicPort"
|
|
9
5
|
import SchematicText from "./SchematicText"
|
|
10
6
|
import SchematicTrace from "./SchematicTrace"
|
|
11
7
|
|
|
@@ -35,30 +31,6 @@ export const SchematicElement = ({
|
|
|
35
31
|
)
|
|
36
32
|
}
|
|
37
33
|
|
|
38
|
-
if (element.type === "schematic_port") {
|
|
39
|
-
return (
|
|
40
|
-
<SchematicPort port={collectElementRefs(element, allElements) as any} />
|
|
41
|
-
)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (element.type === "schematic_box") {
|
|
45
|
-
return (
|
|
46
|
-
<SchematicBox box={collectElementRefs(element, allElements) as any} />
|
|
47
|
-
)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (element.type === "schematic_line") {
|
|
51
|
-
return (
|
|
52
|
-
<SchematicLine line={collectElementRefs(element, allElements) as any} />
|
|
53
|
-
)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (element.type === "schematic_path") {
|
|
57
|
-
return (
|
|
58
|
-
<SchematicPath path={collectElementRefs(element, allElements) as any} />
|
|
59
|
-
)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
34
|
if (element.type === "schematic_text") {
|
|
63
35
|
return <SchematicText schematic_text={element} />
|
|
64
36
|
}
|
|
@@ -4,6 +4,7 @@ import Path from "svg-path-generator"
|
|
|
4
4
|
import getSVGPathBounds from "lib/utils/get-svg-path-bounds"
|
|
5
5
|
import RenderError from "./RenderError"
|
|
6
6
|
import SVGPathComponent2 from "./SVGPathComponent2"
|
|
7
|
+
import { colorMap } from "lib/utils/colors"
|
|
7
8
|
|
|
8
9
|
interface Props {
|
|
9
10
|
trace: {
|
|
@@ -33,14 +34,14 @@ export const SchematicTrace = ({ trace: { source, schematic } }: Props) => {
|
|
|
33
34
|
y: pathBounds.minY + pathBounds.height / 2,
|
|
34
35
|
}
|
|
35
36
|
return (
|
|
36
|
-
<
|
|
37
|
+
<SVGPathComponent
|
|
37
38
|
rotation={0}
|
|
38
39
|
center={center}
|
|
39
40
|
size={pathBounds}
|
|
40
41
|
paths={[
|
|
41
42
|
{
|
|
42
|
-
stroke:
|
|
43
|
-
strokeWidth: 0.
|
|
43
|
+
stroke:colorMap.schematic.wire,
|
|
44
|
+
strokeWidth: 0.01,
|
|
44
45
|
d,
|
|
45
46
|
},
|
|
46
47
|
]}
|
|
@@ -1,17 +1,10 @@
|
|
|
1
|
-
export * from "./
|
|
2
|
-
export * from "./
|
|
3
|
-
export * from "./
|
|
4
|
-
export * from "./SVGPathComponent"
|
|
5
|
-
export * from "./ProjectComponent"
|
|
1
|
+
export * from "./ContextProviders"
|
|
2
|
+
export * from "./RenderError"
|
|
3
|
+
export * from "./SchematicChip"
|
|
6
4
|
export * from "./SchematicComponent"
|
|
7
|
-
export * from "./
|
|
5
|
+
export * from "./SchematicComponentFromSymbol"
|
|
6
|
+
export * from "./SchematicGroup"
|
|
8
7
|
export * from "./SchematicText"
|
|
9
|
-
export * from "./ProjectComponent"
|
|
10
8
|
export * from "./SchematicTrace"
|
|
11
|
-
export * from "./
|
|
12
|
-
|
|
13
|
-
export * from "./SimpleGround"
|
|
14
|
-
export * from "./SimpleInductor"
|
|
15
|
-
export * from "./RenderError"
|
|
16
|
-
export * from "./SimpleDiode"
|
|
17
|
-
export * from "./ContextProviders"
|
|
9
|
+
export * from "./SVGPathComponent"
|
|
10
|
+
|