@tscircuit/core 0.0.72 → 0.0.74
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 +0 -4
- package/package.json +2 -4
- package/index.ts +0 -1
- package/lib/Project.ts +0 -131
- package/lib/components/base-components/NormalComponent.ts +0 -419
- package/lib/components/base-components/PrimitiveComponent.ts +0 -478
- package/lib/components/base-components/Renderable.ts +0 -126
- package/lib/components/index.ts +0 -25
- package/lib/components/normal-components/Board.ts +0 -49
- package/lib/components/normal-components/Capacitor.ts +0 -70
- package/lib/components/normal-components/Chip.ts +0 -98
- package/lib/components/normal-components/Diode.ts +0 -27
- package/lib/components/normal-components/Jumper.ts +0 -101
- package/lib/components/normal-components/Led.ts +0 -27
- package/lib/components/normal-components/Resistor.ts +0 -59
- package/lib/components/primitive-components/Constraint.ts +0 -91
- package/lib/components/primitive-components/FabricationNotePath.ts +0 -50
- package/lib/components/primitive-components/FabricationNoteText.ts +0 -26
- package/lib/components/primitive-components/Footprint.ts +0 -239
- package/lib/components/primitive-components/Group.ts +0 -42
- package/lib/components/primitive-components/Hole.ts +0 -65
- package/lib/components/primitive-components/Keepout.ts +0 -58
- package/lib/components/primitive-components/Net.ts +0 -171
- package/lib/components/primitive-components/PlatedHole.ts +0 -116
- package/lib/components/primitive-components/Port.ts +0 -236
- package/lib/components/primitive-components/SilkscreenPath.ts +0 -48
- package/lib/components/primitive-components/SilkscreenText.ts +0 -25
- package/lib/components/primitive-components/SmtPad.ts +0 -162
- package/lib/components/primitive-components/Trace.ts +0 -635
- package/lib/components/primitive-components/TraceHint.ts +0 -71
- package/lib/fiber/catalogue.ts +0 -22
- package/lib/fiber/create-instance-from-react-element.ts +0 -179
- package/lib/fiber/intrinsic-jsx.ts +0 -48
- package/lib/index.ts +0 -5
- package/lib/register-catalogue.ts +0 -12
- package/lib/soup/underscorifyPinStyles.ts +0 -25
- package/lib/soup/underscorifyPortArrangement.ts +0 -51
- package/lib/utils/autorouting/SimpleRouteJson.ts +0 -48
- package/lib/utils/autorouting/computeObstacleBounds.ts +0 -10
- package/lib/utils/autorouting/findPossibleTraceLayerCombinations.ts +0 -102
- package/lib/utils/autorouting/mergeRoutes.ts +0 -71
- package/lib/utils/components/createNetsFromProps.ts +0 -15
- package/lib/utils/constants.ts +0 -35
- package/lib/utils/createComponentsFromSoup.ts +0 -79
- package/lib/utils/extend-aliases.ts +0 -12
- package/lib/utils/get-bounds-of-pcb-components.ts +0 -41
- package/lib/utils/get-relative-direction.ts +0 -14
- package/lib/utils/getClosest.ts +0 -35
- package/lib/utils/getPortFromHints.ts +0 -10
- package/lib/utils/pairs.ts +0 -10
- package/lib/utils/projectPointInDirection.ts +0 -18
- package/lib/utils/range.ts +0 -8
- package/lib/utils/schematic/getAllDimensionsForSchematicBox.ts +0 -330
- package/lib/utils/schematic/getSizeOfSidesFromPortArrangement.ts +0 -47
- package/lib/utils/selector-matching/index.ts +0 -2
- package/lib/utils/selector-matching/is-matching-path-selector.ts +0 -32
- package/lib/utils/selector-matching/is-matching-selector.ts +0 -64
- package/lib/utils/try-now.ts +0 -7
package/README.md
CHANGED
|
@@ -2,10 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
[tscircuit](https://github.com/tscircuit/tscircuit) · [Development Guide](./docs/DEVELOPMENT.md)
|
|
4
4
|
|
|
5
|
-
> [!WARNING]
|
|
6
|
-
> You should use [@tscircuit/builder](https://github.com/tscircuit/builder) instead, this package is
|
|
7
|
-
> going to be in alpha for a while.
|
|
8
|
-
|
|
9
5
|
A rewrite of [tscircuit builder](https://github.com/tscircuit/builder) with a ThreeJS/react-three-like API and architecture.
|
|
10
6
|
|
|
11
7
|
## Usage
|
package/package.json
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tscircuit/core",
|
|
3
|
-
"module": "index.ts",
|
|
4
3
|
"type": "module",
|
|
5
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.74",
|
|
6
5
|
"types": "dist/index.d.ts",
|
|
7
6
|
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
8
|
"files": [
|
|
9
|
-
"index.ts",
|
|
10
|
-
"lib",
|
|
11
9
|
"dist"
|
|
12
10
|
],
|
|
13
11
|
"scripts": {
|
package/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./lib/index"
|
package/lib/Project.ts
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import type { AnySoupElement } from "@tscircuit/soup"
|
|
2
|
-
import type { PrimitiveComponent } from "./components/base-components/PrimitiveComponent"
|
|
3
|
-
import type { SoupUtilObjects } from "@tscircuit/soup-util"
|
|
4
|
-
import { su } from "@tscircuit/soup-util"
|
|
5
|
-
import { isValidElement, type ReactElement } from "react"
|
|
6
|
-
import { createInstanceFromReactElement } from "./fiber/create-instance-from-react-element"
|
|
7
|
-
import { identity, type Matrix } from "transformation-matrix"
|
|
8
|
-
|
|
9
|
-
export class Circuit {
|
|
10
|
-
firstChild: PrimitiveComponent | null = null
|
|
11
|
-
children: PrimitiveComponent[]
|
|
12
|
-
db: SoupUtilObjects
|
|
13
|
-
root: Circuit | null = null
|
|
14
|
-
isRoot = true
|
|
15
|
-
|
|
16
|
-
_hasRenderedAtleastOnce = false
|
|
17
|
-
|
|
18
|
-
constructor() {
|
|
19
|
-
this.children = []
|
|
20
|
-
this.db = su([])
|
|
21
|
-
// TODO rename to rootCircuit
|
|
22
|
-
this.root = this
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
add(componentOrElm: PrimitiveComponent | ReactElement) {
|
|
26
|
-
let component: PrimitiveComponent
|
|
27
|
-
if (isValidElement(componentOrElm)) {
|
|
28
|
-
// TODO store subtree
|
|
29
|
-
component = createInstanceFromReactElement(componentOrElm)
|
|
30
|
-
} else {
|
|
31
|
-
component = componentOrElm as PrimitiveComponent
|
|
32
|
-
}
|
|
33
|
-
this.children.push(component)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
_guessRootComponent() {
|
|
37
|
-
if (this.firstChild) return
|
|
38
|
-
if (this.children.length === 1) {
|
|
39
|
-
this.firstChild = this.children[0]
|
|
40
|
-
return
|
|
41
|
-
}
|
|
42
|
-
if (this.children.length === 0) {
|
|
43
|
-
throw new Error(
|
|
44
|
-
"Not able to guess root component: Project has no children (use project.add(...))",
|
|
45
|
-
)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (this.children.length > 0) {
|
|
49
|
-
const board =
|
|
50
|
-
this.children.find((c) => c.componentName === "Board") ?? null
|
|
51
|
-
|
|
52
|
-
if (board) {
|
|
53
|
-
this.firstChild = board
|
|
54
|
-
return
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
throw new Error(
|
|
58
|
-
"Not able to guess root component: Project has multiple children and no board",
|
|
59
|
-
)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
render() {
|
|
63
|
-
if (!this.firstChild) {
|
|
64
|
-
this._guessRootComponent()
|
|
65
|
-
}
|
|
66
|
-
const { firstChild, db } = this
|
|
67
|
-
|
|
68
|
-
if (!firstChild) throw new Error("Project has no root component")
|
|
69
|
-
firstChild.parent = this as any
|
|
70
|
-
firstChild.runRenderCycle()
|
|
71
|
-
this._hasRenderedAtleastOnce = true
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
getSoup(): AnySoupElement[] {
|
|
75
|
-
if (!this._hasRenderedAtleastOnce) this.render()
|
|
76
|
-
return this.db.toArray()
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
getCircuitJson(): AnySoupElement[] {
|
|
80
|
-
return this.getSoup()
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async getSvg(options: { view: "pcb"; layer?: string }): Promise<string> {
|
|
84
|
-
const circuitToSvg = await import("circuit-to-svg").catch((e) => {
|
|
85
|
-
throw new Error(
|
|
86
|
-
`To use project.getSvg, you must install the "circuit-to-svg" package.\n\n"${e.message}"`,
|
|
87
|
-
)
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
return circuitToSvg.circuitJsonToPcbSvg(this.getCircuitJson())
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
async preview(
|
|
94
|
-
previewNameOrOpts:
|
|
95
|
-
| string
|
|
96
|
-
| {
|
|
97
|
-
previewName: string
|
|
98
|
-
tscircuitApiKey?: string
|
|
99
|
-
},
|
|
100
|
-
) {
|
|
101
|
-
const previewOpts =
|
|
102
|
-
typeof previewNameOrOpts === "object"
|
|
103
|
-
? previewNameOrOpts
|
|
104
|
-
: { previewName: previewNameOrOpts }
|
|
105
|
-
throw new Error("project.preview is not yet implemented")
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
computeSchematicGlobalTransform(): Matrix {
|
|
109
|
-
return identity()
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
_computePcbGlobalTransformBeforeLayout(): Matrix {
|
|
113
|
-
return identity()
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
selectAll(selector: string): PrimitiveComponent[] {
|
|
117
|
-
return this.firstChild?.selectAll(selector) ?? []
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
selectOne(
|
|
121
|
-
selector: string,
|
|
122
|
-
opts?: { type?: "component" | "port" },
|
|
123
|
-
): PrimitiveComponent | null {
|
|
124
|
-
return this.firstChild?.selectOne(selector, opts) ?? null
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* @deprecated
|
|
130
|
-
*/
|
|
131
|
-
export const Project = Circuit
|
|
@@ -1,419 +0,0 @@
|
|
|
1
|
-
import { Footprint } from "../primitive-components/Footprint"
|
|
2
|
-
import { ZodType, z } from "zod"
|
|
3
|
-
import { PrimitiveComponent } from "./PrimitiveComponent"
|
|
4
|
-
import { Port } from "../primitive-components/Port"
|
|
5
|
-
import { symbols, type BaseSymbolName, type SchSymbol } from "schematic-symbols"
|
|
6
|
-
import { fp } from "footprinter"
|
|
7
|
-
import {
|
|
8
|
-
isValidElement as isReactElement,
|
|
9
|
-
isValidElement,
|
|
10
|
-
type ReactElement,
|
|
11
|
-
type ReactNode,
|
|
12
|
-
} from "react"
|
|
13
|
-
import {
|
|
14
|
-
createInstanceFromReactElement,
|
|
15
|
-
type ReactSubtree,
|
|
16
|
-
} from "lib/fiber/create-instance-from-react-element"
|
|
17
|
-
import { getPortFromHints } from "lib/utils/getPortFromHints"
|
|
18
|
-
import { createComponentsFromSoup } from "lib/utils/createComponentsFromSoup"
|
|
19
|
-
import { Net } from "../primitive-components/Net"
|
|
20
|
-
import { createNetsFromProps } from "lib/utils/components/createNetsFromProps"
|
|
21
|
-
import { getBoundsOfPcbComponents } from "lib/utils/get-bounds-of-pcb-components"
|
|
22
|
-
|
|
23
|
-
export type PortMap<T extends string> = {
|
|
24
|
-
[K in T]: Port
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* A NormalComponent is the base class for most components that a user will
|
|
29
|
-
* interact with. It has the ability to set a footprint and discover ports.
|
|
30
|
-
*
|
|
31
|
-
* When you're extending a NormalComponent, you almost always want to override
|
|
32
|
-
* initPorts() to create ports for the component.
|
|
33
|
-
*
|
|
34
|
-
* class Led extends NormalComponent<typeof resistorProps> {
|
|
35
|
-
* pin1: Port = this.portMap.pin1
|
|
36
|
-
* pin2: Port = this.portMap.pin2
|
|
37
|
-
*
|
|
38
|
-
* initPorts() {
|
|
39
|
-
* this.add(new Port({ pinNumber: 1, aliases: ["anode", "pos"] }))
|
|
40
|
-
* this.add(new Port({ pinNumber: 2, aliases: ["cathode", "neg"] }))
|
|
41
|
-
* }
|
|
42
|
-
* }
|
|
43
|
-
*/
|
|
44
|
-
export class NormalComponent<
|
|
45
|
-
ZodProps extends ZodType = any,
|
|
46
|
-
PortNames extends string = never,
|
|
47
|
-
> extends PrimitiveComponent<ZodProps> {
|
|
48
|
-
reactSubtrees: Array<ReactSubtree> = []
|
|
49
|
-
|
|
50
|
-
isPrimitiveContainer = true
|
|
51
|
-
|
|
52
|
-
constructor(props: z.input<ZodProps>) {
|
|
53
|
-
super(props)
|
|
54
|
-
this._addChildrenFromStringFootprint()
|
|
55
|
-
this.initPorts()
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Override this method for better control over the auto-discovery of ports.
|
|
60
|
-
*
|
|
61
|
-
* If you override this method just do something like:
|
|
62
|
-
* initPorts() {
|
|
63
|
-
* this.add(new Port({ pinNumber: 1, aliases: ["anode", "pos"] }))
|
|
64
|
-
* this.add(new Port({ pinNumber: 2, aliases: ["cathode", "neg"] }))
|
|
65
|
-
* }
|
|
66
|
-
*
|
|
67
|
-
* By default, we'll pull the ports from the first place we find them:
|
|
68
|
-
* 1. `config.schematicSymbolName`
|
|
69
|
-
* 2. `props.footprint`
|
|
70
|
-
*
|
|
71
|
-
*/
|
|
72
|
-
initPorts() {
|
|
73
|
-
const { config } = this
|
|
74
|
-
const portsToCreate: Port[] = []
|
|
75
|
-
if (config.schematicSymbolName) {
|
|
76
|
-
const sym = symbols[
|
|
77
|
-
`${config.schematicSymbolName}_horz` as keyof typeof symbols
|
|
78
|
-
] as SchSymbol | undefined
|
|
79
|
-
if (!sym) return
|
|
80
|
-
|
|
81
|
-
for (const symPort of sym.ports) {
|
|
82
|
-
const port = getPortFromHints(symPort.labels)
|
|
83
|
-
|
|
84
|
-
if (port) {
|
|
85
|
-
port.schematicSymbolPortDef = symPort
|
|
86
|
-
portsToCreate.push(port)
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
this.addAll(portsToCreate)
|
|
91
|
-
return
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const portsFromFootprint = this.getPortsFromFootprint()
|
|
95
|
-
portsToCreate.push(...portsFromFootprint)
|
|
96
|
-
|
|
97
|
-
const pinLabels: Record<string, string> | undefined =
|
|
98
|
-
this._parsedProps.pinLabels
|
|
99
|
-
if (pinLabels) {
|
|
100
|
-
for (let [pinNumber, label] of Object.entries(pinLabels)) {
|
|
101
|
-
pinNumber = pinNumber.replace("pin", "")
|
|
102
|
-
const existingPort = portsToCreate.find(
|
|
103
|
-
(p) => p._parsedProps.pinNumber === Number(pinNumber),
|
|
104
|
-
)
|
|
105
|
-
if (!existingPort) {
|
|
106
|
-
throw new Error(
|
|
107
|
-
`Could not find port for pin number ${pinNumber} in chip ${this.getString()}`,
|
|
108
|
-
)
|
|
109
|
-
}
|
|
110
|
-
existingPort.externallyAddedAliases.push(label)
|
|
111
|
-
existingPort.props.name = label
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
this.addAll(portsToCreate)
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
_addChildrenFromStringFootprint() {
|
|
119
|
-
const { footprint } = this.props
|
|
120
|
-
if (!footprint) return
|
|
121
|
-
if (typeof footprint === "string") {
|
|
122
|
-
const fpSoup = fp.string(footprint).soup()
|
|
123
|
-
// Adjust the layer of the footprint to match the layer of the component
|
|
124
|
-
if (this.props.layer) {
|
|
125
|
-
for (const elm of fpSoup) {
|
|
126
|
-
if ("layer" in elm) {
|
|
127
|
-
elm.layer = this.props.layer
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
const fpComponents = createComponentsFromSoup(fpSoup)
|
|
132
|
-
this.addAll(fpComponents)
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
get portMap(): PortMap<PortNames> {
|
|
137
|
-
return new Proxy(
|
|
138
|
-
{},
|
|
139
|
-
{
|
|
140
|
-
get: (target, prop): Port => {
|
|
141
|
-
const port = this.children.find(
|
|
142
|
-
(c) =>
|
|
143
|
-
c.componentName === "Port" &&
|
|
144
|
-
(c as Port).isMatchingNameOrAlias(prop as string),
|
|
145
|
-
)
|
|
146
|
-
if (!port) {
|
|
147
|
-
throw new Error(
|
|
148
|
-
`There was an issue finding the port "${prop.toString()}" inside of a ${this.componentName} component with name: "${this.props.name}". This is a bug in @tscircuit/core`,
|
|
149
|
-
)
|
|
150
|
-
}
|
|
151
|
-
return port as Port
|
|
152
|
-
},
|
|
153
|
-
},
|
|
154
|
-
) as any
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
getInstanceForReactElement(element: ReactElement): NormalComponent | null {
|
|
158
|
-
for (const subtree of this.reactSubtrees) {
|
|
159
|
-
if (subtree.element === element) return subtree.component
|
|
160
|
-
}
|
|
161
|
-
return null
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
doInitialSourceRender() {
|
|
165
|
-
const ftype = this.config.sourceFtype
|
|
166
|
-
if (!ftype) return
|
|
167
|
-
const { db } = this.root!
|
|
168
|
-
const { _parsedProps: props } = this
|
|
169
|
-
const source_component = db.source_component.insert({
|
|
170
|
-
ftype,
|
|
171
|
-
name: props.name,
|
|
172
|
-
manufacturer_part_number: props.manufacturerPartNumber ?? props.mfn,
|
|
173
|
-
supplier_part_numbers: props.supplierPartNumbers,
|
|
174
|
-
})
|
|
175
|
-
this.source_component_id = source_component.source_component_id
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Render the schematic component for this NormalComponent using the
|
|
180
|
-
* config.schematicSymbolName if it exists.
|
|
181
|
-
*
|
|
182
|
-
* You can override this method to do more complicated things.
|
|
183
|
-
*/
|
|
184
|
-
doInitialSchematicComponentRender() {
|
|
185
|
-
const { db } = this.root!
|
|
186
|
-
const { schematicSymbolName } = this.config
|
|
187
|
-
if (!schematicSymbolName) return
|
|
188
|
-
// TODO switch between horizontal and vertical based on schRotation
|
|
189
|
-
const symbol_name = `${this.config.schematicSymbolName}_horz`
|
|
190
|
-
|
|
191
|
-
const symbol = (symbols as any)[symbol_name] as SchSymbol | undefined
|
|
192
|
-
|
|
193
|
-
if (!symbol) {
|
|
194
|
-
throw new Error(`Could not find schematic-symbol "${symbol_name}"`)
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const schematic_component = db.schematic_component.insert({
|
|
198
|
-
center: { x: this.props.schX ?? 0, y: this.props.schY ?? 0 },
|
|
199
|
-
rotation: this.props.schRotation ?? 0,
|
|
200
|
-
size: symbol.size,
|
|
201
|
-
source_component_id: this.source_component_id!,
|
|
202
|
-
|
|
203
|
-
// @ts-ignore
|
|
204
|
-
symbol_name,
|
|
205
|
-
})
|
|
206
|
-
this.schematic_component_id = schematic_component.schematic_component_id
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
doInitialPcbComponentRender() {
|
|
210
|
-
const { db } = this.root!
|
|
211
|
-
const { _parsedProps: props } = this
|
|
212
|
-
const pcb_component = db.pcb_component.insert({
|
|
213
|
-
center: this._getGlobalPcbPositionBeforeLayout(),
|
|
214
|
-
// width/height are computed in the PcbComponentSizeCalculation phase
|
|
215
|
-
width: 0,
|
|
216
|
-
height: 0,
|
|
217
|
-
layer: props.layer ?? "top",
|
|
218
|
-
rotation: props.pcbRotation ?? 0,
|
|
219
|
-
source_component_id: this.source_component_id!,
|
|
220
|
-
})
|
|
221
|
-
this.pcb_component_id = pcb_component.pcb_component_id
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* At this stage, the smtpads/pcb primitives are placed, so we can compute
|
|
226
|
-
* the width/height of the component
|
|
227
|
-
*/
|
|
228
|
-
doInitialPcbComponentSizeCalculation(): void {
|
|
229
|
-
if (!this.pcb_component_id) return
|
|
230
|
-
const { db } = this.root!
|
|
231
|
-
const { _parsedProps: props } = this
|
|
232
|
-
|
|
233
|
-
const bounds = getBoundsOfPcbComponents(this.children)
|
|
234
|
-
|
|
235
|
-
db.pcb_component.update(this.pcb_component_id!, {
|
|
236
|
-
width: bounds.width,
|
|
237
|
-
height: bounds.height,
|
|
238
|
-
})
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
_renderReactSubtree(element: ReactElement): ReactSubtree {
|
|
242
|
-
return {
|
|
243
|
-
element,
|
|
244
|
-
component: createInstanceFromReactElement(element),
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
doInitialInitializePortsFromChildren(): void {
|
|
249
|
-
this.initPorts()
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
doInitialReactSubtreesRender(): void {
|
|
253
|
-
if (isReactElement(this.props.footprint)) {
|
|
254
|
-
if (this.reactSubtrees.some((rs) => rs.element === this.props.footprint))
|
|
255
|
-
return
|
|
256
|
-
const subtree = this._renderReactSubtree(this.props.footprint)
|
|
257
|
-
this.reactSubtrees.push(subtree)
|
|
258
|
-
this.add(subtree.component)
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
_hasExistingPortExactly(port1: Port): boolean {
|
|
263
|
-
const existingPorts = this.children.filter(
|
|
264
|
-
(c) => c.componentName === "Port",
|
|
265
|
-
) as Port[]
|
|
266
|
-
return existingPorts.some((port2) => {
|
|
267
|
-
const aliases1 = port1.getNameAndAliases()
|
|
268
|
-
const aliases2 = port2.getNameAndAliases()
|
|
269
|
-
return (
|
|
270
|
-
aliases1.length === aliases2.length &&
|
|
271
|
-
aliases1.every((alias) => aliases2.includes(alias))
|
|
272
|
-
)
|
|
273
|
-
})
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
add(componentOrElm: PrimitiveComponent | ReactElement) {
|
|
277
|
-
let component: PrimitiveComponent
|
|
278
|
-
if (isReactElement(componentOrElm)) {
|
|
279
|
-
const subtree = this._renderReactSubtree(componentOrElm)
|
|
280
|
-
this.reactSubtrees.push(subtree)
|
|
281
|
-
component = subtree.component
|
|
282
|
-
} else {
|
|
283
|
-
component = componentOrElm as PrimitiveComponent
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
if (component.componentName === "Port") {
|
|
287
|
-
if (this._hasExistingPortExactly(component as Port)) return
|
|
288
|
-
// Check if this port is already contained in the children, skip if it's
|
|
289
|
-
// already defined
|
|
290
|
-
const existingPorts = this.children.filter(
|
|
291
|
-
(c) => c.componentName === "Port",
|
|
292
|
-
) as Port[]
|
|
293
|
-
const conflictingPort = existingPorts.find((p) =>
|
|
294
|
-
p.isMatchingAnyOf(component.getNameAndAliases()),
|
|
295
|
-
)
|
|
296
|
-
if (conflictingPort) {
|
|
297
|
-
throw new Error(
|
|
298
|
-
`Conflicting ports added. Port 1: ${conflictingPort}, Port 2: ${component}`,
|
|
299
|
-
)
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
super.add(component)
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
getPortsFromFootprint(): Port[] {
|
|
307
|
-
let { footprint } = this.props
|
|
308
|
-
|
|
309
|
-
if (!footprint || isValidElement(footprint)) {
|
|
310
|
-
footprint = this.children.find((c) => c.componentName === "Footprint")
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
if (typeof footprint === "string") {
|
|
314
|
-
const fpSoup = fp.string(footprint).soup()
|
|
315
|
-
|
|
316
|
-
const newPorts: Port[] = []
|
|
317
|
-
for (const elm of fpSoup) {
|
|
318
|
-
if ("port_hints" in elm && elm.port_hints) {
|
|
319
|
-
const newPort = getPortFromHints(elm.port_hints)
|
|
320
|
-
if (!newPort) continue
|
|
321
|
-
newPorts.push(newPort)
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
return newPorts
|
|
326
|
-
}
|
|
327
|
-
if (
|
|
328
|
-
!isValidElement(footprint) &&
|
|
329
|
-
footprint &&
|
|
330
|
-
footprint.componentName === "Footprint"
|
|
331
|
-
) {
|
|
332
|
-
const fp = footprint as Footprint
|
|
333
|
-
|
|
334
|
-
const newPorts: Port[] = []
|
|
335
|
-
for (const fpChild of fp.children) {
|
|
336
|
-
const newPort = getPortFromHints(fpChild.props.portHints ?? [])
|
|
337
|
-
if (!newPort) continue
|
|
338
|
-
newPorts.push(newPort)
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
if (newPorts.length === 0) {
|
|
342
|
-
throw new Error(
|
|
343
|
-
`No ports found in chip ${this} (define a schPortArrangement, a footprint or add portHints to elements of the footprint)`,
|
|
344
|
-
)
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
return newPorts
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
// Explore children for possible smtpads etc.
|
|
351
|
-
const newPorts: Port[] = []
|
|
352
|
-
if (!footprint) {
|
|
353
|
-
for (const child of this.children) {
|
|
354
|
-
if (child.props.portHints && child.isPcbPrimitive) {
|
|
355
|
-
const port = getPortFromHints(child.props.portHints)
|
|
356
|
-
if (port) newPorts.push(port)
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
return newPorts
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
getPortsFromSchematicSymbol(): Port[] {
|
|
364
|
-
const { config } = this
|
|
365
|
-
if (!config.schematicSymbolName) return []
|
|
366
|
-
const symbol: SchSymbol = (symbols as any)[config.schematicSymbolName]
|
|
367
|
-
if (!symbol) return []
|
|
368
|
-
const newPorts: Port[] = []
|
|
369
|
-
for (const symbolPort of symbol.ports) {
|
|
370
|
-
const port = getPortFromHints(symbolPort.labels)
|
|
371
|
-
if (port) {
|
|
372
|
-
port.schematicSymbolPortDef = symbolPort
|
|
373
|
-
newPorts.push(port)
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
return newPorts
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
_createNetsFromProps(propsWithConnections: (string | undefined | null)[]) {
|
|
380
|
-
createNetsFromProps(this, propsWithConnections)
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
/**
|
|
384
|
-
* Use data from our props to create ports for this component.
|
|
385
|
-
*
|
|
386
|
-
* Generally, this is done by looking at the schematic and the footprint,
|
|
387
|
-
* reading the pins, making sure there aren't duplicates.
|
|
388
|
-
*
|
|
389
|
-
* Can probably be removed in favor of initPorts()
|
|
390
|
-
*
|
|
391
|
-
*/
|
|
392
|
-
doInitialPortDiscovery(): void {
|
|
393
|
-
const newPorts = [
|
|
394
|
-
...this.getPortsFromFootprint(),
|
|
395
|
-
...this.getPortsFromSchematicSymbol(),
|
|
396
|
-
]
|
|
397
|
-
|
|
398
|
-
const existingPorts = this.children.filter(
|
|
399
|
-
(c) => c.componentName === "Port",
|
|
400
|
-
) as Port[]
|
|
401
|
-
|
|
402
|
-
for (const newPort of newPorts) {
|
|
403
|
-
const existingPort = existingPorts.find((p) =>
|
|
404
|
-
p.isMatchingAnyOf(newPort.getNameAndAliases()),
|
|
405
|
-
)
|
|
406
|
-
if (existingPort) {
|
|
407
|
-
if (
|
|
408
|
-
!existingPort.schematicSymbolPortDef &&
|
|
409
|
-
newPort.schematicSymbolPortDef
|
|
410
|
-
) {
|
|
411
|
-
existingPort.schematicSymbolPortDef = newPort.schematicSymbolPortDef
|
|
412
|
-
}
|
|
413
|
-
continue
|
|
414
|
-
}
|
|
415
|
-
existingPorts.push(newPort)
|
|
416
|
-
this.add(newPort)
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
}
|