@tscircuit/core 0.0.330 → 0.0.332

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 (3) hide show
  1. package/dist/index.d.ts +29 -11
  2. package/dist/index.js +547 -211
  3. package/package.json +3 -2
package/dist/index.d.ts CHANGED
@@ -1,14 +1,15 @@
1
1
  import * as _tscircuit_props from '@tscircuit/props';
2
- import { subcircuitGroupProps, traceProps, SupplierPartNumbers, SchematicPortArrangement, groupProps, AutorouterConfig, boardProps, capacitorProps, chipProps, diodeProps, jumperProps, ledProps, powerSourceProps, resistorProps, constraintProps, fabricationNotePathProps, fabricationNoteTextProps, footprintProps, subcircuitProps, holeProps, pcbKeepoutProps, netAliasProps, platedHoleProps, silkscreenCircleProps, silkscreenPathProps, silkscreenRectProps, silkscreenTextProps, silkscreenLineProps, smtPadProps, traceHintProps, viaProps, batteryProps, pinHeaderProps, resonatorProps, inductorProps, potentiometerProps, pushButtonProps, crystalProps, transistorProps, mosfetProps, switchProps, CapacitorProps, ChipProps, ResistorProps, ManualEditEvent, manual_edits_file } from '@tscircuit/props';
2
+ import { subcircuitGroupProps, AutorouterConfig, traceProps, SupplierPartNumbers, SchematicPortArrangement, groupProps, boardProps, capacitorProps, chipProps, diodeProps, jumperProps, ledProps, powerSourceProps, resistorProps, constraintProps, fabricationNotePathProps, fabricationNoteTextProps, footprintProps, subcircuitProps, holeProps, pcbKeepoutProps, netAliasProps, platedHoleProps, silkscreenCircleProps, silkscreenPathProps, silkscreenRectProps, silkscreenTextProps, silkscreenLineProps, smtPadProps, traceHintProps, viaProps, batteryProps, pinHeaderProps, resonatorProps, inductorProps, potentiometerProps, pushButtonProps, crystalProps, transistorProps, mosfetProps, switchProps, CapacitorProps, ChipProps, ResistorProps, ManualEditEvent, manual_edits_file } from '@tscircuit/props';
3
3
  import React, { ReactElement, DetailedHTMLProps, SVGProps } from 'react';
4
4
  export { createElement } from 'react';
5
5
  import * as zod from 'zod';
6
6
  import { z, ZodType } from 'zod';
7
7
  import { symbols, SchSymbol, BaseSymbolName } from 'schematic-symbols';
8
- import { PcbTraceError, PcbPlacementError, PcbManualEditConflictError, LayerRef, AnyCircuitElement, AnySourceComponent, PcbTrace, RouteHintPoint, CircuitJson } from 'circuit-json';
8
+ import { PcbTraceError, PcbPlacementError, PcbManualEditConflictError, LayerRef, AnyCircuitElement, AnySourceComponent, PcbTraceRoutePoint, PcbTrace, RouteHintPoint, CircuitJson } from 'circuit-json';
9
9
  import { Matrix } from 'transformation-matrix';
10
10
  import { SoupUtilObjects } from '@tscircuit/soup-util';
11
11
  import * as _tscircuit_layout from '@tscircuit/layout';
12
+ import { ConnectivityMap } from 'circuit-json-to-connectivity-map';
12
13
 
13
14
  declare const orderedRenderPhases: readonly ["ReactSubtreesRender", "InitializePortsFromChildren", "CreateNetsFromProps", "CreateTracesFromProps", "CreateTraceHintsFromProps", "SourceRender", "SourceParentAttachment", "PortMatching", "SourceTraceRender", "SourceAddConnectivityMapKey", "SchematicComponentRender", "SchematicPortRender", "SchematicLayout", "SchematicTraceRender", "PcbComponentRender", "PcbPrimitiveRender", "PcbFootprintLayout", "PcbPortRender", "PcbPortAttachment", "PcbLayout", "PcbComponentSizeCalculation", "PcbBoardAutoSize", "PcbTraceRender", "PcbTraceHintRender", "PcbRouteNetIslands", "CadModelRender", "PartsEngineRender"];
14
15
  type RenderPhase = (typeof orderedRenderPhases)[number];
@@ -103,7 +104,7 @@ interface SchematicBoxDimensions {
103
104
  };
104
105
  }
105
106
 
106
- type RootCircuitEventName = "asyncEffect:start" | "asyncEffect:end" | "renderable:renderLifecycle:anyEvent" | `renderable:renderLifecycle:${RenderPhase}:start` | `renderable:renderLifecycle:${RenderPhase}:end` | "external:evalError";
107
+ type RootCircuitEventName = "asyncEffect:start" | "asyncEffect:end" | "renderable:renderLifecycle:anyEvent" | `renderable:renderLifecycle:${RenderPhase}:start` | `renderable:renderLifecycle:${RenderPhase}:end` | "external:evalError" | "autorouting:start" | "autorouting:end" | "autorouting:progress";
107
108
  declare class RootCircuit {
108
109
  firstChild: PrimitiveComponent | null;
109
110
  children: PrimitiveComponent[];
@@ -169,6 +170,7 @@ declare const Circuit: typeof RootCircuit;
169
170
  interface ISubcircuit extends PrimitiveComponent {
170
171
  _shouldUseTraceByTraceRouting(): boolean;
171
172
  _parsedProps: z.infer<typeof subcircuitGroupProps>;
173
+ _getAutorouterConfig(): AutorouterConfig;
172
174
  subcircuit_id: string | null;
173
175
  }
174
176
 
@@ -391,6 +393,7 @@ declare class Net extends PrimitiveComponent<typeof netProps> {
391
393
  };
392
394
  getPortSelector(): string;
393
395
  doInitialSourceRender(): void;
396
+ doInitialSourceParentAttachment(): void;
394
397
  /**
395
398
  * Get all ports connected to this net.
396
399
  *
@@ -412,6 +415,8 @@ declare class Net extends PrimitiveComponent<typeof netProps> {
412
415
  * Sometimes this phase doesn't find any net islands if the autorouter did
413
416
  * a good job and connected the islands. In some sense this is a "backup"
414
417
  * routing phase for autorouters that don't care about connecting nets.
418
+ *
419
+ * This should only run if the autorouter is sequential-trace
415
420
  */
416
421
  doInitialPcbRouteNetIslands(): void;
417
422
  renderError(message: Parameters<typeof PrimitiveComponent.prototype.renderError>[0]): void;
@@ -662,6 +667,7 @@ declare class Trace extends PrimitiveComponent<typeof traceProps> implements Tra
662
667
  _isExplicitlyConnectedToNet(net: Net): boolean;
663
668
  doInitialCreateNetsFromProps(): void;
664
669
  doInitialSourceTraceRender(): void;
670
+ _insertErrorIfTraceIsOutsideBoard(mergedRoute: PcbTraceRoutePoint[], ports: Port[]): void;
665
671
  doInitialPcbTraceRender(): void;
666
672
  _doInitialSchematicTraceRenderWithDisplayLabel(): void;
667
673
  private _isSymbolToChipConnection;
@@ -902,6 +908,7 @@ declare class NormalComponent<ZodProps extends ZodType = any, PortNames extends
902
908
  type SimplifiedPcbTrace = {
903
909
  type: "pcb_trace";
904
910
  pcb_trace_id: string;
911
+ connection_name?: string;
905
912
  route: Array<{
906
913
  route_type: "wire";
907
914
  x: number;
@@ -965,12 +972,15 @@ declare class Group<Props extends z.ZodType<any, any, any> = typeof groupProps>
965
972
  doInitialSourceParentAttachment(): void;
966
973
  doInitialPcbComponentRender(): void;
967
974
  doInitialCreateTraceHintsFromProps(): void;
968
- _getSimpleRouteJsonFromPcbTraces(): SimpleRouteJson;
969
975
  doInitialSourceAddConnectivityMapKey(): void;
970
976
  _areChildSubcircuitsRouted(): boolean;
971
977
  _shouldRouteAsync(): boolean;
972
978
  _hasTracesToRoute(): boolean;
973
979
  _runEffectMakeHttpAutoroutingRequest(): Promise<void>;
980
+ /**
981
+ * Run local autorouting using the CapacityMeshAutorouter
982
+ */
983
+ _runLocalCapacityMeshAutorouting(): Promise<void>;
974
984
  _startAsyncAutorouting(): void;
975
985
  doInitialPcbTraceRender(): void;
976
986
  updatePcbTraceRender(): void;
@@ -10714,10 +10724,15 @@ declare const applyEditEventsToManualEditsFile: ({ circuitJson, editEvents, manu
10714
10724
  /**
10715
10725
  * This function can only be called in the PcbTraceRender phase or later
10716
10726
  */
10717
- declare const getSimpleRouteJsonFromCircuitJson: ({ circuitJson, minTraceWidth, }: {
10718
- circuitJson: AnyCircuitElement[];
10727
+ declare const getSimpleRouteJsonFromCircuitJson: ({ db, circuitJson, subcircuit_id, minTraceWidth, }: {
10728
+ db?: SoupUtilObjects;
10729
+ circuitJson?: AnyCircuitElement[];
10730
+ subcircuit_id?: string | null;
10719
10731
  minTraceWidth?: number;
10720
- }) => SimpleRouteJson;
10732
+ }) => {
10733
+ simpleRouteJson: SimpleRouteJson;
10734
+ connMap: ConnectivityMap;
10735
+ };
10721
10736
 
10722
10737
  type RenderEvent = {
10723
10738
  type: string;
@@ -10736,7 +10751,7 @@ declare const getPhaseTimingsFromRenderEvents: (renderEvents: RenderEvent[]) =>
10736
10751
  type Nums16 = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "10" | "11" | "12" | "13" | "14" | "15" | "16";
10737
10752
  type Nums40 = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "10" | "11" | "12" | "13" | "14" | "15" | "16" | "17" | "18" | "19" | "20" | "21" | "22" | "23" | "24" | "25" | "26" | "27" | "28" | "29" | "30" | "31" | "32" | "33" | "34" | "35" | "36" | "37" | "38" | "39" | "40";
10738
10753
  type PinNumbers100 = "pin1" | "pin2" | "pin3" | "pin4" | "pin5" | "pin6" | "pin7" | "pin8" | "pin9" | "pin10" | "pin11" | "pin12" | "pin13" | "pin14" | "pin15" | "pin16" | "pin17" | "pin18" | "pin19" | "pin20" | "pin21" | "pin22" | "pin23" | "pin24" | "pin25" | "pin26" | "pin27" | "pin28" | "pin29" | "pin30" | "pin31" | "pin32" | "pin33" | "pin34" | "pin35" | "pin36" | "pin37" | "pin38" | "pin39" | "pin40" | "pin41" | "pin42" | "pin43" | "pin44" | "pin45" | "pin46" | "pin47" | "pin48" | "pin49" | "pin50" | "pin51" | "pin52" | "pin53" | "pin54" | "pin55" | "pin56" | "pin57" | "pin58" | "pin59" | "pin60" | "pin61" | "pin62" | "pin63" | "pin64" | "pin65" | "pin66" | "pin67" | "pin68" | "pin69" | "pin70" | "pin71" | "pin72" | "pin73" | "pin74" | "pin75" | "pin76" | "pin77" | "pin78" | "pin79" | "pin80" | "pin81" | "pin82" | "pin83" | "pin84" | "pin85" | "pin86" | "pin87" | "pin88" | "pin89" | "pin90" | "pin91" | "pin92" | "pin93" | "pin94" | "pin95" | "pin96" | "pin97" | "pin98" | "pin99" | "pin100";
10739
- type CommonPinNames = "pos" | "neg" | "V5" | "V3_3" | "VCC" | "VDD" | "GND" | `D${Nums40}` | `GP${Nums40}` | `GPIO${Nums40}` | "DP" | "DN" | "VIN" | "VOUT" | "VREF" | "VIN" | "VOUT" | "VREF" | "VIN" | "VOUT" | "VREF" | "OUT" | "DISCH" | "EN" | "IN" | "CLK" | "DATA" | "THRES" | "TRIG" | "RESET" | `A${Nums40}` | `B${Nums40}` | PinNumbers100;
10754
+ type CommonPinNames = "pos" | "neg" | "V5" | "V3_3" | "PWR" | "VCC" | "VDD" | "GND" | `D${Nums40}` | `GP${Nums40}` | `GPIO${Nums40}` | "DP" | "DN" | "VIN" | "VOUT" | "VREF" | "VIN" | "VOUT" | "VREF" | "VIN" | "VOUT" | "VREF" | "OUT" | "DISCH" | "EN" | "IN" | "CLK" | "DATA" | "THRES" | "TRIG" | "RESET" | `A${Nums40}` | `B${Nums40}` | PinNumbers100;
10740
10755
  type TransistorPinNames = "base" | "collector" | "emitter";
10741
10756
 
10742
10757
  type NonPolarizedSel = Record<`R${Nums40}`, {
@@ -10761,12 +10776,15 @@ type PolarizedSel = Record<`C${Nums40}` | `L${Nums40}` | `LED${Nums40}` | `D${Nu
10761
10776
  pos: string;
10762
10777
  neg: string;
10763
10778
  }>;
10779
+ type CommonNetNames = "VCC" | "GND" | "VDD" | "PWR" | "V5" | "V3_3";
10764
10780
  type TransistorSel = Record<`Q${Nums40}`, Record<TransistorPinNames, string>>;
10765
- type JumperSel = Record<`J${Nums40}`, Record<PinNumbers100, string>>;
10781
+ type JumperSel = Record<`J${Nums40}`, Record<PinNumbers100 | CommonPinNames, string>>;
10766
10782
  type ChipSel = Record<`U${Nums40}`, Record<CommonPinNames, string>>;
10767
- type NetSel = Record<"net", Record<"VCC" | "GND" | "VDD", string>>;
10783
+ type NetSel = Record<"net", Record<CommonNetNames, string>>;
10768
10784
  type ConnectionSel = Record<`CN${Nums40}`, Record<CommonPinNames, string>>;
10769
- type Sel = NonPolarizedSel & PolarizedSel & TransistorSel & JumperSel & ChipSel & SwSel & NetSel & ConnectionSel;
10785
+ type SubcircuitSel = Record<"subcircuit", Record<`S${Nums40}`, SelWithoutSubcircuit>>;
10786
+ type SelWithoutSubcircuit = NonPolarizedSel & PolarizedSel & TransistorSel & JumperSel & ChipSel & SwSel & NetSel & ConnectionSel;
10787
+ type Sel = SubcircuitSel & SelWithoutSubcircuit;
10770
10788
  declare const sel: Sel;
10771
10789
 
10772
10790
  interface TscircuitElements {
package/dist/index.js CHANGED
@@ -1192,6 +1192,14 @@ var Net = class extends PrimitiveComponent {
1192
1192
  });
1193
1193
  this.source_net_id = net.source_net_id;
1194
1194
  }
1195
+ doInitialSourceParentAttachment() {
1196
+ const subcircuit = this.getSubcircuit();
1197
+ if (!subcircuit) return;
1198
+ const { db } = this.root;
1199
+ db.source_net.update(this.source_net_id, {
1200
+ subcircuit_id: subcircuit.subcircuit_id
1201
+ });
1202
+ }
1195
1203
  /**
1196
1204
  * Get all ports connected to this net.
1197
1205
  *
@@ -1235,10 +1243,14 @@ var Net = class extends PrimitiveComponent {
1235
1243
  * Sometimes this phase doesn't find any net islands if the autorouter did
1236
1244
  * a good job and connected the islands. In some sense this is a "backup"
1237
1245
  * routing phase for autorouters that don't care about connecting nets.
1246
+ *
1247
+ * This should only run if the autorouter is sequential-trace
1238
1248
  */
1239
1249
  doInitialPcbRouteNetIslands() {
1240
1250
  if (this.root?.pcbDisabled) return;
1241
1251
  if (this.getSubcircuit()._parsedProps.routingDisabled) return;
1252
+ if (this.getSubcircuit()._getAutorouterConfig().groupMode !== "sequential-trace")
1253
+ return;
1242
1254
  const { db } = this.root;
1243
1255
  const { _parsedProps: props } = this;
1244
1256
  const traces = this._getAllDirectlyConnectedTraces().filter(
@@ -1335,8 +1347,12 @@ var Net = class extends PrimitiveComponent {
1335
1347
  var createNetsFromProps = (component, props) => {
1336
1348
  for (const prop of props) {
1337
1349
  if (typeof prop === "string" && prop.startsWith("net.")) {
1338
- if (!component.getSubcircuit().selectOne(prop)) {
1339
- component.getSubcircuit().add(new Net({ name: prop.split("net.")[1] }));
1350
+ const subcircuit = component.getSubcircuit();
1351
+ if (!subcircuit.selectOne(prop)) {
1352
+ const net = new Net({
1353
+ name: prop.split("net.")[1]
1354
+ });
1355
+ subcircuit.add(net);
1340
1356
  }
1341
1357
  }
1342
1358
  }
@@ -2284,7 +2300,8 @@ var Port = class extends PrimitiveComponent {
2284
2300
  );
2285
2301
  }
2286
2302
  db.source_port.update(this.source_port_id, {
2287
- source_component_id: this.parent?.source_component_id
2303
+ source_component_id: this.parent?.source_component_id,
2304
+ subcircuit_id: this.getSubcircuit()?.subcircuit_id
2288
2305
  });
2289
2306
  this.source_component_id = this.parent?.source_component_id;
2290
2307
  }
@@ -2967,6 +2984,7 @@ var DirectLineRouter = class {
2967
2984
  const trace = {
2968
2985
  type: "pcb_trace",
2969
2986
  pcb_trace_id: "",
2987
+ connection_name: connection.name,
2970
2988
  route: [
2971
2989
  {
2972
2990
  route_type: "wire",
@@ -3634,6 +3652,22 @@ var pushEdgesOfSchematicTraceToPreventOverlap = ({
3634
3652
  }
3635
3653
  };
3636
3654
 
3655
+ // lib/utils/is-route-outside-board.ts
3656
+ var isRouteOutsideBoard = (mergedRoute, { db }) => {
3657
+ const pcbBoard = db.pcb_board.list()[0];
3658
+ if (pcbBoard.outline) {
3659
+ return true;
3660
+ }
3661
+ const boardWidth = pcbBoard.width;
3662
+ const boardHeight = pcbBoard.height;
3663
+ const boardCenterX = pcbBoard.center.x;
3664
+ const boardCenterY = pcbBoard.center.y;
3665
+ const outsideBoard = mergedRoute.some((point) => {
3666
+ return point.x < boardCenterX - boardWidth / 2 || point.y < boardCenterY - boardHeight / 2 || point.x > boardCenterX + boardWidth / 2 || point.y > boardCenterY + boardHeight / 2;
3667
+ });
3668
+ return outsideBoard;
3669
+ };
3670
+
3637
3671
  // lib/components/primitive-components/Trace/Trace.ts
3638
3672
  var portToObjective = (port) => {
3639
3673
  const portPosition = port._getGlobalPcbPositionAfterLayout();
@@ -3790,6 +3824,20 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
3790
3824
  });
3791
3825
  this.source_trace_id = trace.source_trace_id;
3792
3826
  }
3827
+ _insertErrorIfTraceIsOutsideBoard(mergedRoute, ports) {
3828
+ const { db } = this.root;
3829
+ const isOutsideBoard = isRouteOutsideBoard(mergedRoute, { db });
3830
+ if (isOutsideBoard) {
3831
+ db.pcb_trace_error.insert({
3832
+ error_type: "pcb_trace_error",
3833
+ source_trace_id: this.source_trace_id,
3834
+ message: `Trace ${this.getString()} routed outside the board boundaries.`,
3835
+ pcb_trace_id: this.pcb_trace_id,
3836
+ pcb_component_ids: [],
3837
+ pcb_port_ids: ports.map((p) => p.pcb_port_id)
3838
+ });
3839
+ }
3840
+ }
3793
3841
  doInitialPcbTraceRender() {
3794
3842
  if (this.root?.pcbDisabled) return;
3795
3843
  const { db } = this.root;
@@ -4061,6 +4109,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
4061
4109
  });
4062
4110
  }
4063
4111
  }
4112
+ this._insertErrorIfTraceIsOutsideBoard(mergedRoute, ports);
4064
4113
  }
4065
4114
  _doInitialSchematicTraceRenderWithDisplayLabel() {
4066
4115
  if (this.root?.schematicDisabled) return;
@@ -4658,7 +4707,6 @@ var NormalComponent = class extends PrimitiveComponent {
4658
4707
  if (symbol) {
4659
4708
  const schematic_component2 = db.schematic_component.insert({
4660
4709
  center,
4661
- rotation: props.schRotation ?? 0,
4662
4710
  size: symbol.size,
4663
4711
  source_component_id: this.source_component_id,
4664
4712
  symbol_name,
@@ -5102,64 +5150,156 @@ import {
5102
5150
  groupProps
5103
5151
  } from "@tscircuit/props";
5104
5152
  import * as SAL from "@tscircuit/schematic-autolayout";
5105
- import "circuit-json";
5106
- import { ConnectivityMap } from "circuit-json-to-connectivity-map";
5107
- import Debug5 from "debug";
5108
5153
 
5109
- // lib/utils/autorouting/getSimpleRouteJsonFromTracesAndDb.ts
5110
- import { getObstaclesFromSoup as getObstaclesFromSoup2 } from "@tscircuit/infgrid-ijump-astar";
5111
- var getSimpleRouteJsonFromTracesAndDb = ({
5112
- db,
5113
- traces,
5114
- minTraceWidth = 0.1
5115
- }) => {
5116
- const obstacles = getObstaclesFromSoup2([
5117
- ...db.pcb_component.list(),
5118
- ...db.pcb_smtpad.list(),
5119
- ...db.pcb_plated_hole.list()
5120
- ]);
5121
- const allPoints = obstacles.flatMap((o) => [
5122
- {
5123
- x: o.center.x - o.width / 2,
5124
- y: o.center.y - o.height / 2
5125
- },
5126
- {
5127
- x: o.center.x + o.width / 2,
5128
- y: o.center.y + o.height / 2
5129
- }
5130
- ]);
5131
- const bounds = {
5132
- minX: Math.min(...allPoints.map((p) => p.x)) - 1,
5133
- maxX: Math.max(...allPoints.map((p) => p.x)) + 1,
5134
- minY: Math.min(...allPoints.map((p) => p.y)) - 1,
5135
- maxY: Math.max(...allPoints.map((p) => p.y)) + 1
5136
- };
5137
- const connections = traces.map((trace) => {
5138
- const connectedPorts = trace._findConnectedPorts();
5139
- if (!connectedPorts.allPortsFound || connectedPorts.ports.length < 2)
5140
- return null;
5141
- return {
5142
- name: trace.source_trace_id ?? "",
5143
- pointsToConnect: connectedPorts.ports.map((port) => {
5144
- const pos = port._getGlobalPcbPositionBeforeLayout();
5145
- return {
5146
- x: pos.x,
5147
- y: pos.y,
5148
- layer: port.getAvailablePcbLayers()[0] ?? "top"
5149
- };
5150
- })
5151
- };
5152
- }).filter((c) => c !== null);
5153
- return {
5154
- bounds,
5155
- obstacles: [],
5156
- connections,
5157
- layerCount: 2,
5158
- minTraceWidth
5154
+ // lib/utils/autorouting/CapacityMeshAutorouter.ts
5155
+ import { CapacityMeshSolver } from "@tscircuit/capacity-autorouter";
5156
+ var CapacityMeshAutorouter = class {
5157
+ input;
5158
+ isRouting = false;
5159
+ solver;
5160
+ eventHandlers = {
5161
+ complete: [],
5162
+ error: [],
5163
+ progress: []
5159
5164
  };
5165
+ cycleCount = 0;
5166
+ stepDelay;
5167
+ timeoutId;
5168
+ constructor(input, options = {}) {
5169
+ this.input = input;
5170
+ const { capacityDepth, targetMinCapacity, stepDelay = 0 } = options;
5171
+ this.solver = new CapacityMeshSolver(input, {
5172
+ capacityDepth,
5173
+ targetMinCapacity
5174
+ });
5175
+ this.stepDelay = stepDelay;
5176
+ }
5177
+ /**
5178
+ * Start the autorouting process asynchronously
5179
+ * This will emit progress events during routing and a complete event when done
5180
+ */
5181
+ start() {
5182
+ if (this.isRouting) return;
5183
+ this.isRouting = true;
5184
+ this.cycleCount = 0;
5185
+ this.runCycleAndQueueNextCycle();
5186
+ }
5187
+ /**
5188
+ * Execute the next routing step and schedule the following one if needed
5189
+ */
5190
+ runCycleAndQueueNextCycle() {
5191
+ if (!this.isRouting) return;
5192
+ try {
5193
+ if (this.solver.solved || this.solver.failed) {
5194
+ if (this.solver.failed) {
5195
+ this.emitEvent({
5196
+ type: "error",
5197
+ error: new Error(this.solver.error || "Routing failed")
5198
+ });
5199
+ } else {
5200
+ this.emitEvent({
5201
+ type: "complete",
5202
+ traces: this.solver.getOutputSimpleRouteJson().traces || []
5203
+ });
5204
+ }
5205
+ this.isRouting = false;
5206
+ return;
5207
+ }
5208
+ const startTime = performance.now();
5209
+ const startIterations = this.solver.iterations;
5210
+ while (performance.now() - startTime < 10 && !this.solver.failed && !this.solver.solved) {
5211
+ this.solver.step();
5212
+ }
5213
+ this.cycleCount++;
5214
+ const debugGraphics = this.solver.activeSolver?.visualize() || void 0;
5215
+ const progress = this.solver.progress;
5216
+ this.emitEvent({
5217
+ type: "progress",
5218
+ steps: this.cycleCount,
5219
+ progress,
5220
+ phase: this.solver.getCurrentPhase(),
5221
+ debugGraphics
5222
+ });
5223
+ if (this.stepDelay > 0) {
5224
+ this.timeoutId = setTimeout(
5225
+ () => this.runCycleAndQueueNextCycle(),
5226
+ this.stepDelay
5227
+ );
5228
+ } else {
5229
+ this.timeoutId = setTimeout(
5230
+ () => this.runCycleAndQueueNextCycle(),
5231
+ 0
5232
+ );
5233
+ }
5234
+ } catch (error) {
5235
+ this.emitEvent({
5236
+ type: "error",
5237
+ error: error instanceof Error ? error : new Error(String(error))
5238
+ });
5239
+ this.isRouting = false;
5240
+ }
5241
+ }
5242
+ /**
5243
+ * Stop the routing process if it's in progress
5244
+ */
5245
+ stop() {
5246
+ if (!this.isRouting) return;
5247
+ this.isRouting = false;
5248
+ if (this.timeoutId !== void 0) {
5249
+ clearTimeout(this.timeoutId);
5250
+ this.timeoutId = void 0;
5251
+ }
5252
+ }
5253
+ on(event, callback) {
5254
+ if (event === "complete") {
5255
+ this.eventHandlers.complete.push(
5256
+ callback
5257
+ );
5258
+ } else if (event === "error") {
5259
+ this.eventHandlers.error.push(
5260
+ callback
5261
+ );
5262
+ } else if (event === "progress") {
5263
+ this.eventHandlers.progress.push(
5264
+ callback
5265
+ );
5266
+ }
5267
+ }
5268
+ /**
5269
+ * Emit an event to all registered handlers
5270
+ */
5271
+ emitEvent(event) {
5272
+ if (event.type === "complete") {
5273
+ for (const handler of this.eventHandlers.complete) {
5274
+ handler(event);
5275
+ }
5276
+ } else if (event.type === "error") {
5277
+ for (const handler of this.eventHandlers.error) {
5278
+ handler(event);
5279
+ }
5280
+ } else if (event.type === "progress") {
5281
+ for (const handler of this.eventHandlers.progress) {
5282
+ handler(event);
5283
+ }
5284
+ }
5285
+ }
5286
+ /**
5287
+ * Solve the routing problem synchronously
5288
+ * @returns Array of routed traces
5289
+ */
5290
+ solveSync() {
5291
+ this.solver.solve();
5292
+ if (this.solver.failed) {
5293
+ throw new Error(this.solver.error || "Routing failed");
5294
+ }
5295
+ return this.solver.getOutputSimpleRouteJson().traces || [];
5296
+ }
5160
5297
  };
5161
5298
 
5162
5299
  // lib/components/primitive-components/Group/Group.ts
5300
+ import "circuit-json";
5301
+ import { ConnectivityMap as ConnectivityMap2 } from "circuit-json-to-connectivity-map";
5302
+ import Debug5 from "debug";
5163
5303
  import "zod";
5164
5304
 
5165
5305
  // lib/components/primitive-components/TraceHint.ts
@@ -5223,6 +5363,220 @@ var TraceHint = class extends PrimitiveComponent {
5223
5363
  }
5224
5364
  };
5225
5365
 
5366
+ // lib/utils/edit-events/apply-edit-events-to-manual-edits-file.ts
5367
+ import "zod";
5368
+ import { su } from "@tscircuit/soup-util";
5369
+ var applyEditEventsToManualEditsFile = ({
5370
+ circuitJson,
5371
+ editEvents,
5372
+ manualEditsFile
5373
+ }) => {
5374
+ const updatedManualEditsFile = {
5375
+ ...manualEditsFile,
5376
+ schematic_placements: [...manualEditsFile.schematic_placements ?? []]
5377
+ };
5378
+ for (const editEvent of editEvents) {
5379
+ if (editEvent.edit_event_type === "edit_schematic_component_location") {
5380
+ const { schematic_component_id, new_center } = editEvent;
5381
+ const schematic_component2 = su(circuitJson).schematic_component.get(
5382
+ schematic_component_id
5383
+ );
5384
+ if (!schematic_component2) continue;
5385
+ const source_component = su(circuitJson).source_component.get(
5386
+ schematic_component2.source_component_id
5387
+ );
5388
+ if (!source_component) continue;
5389
+ const existingPlacementIndex = updatedManualEditsFile.schematic_placements?.findIndex(
5390
+ (p) => p.selector === source_component.name
5391
+ );
5392
+ const newPlacement = {
5393
+ selector: source_component.name,
5394
+ center: new_center,
5395
+ relative_to: "group_center"
5396
+ };
5397
+ if (existingPlacementIndex >= 0) {
5398
+ updatedManualEditsFile.schematic_placements[existingPlacementIndex] = newPlacement;
5399
+ } else {
5400
+ updatedManualEditsFile.schematic_placements.push(newPlacement);
5401
+ }
5402
+ }
5403
+ }
5404
+ return updatedManualEditsFile;
5405
+ };
5406
+
5407
+ // lib/utils/autorouting/getSimpleRouteJsonFromCircuitJson.ts
5408
+ import { getObstaclesFromSoup as getObstaclesFromSoup2 } from "@tscircuit/infgrid-ijump-astar";
5409
+ import { su as su2 } from "@tscircuit/soup-util";
5410
+ import {
5411
+ getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson2
5412
+ } from "circuit-json-to-connectivity-map";
5413
+
5414
+ // lib/utils/autorouting/getAncestorSubcircuitIds.ts
5415
+ var getDescendantSubcircuitIds = (db, root_subcircuit_id) => {
5416
+ const groups = db.source_group.list();
5417
+ const result = [];
5418
+ const findDescendants = (parentId) => {
5419
+ const children = groups.filter(
5420
+ (group) => group.parent_subcircuit_id === parentId
5421
+ );
5422
+ for (const child of children) {
5423
+ if (child.subcircuit_id) {
5424
+ result.push(child.subcircuit_id);
5425
+ findDescendants(child.subcircuit_id);
5426
+ }
5427
+ }
5428
+ };
5429
+ findDescendants(root_subcircuit_id);
5430
+ return result;
5431
+ };
5432
+
5433
+ // lib/utils/autorouting/getSimpleRouteJsonFromCircuitJson.ts
5434
+ var getSimpleRouteJsonFromCircuitJson = ({
5435
+ db,
5436
+ circuitJson,
5437
+ subcircuit_id,
5438
+ minTraceWidth = 0.1
5439
+ }) => {
5440
+ if (!db && circuitJson) {
5441
+ db = su2(circuitJson);
5442
+ }
5443
+ if (!db) {
5444
+ throw new Error("db or circuitJson is required");
5445
+ }
5446
+ const relevantSubcircuitIds = subcircuit_id ? /* @__PURE__ */ new Set([subcircuit_id]) : null;
5447
+ if (subcircuit_id) {
5448
+ const descendantSubcircuitIds = getDescendantSubcircuitIds(
5449
+ db,
5450
+ subcircuit_id
5451
+ );
5452
+ for (const id of descendantSubcircuitIds) {
5453
+ relevantSubcircuitIds.add(id);
5454
+ }
5455
+ }
5456
+ const subcircuitElements = (circuitJson ?? db.toArray()).filter(
5457
+ (e) => !subcircuit_id || "subcircuit_id" in e && relevantSubcircuitIds.has(e.subcircuit_id)
5458
+ );
5459
+ const board = db.pcb_board.list()[0];
5460
+ db = su2(subcircuitElements);
5461
+ const connMap = getFullConnectivityMapFromCircuitJson2(subcircuitElements);
5462
+ const obstacles = getObstaclesFromSoup2(
5463
+ [
5464
+ ...db.pcb_component.list(),
5465
+ ...db.pcb_smtpad.list(),
5466
+ ...db.pcb_plated_hole.list()
5467
+ ].filter(
5468
+ (e) => !subcircuit_id || relevantSubcircuitIds?.has(e.subcircuit_id)
5469
+ ),
5470
+ connMap
5471
+ );
5472
+ const allPoints = obstacles.flatMap((o) => [
5473
+ {
5474
+ x: o.center.x - o.width / 2,
5475
+ y: o.center.y - o.height / 2
5476
+ },
5477
+ {
5478
+ x: o.center.x + o.width / 2,
5479
+ y: o.center.y + o.height / 2
5480
+ }
5481
+ ]);
5482
+ let bounds;
5483
+ if (board) {
5484
+ bounds = {
5485
+ minX: board.center.x - board.width / 2,
5486
+ maxX: board.center.x + board.width / 2,
5487
+ minY: board.center.y - board.height / 2,
5488
+ maxY: board.center.y + board.height / 2
5489
+ };
5490
+ } else {
5491
+ bounds = {
5492
+ minX: Math.min(...allPoints.map((p) => p.x)) - 1,
5493
+ maxX: Math.max(...allPoints.map((p) => p.x)) + 1,
5494
+ minY: Math.min(...allPoints.map((p) => p.y)) - 1,
5495
+ maxY: Math.max(...allPoints.map((p) => p.y)) + 1
5496
+ };
5497
+ }
5498
+ const directTraceConnections = db.source_trace.list().map((trace) => {
5499
+ const connectedPorts = trace.connected_source_port_ids.map((id) => {
5500
+ const source_port = db.source_port.get(id);
5501
+ const pcb_port = db.pcb_port.getWhere({ source_port_id: id });
5502
+ return {
5503
+ ...source_port,
5504
+ ...pcb_port
5505
+ };
5506
+ });
5507
+ if (connectedPorts.length < 2) return null;
5508
+ return {
5509
+ name: connMap.getNetConnectedToId(trace.source_trace_id) ?? trace.source_trace_id ?? "",
5510
+ source_trace_id: trace.source_trace_id,
5511
+ pointsToConnect: connectedPorts.map((port) => {
5512
+ return {
5513
+ x: port.x,
5514
+ y: port.y,
5515
+ layer: port.layers?.[0] ?? "top"
5516
+ };
5517
+ })
5518
+ };
5519
+ }).filter((c) => c !== null);
5520
+ const source_nets = db.source_net.list().filter(
5521
+ (e) => !subcircuit_id || relevantSubcircuitIds?.has(e.subcircuit_id)
5522
+ );
5523
+ const connectionsFromNets = [];
5524
+ for (const net of source_nets) {
5525
+ const connectedSourceTraces = db.source_trace.list().filter((st) => st.connected_source_net_ids?.includes(net.source_net_id));
5526
+ connectionsFromNets.push({
5527
+ name: connMap.getNetConnectedToId(net.source_net_id) ?? net.source_net_id,
5528
+ pointsToConnect: connectedSourceTraces.flatMap((st) => {
5529
+ const pcb_ports = db.pcb_port.list().filter(
5530
+ (p) => st.connected_source_port_ids.includes(p.source_port_id)
5531
+ );
5532
+ return pcb_ports.map((p) => ({
5533
+ x: p.x,
5534
+ y: p.y,
5535
+ layer: p.layers?.[0] ?? "top",
5536
+ pcb_port_id: p.pcb_port_id
5537
+ }));
5538
+ })
5539
+ });
5540
+ }
5541
+ return {
5542
+ simpleRouteJson: {
5543
+ bounds,
5544
+ obstacles,
5545
+ connections: [...directTraceConnections, ...connectionsFromNets],
5546
+ // TODO add traces so that we don't run into things routed by another
5547
+ // subcircuit
5548
+ layerCount: 2,
5549
+ minTraceWidth
5550
+ },
5551
+ connMap
5552
+ };
5553
+ };
5554
+
5555
+ // lib/utils/render-events/getPhaseTimingsFromRenderEvents.ts
5556
+ var getPhaseTimingsFromRenderEvents = (renderEvents) => {
5557
+ const phaseTimings = {};
5558
+ if (!renderEvents) return phaseTimings;
5559
+ for (const renderPhase of orderedRenderPhases) {
5560
+ phaseTimings[renderPhase] = 0;
5561
+ }
5562
+ const startEvents = /* @__PURE__ */ new Map();
5563
+ for (const event of renderEvents) {
5564
+ const [, , phase, eventType] = event.type.split(":");
5565
+ if (eventType === "start") {
5566
+ startEvents.set(`${phase}:${event.renderId}`, event);
5567
+ continue;
5568
+ }
5569
+ if (eventType === "end") {
5570
+ const startEvent = startEvents.get(`${phase}:${event.renderId}`);
5571
+ if (startEvent) {
5572
+ const duration = event.createdAt - startEvent.createdAt;
5573
+ phaseTimings[phase] = (phaseTimings[phase] || 0) + duration;
5574
+ }
5575
+ }
5576
+ }
5577
+ return phaseTimings;
5578
+ };
5579
+
5226
5580
  // lib/components/primitive-components/Group/Group.ts
5227
5581
  var Group = class extends NormalComponent {
5228
5582
  pcb_group_id = null;
@@ -5288,20 +5642,11 @@ var Group = class extends NormalComponent {
5288
5642
  );
5289
5643
  }
5290
5644
  }
5291
- _getSimpleRouteJsonFromPcbTraces() {
5292
- const traces = this.selectAll("trace");
5293
- const { db } = this.root;
5294
- return getSimpleRouteJsonFromTracesAndDb({
5295
- db,
5296
- traces,
5297
- minTraceWidth: this._parsedProps.minTraceWidth ?? 0.1
5298
- });
5299
- }
5300
5645
  doInitialSourceAddConnectivityMapKey() {
5301
5646
  if (!this.isSubcircuit) return;
5302
5647
  const { db } = this.root;
5303
5648
  const traces = this.selectAll("trace");
5304
- const connMap = new ConnectivityMap({});
5649
+ const connMap = new ConnectivityMap2({});
5305
5650
  connMap.addConnections(
5306
5651
  traces.map((t) => {
5307
5652
  const source_trace = db.source_trace.get(
@@ -5339,9 +5684,10 @@ var Group = class extends NormalComponent {
5339
5684
  }
5340
5685
  _shouldRouteAsync() {
5341
5686
  const autorouter = this._getAutorouterConfig();
5342
- if (autorouter.local) return false;
5343
5687
  if (autorouter.groupMode === "sequential-trace") return false;
5344
- return true;
5688
+ if (autorouter.local && autorouter.groupMode === "subcircuit") return true;
5689
+ if (!autorouter.local) return true;
5690
+ return false;
5345
5691
  }
5346
5692
  _hasTracesToRoute() {
5347
5693
  const debug4 = Debug5("tscircuit:core:_hasTracesToRoute");
@@ -5372,7 +5718,11 @@ var Group = class extends NormalComponent {
5372
5718
  {
5373
5719
  method: "POST",
5374
5720
  body: JSON.stringify({
5375
- input_simple_route_json: this._getSimpleRouteJsonFromPcbTraces(),
5721
+ input_simple_route_json: getSimpleRouteJsonFromCircuitJson({
5722
+ db,
5723
+ minTraceWidth: this.props.autorouter?.minTraceWidth ?? 0.15,
5724
+ subcircuit_id: this.subcircuit_id
5725
+ }).simpleRouteJson,
5376
5726
  subcircuit_id: this.subcircuit_id
5377
5727
  }),
5378
5728
  headers: { "Content-Type": "application/json" }
@@ -5450,12 +5800,73 @@ var Group = class extends NormalComponent {
5450
5800
  await new Promise((resolve) => setTimeout(resolve, 100));
5451
5801
  }
5452
5802
  }
5803
+ /**
5804
+ * Run local autorouting using the CapacityMeshAutorouter
5805
+ */
5806
+ async _runLocalCapacityMeshAutorouting() {
5807
+ const { db } = this.root;
5808
+ const debug4 = Debug5("tscircuit:core:_runLocalCapacityMeshAutorouting");
5809
+ debug4(`[${this.getString()}] starting local capacity mesh autorouting`);
5810
+ const { simpleRouteJson, connMap } = getSimpleRouteJsonFromCircuitJson({
5811
+ db,
5812
+ minTraceWidth: this.props.autorouter?.minTraceWidth ?? 0.15,
5813
+ subcircuit_id: this.subcircuit_id
5814
+ });
5815
+ this.root?.emit("autorouting:start", {
5816
+ subcircuit_id: this.subcircuit_id,
5817
+ componentDisplayName: this.getString(),
5818
+ simpleRouteJson
5819
+ });
5820
+ const autorouter = new CapacityMeshAutorouter(simpleRouteJson, {
5821
+ // Optional configuration parameters
5822
+ capacityDepth: this.props.autorouter?.capacityDepth,
5823
+ targetMinCapacity: this.props.autorouter?.targetMinCapacity
5824
+ });
5825
+ const routingPromise = new Promise(
5826
+ (resolve, reject) => {
5827
+ autorouter.on("complete", (event) => {
5828
+ debug4(`[${this.getString()}] local autorouting complete`);
5829
+ resolve(event.traces);
5830
+ });
5831
+ autorouter.on("error", (event) => {
5832
+ debug4(
5833
+ `[${this.getString()}] local autorouting error: ${event.error.message}`
5834
+ );
5835
+ reject(event.error);
5836
+ });
5837
+ }
5838
+ );
5839
+ autorouter.start();
5840
+ try {
5841
+ const traces = await routingPromise;
5842
+ this._asyncAutoroutingResult = {
5843
+ output_pcb_traces: traces
5844
+ };
5845
+ this._markDirty("PcbTraceRender");
5846
+ } catch (error) {
5847
+ const { db: db2 } = this.root;
5848
+ db2.pcb_autorouting_error.insert({
5849
+ pcb_error_id: `local_${this.subcircuit_id}`,
5850
+ message: error instanceof Error ? error.message : String(error)
5851
+ });
5852
+ throw error;
5853
+ } finally {
5854
+ autorouter.stop();
5855
+ }
5856
+ }
5453
5857
  _startAsyncAutorouting() {
5454
5858
  this._hasStartedAsyncAutorouting = true;
5455
- this._queueAsyncEffect(
5456
- "make-http-autorouting-request",
5457
- async () => this._runEffectMakeHttpAutoroutingRequest()
5458
- );
5859
+ if (this._getAutorouterConfig().local) {
5860
+ this._queueAsyncEffect(
5861
+ "capacity-mesh-autorouting",
5862
+ async () => this._runLocalCapacityMeshAutorouting()
5863
+ );
5864
+ } else {
5865
+ this._queueAsyncEffect(
5866
+ "make-http-autorouting-request",
5867
+ async () => this._runEffectMakeHttpAutoroutingRequest()
5868
+ );
5869
+ }
5459
5870
  }
5460
5871
  doInitialPcbTraceRender() {
5461
5872
  const debug4 = Debug5("tscircuit:core:doInitialPcbTraceRender");
@@ -5477,6 +5888,7 @@ var Group = class extends NormalComponent {
5477
5888
  }
5478
5889
  updatePcbTraceRender() {
5479
5890
  const debug4 = Debug5("tscircuit:core:updatePcbTraceRender");
5891
+ debug4(`[${this.getString()}] updating...`);
5480
5892
  if (!this.isSubcircuit) return;
5481
5893
  if (this._shouldRouteAsync() && this._hasTracesToRoute() && !this._hasStartedAsyncAutorouting) {
5482
5894
  if (this._areChildSubcircuitsRouted()) {
@@ -5491,10 +5903,16 @@ var Group = class extends NormalComponent {
5491
5903
  if (this._shouldUseTraceByTraceRouting()) return;
5492
5904
  const { db } = this.root;
5493
5905
  if (this._asyncAutoroutingResult.output_simple_route_json) {
5906
+ debug4(
5907
+ `[${this.getString()}] updating PCB traces from simple route json (${this._asyncAutoroutingResult.output_simple_route_json.traces?.length} traces)`
5908
+ );
5494
5909
  this._updatePcbTraceRenderFromSimpleRouteJson();
5495
5910
  return;
5496
5911
  }
5497
5912
  if (this._asyncAutoroutingResult.output_pcb_traces) {
5913
+ debug4(
5914
+ `[${this.getString()}] updating PCB traces from ${this._asyncAutoroutingResult.output_pcb_traces.length} traces`
5915
+ );
5498
5916
  this._updatePcbTraceRenderFromPcbTraces();
5499
5917
  return;
5500
5918
  }
@@ -5503,9 +5921,9 @@ var Group = class extends NormalComponent {
5503
5921
  const { db } = this.root;
5504
5922
  const { traces: routedTraces } = this._asyncAutoroutingResult.output_simple_route_json;
5505
5923
  if (!routedTraces) return;
5506
- const circuitTraces = this.selectAll("trace");
5507
5924
  for (const routedTrace of routedTraces) {
5508
5925
  const pcb_trace = db.pcb_trace.insert({
5926
+ subcircuit_id: this.subcircuit_id,
5509
5927
  route: routedTrace.route
5510
5928
  // source_trace_id: circuitTrace.source_trace_id!,
5511
5929
  });
@@ -5519,6 +5937,22 @@ var Group = class extends NormalComponent {
5519
5937
  pcb_trace.subcircuit_id = this.subcircuit_id;
5520
5938
  db.pcb_trace.insert(pcb_trace);
5521
5939
  }
5940
+ for (const pcb_trace of output_pcb_traces) {
5941
+ for (const point of pcb_trace.route) {
5942
+ if (point.route_type === "via") {
5943
+ db.pcb_via.insert({
5944
+ pcb_trace_id: pcb_trace.pcb_trace_id,
5945
+ x: point.x,
5946
+ y: point.y,
5947
+ hole_diameter: 0.3,
5948
+ outer_diameter: 0.6,
5949
+ layers: [point.from_layer, point.to_layer],
5950
+ from_layer: point.from_layer,
5951
+ to_layer: point.to_layer
5952
+ });
5953
+ }
5954
+ }
5955
+ }
5522
5956
  }
5523
5957
  doInitialSchematicLayout() {
5524
5958
  if (!this.isSubcircuit) return;
@@ -5550,7 +5984,7 @@ var Group = class extends NormalComponent {
5550
5984
  const defaults = {
5551
5985
  serverUrl: "https://registry-api.tscircuit.com",
5552
5986
  serverMode: "job",
5553
- serverCacheEnabled: false
5987
+ serverCacheEnabled: true
5554
5988
  };
5555
5989
  const autorouter = this._parsedProps.autorouter ?? this.getInheritedProperty("autorouter");
5556
5990
  if (typeof autorouter === "object") {
@@ -5562,13 +5996,27 @@ var Group = class extends NormalComponent {
5562
5996
  }
5563
5997
  if (autorouter === "auto-local")
5564
5998
  return {
5565
- local: true
5999
+ local: true,
6000
+ groupMode: "subcircuit"
5566
6001
  };
5567
6002
  if (autorouter === "sequential-trace")
5568
6003
  return {
5569
6004
  local: true,
5570
6005
  groupMode: "sequential-trace"
5571
6006
  };
6007
+ if (autorouter === "subcircuit")
6008
+ return {
6009
+ local: true,
6010
+ groupMode: "subcircuit"
6011
+ };
6012
+ if (autorouter === "auto-cloud")
6013
+ return {
6014
+ local: false,
6015
+ groupMode: "subcircuit",
6016
+ serverUrl: defaults.serverUrl,
6017
+ serverMode: defaults.serverMode,
6018
+ serverCacheEnabled: true
6019
+ };
5572
6020
  return {
5573
6021
  local: true,
5574
6022
  groupMode: "sequential-trace"
@@ -6426,7 +6874,9 @@ var PinHeader = class extends NormalComponent {
6426
6874
  new Port({
6427
6875
  name: `pin${i}`,
6428
6876
  pinNumber: i,
6429
- aliases: []
6877
+ aliases: [this._parsedProps.pinLabels?.[i - 1]].filter(
6878
+ Boolean
6879
+ )
6430
6880
  })
6431
6881
  );
6432
6882
  }
@@ -6747,7 +7197,7 @@ var Switch = class extends NormalComponent {
6747
7197
  };
6748
7198
 
6749
7199
  // lib/RootCircuit.ts
6750
- import { su } from "@tscircuit/soup-util";
7200
+ import { su as su3 } from "@tscircuit/soup-util";
6751
7201
  import { isValidElement as isValidElement2 } from "react";
6752
7202
  import { identity as identity4 } from "transformation-matrix";
6753
7203
  var RootCircuit = class {
@@ -6768,7 +7218,7 @@ var RootCircuit = class {
6768
7218
  _hasRenderedAtleastOnce = false;
6769
7219
  constructor() {
6770
7220
  this.children = [];
6771
- this.db = su([]);
7221
+ this.db = su3([]);
6772
7222
  this.root = this;
6773
7223
  }
6774
7224
  add(componentOrElm) {
@@ -7012,137 +7462,6 @@ var useResistor = createUseComponent(
7012
7462
  resistorPins2
7013
7463
  );
7014
7464
 
7015
- // lib/utils/edit-events/apply-edit-events-to-manual-edits-file.ts
7016
- import "zod";
7017
- import { su as su2 } from "@tscircuit/soup-util";
7018
- var applyEditEventsToManualEditsFile = ({
7019
- circuitJson,
7020
- editEvents,
7021
- manualEditsFile
7022
- }) => {
7023
- const updatedManualEditsFile = {
7024
- ...manualEditsFile,
7025
- schematic_placements: [...manualEditsFile.schematic_placements ?? []]
7026
- };
7027
- for (const editEvent of editEvents) {
7028
- if (editEvent.edit_event_type === "edit_schematic_component_location") {
7029
- const { schematic_component_id, new_center } = editEvent;
7030
- const schematic_component2 = su2(circuitJson).schematic_component.get(
7031
- schematic_component_id
7032
- );
7033
- if (!schematic_component2) continue;
7034
- const source_component = su2(circuitJson).source_component.get(
7035
- schematic_component2.source_component_id
7036
- );
7037
- if (!source_component) continue;
7038
- const existingPlacementIndex = updatedManualEditsFile.schematic_placements?.findIndex(
7039
- (p) => p.selector === source_component.name
7040
- );
7041
- const newPlacement = {
7042
- selector: source_component.name,
7043
- center: new_center,
7044
- relative_to: "group_center"
7045
- };
7046
- if (existingPlacementIndex >= 0) {
7047
- updatedManualEditsFile.schematic_placements[existingPlacementIndex] = newPlacement;
7048
- } else {
7049
- updatedManualEditsFile.schematic_placements.push(newPlacement);
7050
- }
7051
- }
7052
- }
7053
- return updatedManualEditsFile;
7054
- };
7055
-
7056
- // lib/utils/autorouting/getSimpleRouteJsonFromCircuitJson.ts
7057
- import { getObstaclesFromSoup as getObstaclesFromSoup3 } from "@tscircuit/infgrid-ijump-astar";
7058
- import { su as su3 } from "@tscircuit/soup-util";
7059
- import { getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson2 } from "circuit-json-to-connectivity-map";
7060
- var getSimpleRouteJsonFromCircuitJson = ({
7061
- circuitJson,
7062
- minTraceWidth = 0.1
7063
- }) => {
7064
- const db = su3(circuitJson);
7065
- const connMap = getFullConnectivityMapFromCircuitJson2(circuitJson);
7066
- const obstacles = getObstaclesFromSoup3(
7067
- [
7068
- ...db.pcb_component.list(),
7069
- ...db.pcb_smtpad.list(),
7070
- ...db.pcb_plated_hole.list()
7071
- ],
7072
- connMap
7073
- );
7074
- const allPoints = obstacles.flatMap((o) => [
7075
- {
7076
- x: o.center.x - o.width / 2,
7077
- y: o.center.y - o.height / 2
7078
- },
7079
- {
7080
- x: o.center.x + o.width / 2,
7081
- y: o.center.y + o.height / 2
7082
- }
7083
- ]);
7084
- const bounds = {
7085
- minX: Math.min(...allPoints.map((p) => p.x)) - 1,
7086
- maxX: Math.max(...allPoints.map((p) => p.x)) + 1,
7087
- minY: Math.min(...allPoints.map((p) => p.y)) - 1,
7088
- maxY: Math.max(...allPoints.map((p) => p.y)) + 1
7089
- };
7090
- const connections = db.source_trace.list().map((trace) => {
7091
- const connectedPorts = trace.connected_source_port_ids.map((id) => {
7092
- const source_port = db.source_port.get(id);
7093
- const pcb_port = db.pcb_port.getWhere({ source_port_id: id });
7094
- return {
7095
- ...source_port,
7096
- ...pcb_port
7097
- };
7098
- });
7099
- if (connectedPorts.length < 2) return null;
7100
- return {
7101
- name: connMap.getNetConnectedToId(trace.source_trace_id) ?? trace.source_trace_id ?? "",
7102
- source_trace_id: trace.source_trace_id,
7103
- pointsToConnect: connectedPorts.map((port) => {
7104
- return {
7105
- x: port.x,
7106
- y: port.y,
7107
- layer: port.layers?.[0] ?? "top"
7108
- };
7109
- })
7110
- };
7111
- }).filter((c) => c !== null);
7112
- return {
7113
- bounds,
7114
- obstacles,
7115
- connections,
7116
- layerCount: 2,
7117
- minTraceWidth
7118
- };
7119
- };
7120
-
7121
- // lib/utils/render-events/getPhaseTimingsFromRenderEvents.ts
7122
- var getPhaseTimingsFromRenderEvents = (renderEvents) => {
7123
- const phaseTimings = {};
7124
- if (!renderEvents) return phaseTimings;
7125
- for (const renderPhase of orderedRenderPhases) {
7126
- phaseTimings[renderPhase] = 0;
7127
- }
7128
- const startEvents = /* @__PURE__ */ new Map();
7129
- for (const event of renderEvents) {
7130
- const [, , phase, eventType] = event.type.split(":");
7131
- if (eventType === "start") {
7132
- startEvents.set(`${phase}:${event.renderId}`, event);
7133
- continue;
7134
- }
7135
- if (eventType === "end") {
7136
- const startEvent = startEvents.get(`${phase}:${event.renderId}`);
7137
- if (startEvent) {
7138
- const duration = event.createdAt - startEvent.createdAt;
7139
- phaseTimings[phase] = (phaseTimings[phase] || 0) + duration;
7140
- }
7141
- }
7142
- }
7143
- return phaseTimings;
7144
- };
7145
-
7146
7465
  // lib/sel/sel.ts
7147
7466
  var sel = new Proxy(
7148
7467
  {},
@@ -7155,6 +7474,23 @@ var sel = new Proxy(
7155
7474
  if (prop1 === "net") {
7156
7475
  return `net.${prop2}`;
7157
7476
  }
7477
+ if (prop1 === "subcircuit") {
7478
+ return new Proxy(
7479
+ {},
7480
+ {
7481
+ get: (_3, prop3) => {
7482
+ return new Proxy(
7483
+ {},
7484
+ {
7485
+ get: (_4, prop4) => {
7486
+ return `subcircuit.${prop2} > .${prop3} > .${prop4}`;
7487
+ }
7488
+ }
7489
+ );
7490
+ }
7491
+ }
7492
+ );
7493
+ }
7158
7494
  return `.${prop1} > .${prop2}`;
7159
7495
  }
7160
7496
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.330",
4
+ "version": "0.0.332",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -53,12 +53,13 @@
53
53
  },
54
54
  "dependencies": {
55
55
  "@lume/kiwi": "^0.4.3",
56
+ "@tscircuit/capacity-autorouter": "^0.0.12",
56
57
  "@tscircuit/infgrid-ijump-astar": "^0.0.33",
57
58
  "@tscircuit/math-utils": "^0.0.9",
58
59
  "@tscircuit/props": "^0.0.152",
59
60
  "@tscircuit/schematic-autolayout": "^0.0.6",
60
61
  "@tscircuit/soup-util": "^0.0.41",
61
- "circuit-json": "^0.0.142",
62
+ "circuit-json": "^0.0.144",
62
63
  "circuit-json-to-connectivity-map": "^0.0.17",
63
64
  "format-si-unit": "^0.0.3",
64
65
  "nanoid": "^5.0.7",