@tscircuit/core 0.0.26 → 0.0.28

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/dist/index.d.ts CHANGED
@@ -119,7 +119,10 @@ declare abstract class PrimitiveComponent<ZodProps extends ZodType = any> extend
119
119
  computePcbPropsTransform(): Matrix;
120
120
  /**
121
121
  * Compute a transformation matrix combining all parent transforms for PCB
122
- * components
122
+ * components, including this component's translation and rotation.
123
+ *
124
+ * This is used to compute this component's position as well as all children
125
+ * components positions
123
126
  */
124
127
  computePcbGlobalTransform(): Matrix;
125
128
  /**
@@ -133,6 +136,14 @@ declare abstract class PrimitiveComponent<ZodProps extends ZodType = any> extend
133
136
  */
134
137
  computeSchematicGlobalTransform(): Matrix;
135
138
  getSchematicSymbol(variant?: "horz" | "vert" | null): SchSymbol | null;
139
+ /**
140
+ * Subcircuit groups have a prop called "layout" that can include manual
141
+ * placements for pcb components. These are typically added from an IDE
142
+ */
143
+ _getManualPlacementForComponent(component: PrimitiveComponent): {
144
+ x: number;
145
+ y: number;
146
+ } | null;
136
147
  getGlobalPcbPosition(): {
137
148
  x: number;
138
149
  y: number;
package/dist/index.js CHANGED
@@ -239,9 +239,23 @@ var PrimitiveComponent = class extends Renderable {
239
239
  }
240
240
  /**
241
241
  * Compute a transformation matrix combining all parent transforms for PCB
242
- * components
242
+ * components, including this component's translation and rotation.
243
+ *
244
+ * This is used to compute this component's position as well as all children
245
+ * components positions
243
246
  */
244
247
  computePcbGlobalTransform() {
248
+ const { _parsedProps: props } = this;
249
+ const manualPlacement = this.getSubcircuit()._getManualPlacementForComponent(this);
250
+ if (manualPlacement && this.props.pcbX === void 0 && this.props.pcbY === void 0) {
251
+ return compose(
252
+ this.parent?.computePcbGlobalTransform() ?? identity(),
253
+ compose(
254
+ translate(manualPlacement.x, manualPlacement.y),
255
+ rotate((props.pcbRotation ?? 0) * Math.PI / 180)
256
+ )
257
+ );
258
+ }
245
259
  return compose(
246
260
  this.parent?.computePcbGlobalTransform() ?? identity(),
247
261
  this.computePcbPropsTransform()
@@ -274,6 +288,27 @@ var PrimitiveComponent = class extends Renderable {
274
288
  if (!config.schematicSymbolName) return null;
275
289
  return symbols[`${config.schematicSymbolName}_${variant}`] ?? null;
276
290
  }
291
+ /**
292
+ * Subcircuit groups have a prop called "layout" that can include manual
293
+ * placements for pcb components. These are typically added from an IDE
294
+ */
295
+ _getManualPlacementForComponent(component) {
296
+ if (!this.isSubcircuit) return null;
297
+ const layout = this.props.layout;
298
+ if (!layout) return null;
299
+ const placementConfig = layout.manual_pcb_placement_config;
300
+ if (!placementConfig) return null;
301
+ for (const position of placementConfig.positions) {
302
+ if (isMatchingSelector(component, position.selector)) {
303
+ const center = applyToPoint(
304
+ this.computePcbGlobalTransform(),
305
+ position.center
306
+ );
307
+ return center;
308
+ }
309
+ }
310
+ return null;
311
+ }
277
312
  getGlobalPcbPosition() {
278
313
  return applyToPoint(this.computePcbGlobalTransform(), { x: 0, y: 0 });
279
314
  }
@@ -15,6 +15,7 @@ import {
15
15
  type Matrix,
16
16
  } from "transformation-matrix"
17
17
  import { isMatchingSelector } from "lib/utils/selector-matching"
18
+ import type { LayoutBuilder } from "@tscircuit/layout"
18
19
 
19
20
  export interface BaseComponentConfig {
20
21
  schematicSymbolName?: BaseSymbolName | null
@@ -125,9 +126,31 @@ export abstract class PrimitiveComponent<
125
126
 
126
127
  /**
127
128
  * Compute a transformation matrix combining all parent transforms for PCB
128
- * components
129
+ * components, including this component's translation and rotation.
130
+ *
131
+ * This is used to compute this component's position as well as all children
132
+ * components positions
129
133
  */
130
134
  computePcbGlobalTransform(): Matrix {
135
+ const { _parsedProps: props } = this
136
+ const manualPlacement =
137
+ this.getSubcircuit()._getManualPlacementForComponent(this)
138
+
139
+ // pcbX or pcbY will override the manual placement
140
+ if (
141
+ manualPlacement &&
142
+ this.props.pcbX === undefined &&
143
+ this.props.pcbY === undefined
144
+ ) {
145
+ return compose(
146
+ this.parent?.computePcbGlobalTransform() ?? identity(),
147
+ compose(
148
+ translate(manualPlacement.x, manualPlacement.y),
149
+ rotate(((props.pcbRotation ?? 0) * Math.PI) / 180),
150
+ ),
151
+ )
152
+ }
153
+
131
154
  return compose(
132
155
  this.parent?.computePcbGlobalTransform() ?? identity(),
133
156
  this.computePcbPropsTransform(),
@@ -168,6 +191,34 @@ export abstract class PrimitiveComponent<
168
191
  )
169
192
  }
170
193
 
194
+ /**
195
+ * Subcircuit groups have a prop called "layout" that can include manual
196
+ * placements for pcb components. These are typically added from an IDE
197
+ */
198
+ _getManualPlacementForComponent(
199
+ component: PrimitiveComponent,
200
+ ): { x: number; y: number } | null {
201
+ if (!this.isSubcircuit) return null
202
+
203
+ const layout: LayoutBuilder = this.props.layout
204
+ if (!layout) return null
205
+
206
+ const placementConfig = layout.manual_pcb_placement_config
207
+ if (!placementConfig) return null
208
+
209
+ for (const position of placementConfig.positions) {
210
+ if (isMatchingSelector(component, position.selector)) {
211
+ const center = applyToPoint(
212
+ this.computePcbGlobalTransform(),
213
+ position.center,
214
+ )
215
+ return center
216
+ }
217
+ }
218
+
219
+ return null
220
+ }
221
+
171
222
  getGlobalPcbPosition(): { x: number; y: number } {
172
223
  return applyToPoint(this.computePcbGlobalTransform(), { x: 0, y: 0 })
173
224
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@tscircuit/core",
3
3
  "module": "index.ts",
4
4
  "type": "module",
5
- "version": "0.0.26",
5
+ "version": "0.0.28",
6
6
  "types": "dist/index.d.ts",
7
7
  "main": "dist/index.js",
8
8
  "files": [
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "devDependencies": {
18
18
  "@biomejs/biome": "^1.8.3",
19
- "@tscircuit/layout": "^0.0.27",
19
+ "@tscircuit/layout": "^0.0.28",
20
20
  "@tscircuit/log-soup": "^1.0.2",
21
21
  "@types/bun": "latest",
22
22
  "@types/react": "^18.3.3",