@tscircuit/core 0.0.257 → 0.0.258

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
@@ -85,6 +85,10 @@ interface SchematicBoxDimensions {
85
85
  width: number;
86
86
  height: number;
87
87
  };
88
+ getSizeIncludingPins(): {
89
+ width: number;
90
+ height: number;
91
+ };
88
92
  }
89
93
 
90
94
  type RootCircuitEventName = "asyncEffect:start" | "asyncEffect:end" | "renderable:renderLifecycle:anyEvent" | `renderable:renderLifecycle:${RenderPhase}:start` | `renderable:renderLifecycle:${RenderPhase}:end` | "external:evalError";
@@ -641,7 +645,8 @@ declare class Trace extends PrimitiveComponent<typeof traceProps> implements Tra
641
645
  doInitialSourceTraceRender(): void;
642
646
  doInitialPcbTraceRender(): void;
643
647
  _doInitialSchematicTraceRenderWithDisplayLabel(): void;
644
- private _isPassiveToChipConnection;
648
+ private _isSymbolToChipConnection;
649
+ private _isSymbolToSymbolConnection;
645
650
  doInitialSchematicTraceRender(): void;
646
651
  }
647
652
 
@@ -1123,6 +1128,7 @@ declare class Board extends Group<typeof boardProps> {
1123
1128
  }[] | undefined;
1124
1129
  }>>;
1125
1130
  schAutoLayoutEnabled: z.ZodOptional<z.ZodBoolean>;
1131
+ schTraceAutoLabelEnabled: z.ZodOptional<z.ZodBoolean>;
1126
1132
  routingDisabled: z.ZodOptional<z.ZodBoolean>;
1127
1133
  defaultTraceWidth: z.ZodOptional<z.ZodEffects<z.ZodUnion<[z.ZodString, z.ZodNumber]>, number, string | number>>;
1128
1134
  minTraceWidth: z.ZodOptional<z.ZodEffects<z.ZodUnion<[z.ZodString, z.ZodNumber]>, number, string | number>>;
@@ -1212,6 +1218,7 @@ declare class Board extends Group<typeof boardProps> {
1212
1218
  cache?: _tscircuit_props.PcbRouteCache | undefined;
1213
1219
  } | undefined;
1214
1220
  schAutoLayoutEnabled?: boolean | undefined;
1221
+ schTraceAutoLabelEnabled?: boolean | undefined;
1215
1222
  partsEngine?: _tscircuit_props.PartsEngine | undefined;
1216
1223
  outline?: {
1217
1224
  x: number;
@@ -1276,6 +1283,7 @@ declare class Board extends Group<typeof boardProps> {
1276
1283
  cache?: _tscircuit_props.PcbRouteCache | undefined;
1277
1284
  } | undefined;
1278
1285
  schAutoLayoutEnabled?: boolean | undefined;
1286
+ schTraceAutoLabelEnabled?: boolean | undefined;
1279
1287
  partsEngine?: _tscircuit_props.PartsEngine | undefined;
1280
1288
  outline?: {
1281
1289
  x: string | number;
package/dist/index.js CHANGED
@@ -53,12 +53,14 @@ __export(components_exports, {
53
53
  // lib/components/base-components/NormalComponent.ts
54
54
  import { fp } from "@tscircuit/footprinter";
55
55
  import { point3, rotation } from "circuit-json";
56
- import Debug3 from "debug";
56
+ import Debug4 from "debug";
57
57
 
58
58
  // lib/fiber/create-instance-from-react-element.ts
59
59
  import ReactReconciler from "react-reconciler";
60
60
 
61
61
  // lib/components/base-components/Renderable.ts
62
+ import Debug from "debug";
63
+ var debug = Debug("tscircuit:renderable");
62
64
  var orderedRenderPhases = [
63
65
  "ReactSubtreesRender",
64
66
  "InitializePortsFromChildren",
@@ -163,6 +165,7 @@ ${error.stack}`
163
165
  });
164
166
  }
165
167
  _emitRenderLifecycleEvent(phase, startOrEnd) {
168
+ debug(`${phase}:${startOrEnd} ${this.getString()}`);
166
169
  const granular_event_type = `renderable:renderLifecycle:${phase}:${startOrEnd}`;
167
170
  const eventPayload = {
168
171
  renderId: this._renderId,
@@ -564,8 +567,8 @@ import {
564
567
  translate
565
568
  } from "transformation-matrix";
566
569
  import { z as z2 } from "zod";
567
- import Debug from "debug";
568
- var debugSelectAll = Debug("tscircuit:primitive-component:selectAll");
570
+ import Debug2 from "debug";
571
+ var debugSelectAll = Debug2("tscircuit:primitive-component:selectAll");
569
572
  var PrimitiveComponent = class extends Renderable {
570
573
  parent = null;
571
574
  children;
@@ -2480,6 +2483,12 @@ var getAllDimensionsForSchematicBox = (params) => {
2480
2483
  getSize() {
2481
2484
  return { width: schWidth, height: schHeight };
2482
2485
  },
2486
+ getSizeIncludingPins() {
2487
+ return {
2488
+ width: schWidth + (sidePinCounts.leftSize || sidePinCounts.rightSize ? 0.4 : 0),
2489
+ height: schHeight + (sidePinCounts.topSize || sidePinCounts.bottomSize ? 0.4 : 0)
2490
+ };
2491
+ },
2483
2492
  pinCount
2484
2493
  };
2485
2494
  };
@@ -2495,8 +2504,8 @@ import { z as z5 } from "zod";
2495
2504
  // lib/components/primitive-components/Footprint.ts
2496
2505
  import { footprintProps } from "@tscircuit/props";
2497
2506
  import * as kiwi from "@lume/kiwi";
2498
- import Debug2 from "debug";
2499
- var debug = Debug2("tscircuit:core:footprint");
2507
+ import Debug3 from "debug";
2508
+ var debug2 = Debug3("tscircuit:core:footprint");
2500
2509
  var Footprint = class extends PrimitiveComponent {
2501
2510
  get config() {
2502
2511
  return {
@@ -2654,7 +2663,7 @@ var Footprint = class extends PrimitiveComponent {
2654
2663
  }
2655
2664
  }
2656
2665
  solver.updateVariables();
2657
- if (debug.enabled) {
2666
+ if (debug2.enabled) {
2658
2667
  console.log("Solution to layout constraints:");
2659
2668
  console.table(
2660
2669
  Object.entries(kVars).map(([key, kvar]) => ({
@@ -2717,7 +2726,7 @@ var getNumericSchPinStyle = (pinStyles, pinLabels) => {
2717
2726
  };
2718
2727
 
2719
2728
  // lib/components/base-components/NormalComponent.ts
2720
- var debug2 = Debug3("tscircuit:core");
2729
+ var debug3 = Debug4("tscircuit:core");
2721
2730
  var rotation3 = z5.object({
2722
2731
  x: rotation,
2723
2732
  y: rotation,
@@ -3010,6 +3019,10 @@ var NormalComponent = class extends PrimitiveComponent {
3010
3019
  center,
3011
3020
  rotation: props.schRotation ?? 0,
3012
3021
  size: dimensions.getSize(),
3022
+ // We should be using the full size, but circuit-to-svg incorrectly
3023
+ // uses the schematic_component size to draw boxes instead of the
3024
+ // schematic_box size
3025
+ // size: dimensions.getSizeIncludingPins(),
3013
3026
  port_arrangement: underscorifyPortArrangement(
3014
3027
  props.schPortArrangement
3015
3028
  ),
@@ -3145,7 +3158,7 @@ var NormalComponent = class extends PrimitiveComponent {
3145
3158
  (p) => p.isMatchingAnyOf(component.getNameAndAliases())
3146
3159
  );
3147
3160
  if (conflictingPort) {
3148
- debug2(
3161
+ debug3(
3149
3162
  `Similar ports added. Port 1: ${conflictingPort}, Port 2: ${component}`
3150
3163
  );
3151
3164
  }
@@ -3536,7 +3549,7 @@ var getSimpleRouteJsonFromTracesAndDb = ({
3536
3549
  };
3537
3550
 
3538
3551
  // lib/components/primitive-components/Group/Group.ts
3539
- import Debug4 from "debug";
3552
+ import Debug5 from "debug";
3540
3553
  var Group = class extends NormalComponent {
3541
3554
  _asyncAutoroutingResult = null;
3542
3555
  get config() {
@@ -3604,9 +3617,9 @@ var Group = class extends NormalComponent {
3604
3617
  if (this._shouldUseTraceByTraceRouting()) return;
3605
3618
  const serverUrl = this.props.autorouter?.serverUrl ?? "https://registry-api.tscircuit.com";
3606
3619
  const serverMode = this.props.autorouter?.serverMode ?? "job";
3607
- const debug3 = Debug4("tscircuit:core:autorouting");
3620
+ const debug4 = Debug5("tscircuit:core:autorouting");
3608
3621
  const fetchWithDebug = (url, options) => {
3609
- debug3("fetching", url);
3622
+ debug4("fetching", url);
3610
3623
  return fetch(url, options);
3611
3624
  };
3612
3625
  this._queueAsyncEffect("make-http-autorouting-request", async () => {
@@ -4476,28 +4489,44 @@ function getTraceDisplayName({
4476
4489
  }
4477
4490
 
4478
4491
  // lib/components/primitive-components/Trace/get-obstacles-for-trace.ts
4479
- import "@tscircuit/math-utils";
4492
+ import { getUnitVectorFromDirection } from "@tscircuit/math-utils";
4480
4493
  var getSchematicObstaclesForTrace = (trace) => {
4481
4494
  const db = trace.root.db;
4495
+ const connectedPorts = trace._findConnectedPorts().ports ?? [];
4496
+ const connectedPortIds = new Set(
4497
+ connectedPorts.map((p) => p.schematic_port_id)
4498
+ );
4482
4499
  const obstacles = [];
4483
4500
  for (const elm of db.toArray()) {
4484
4501
  if (elm.type === "schematic_component") {
4502
+ const isSymbol = Boolean(elm.symbol_name);
4503
+ const dominateAxis = elm.size.width > elm.size.height ? "horz" : "vert";
4485
4504
  obstacles.push({
4486
4505
  type: "rect",
4487
4506
  layers: ["top"],
4488
4507
  center: elm.center,
4489
- width: elm.size.width,
4490
- height: elm.size.height,
4508
+ width: elm.size.width + (isSymbol && dominateAxis === "horz" ? -0.5 : 0),
4509
+ height: elm.size.height + (isSymbol && dominateAxis === "vert" ? -0.5 : 0),
4491
4510
  connectedTo: []
4492
4511
  });
4493
4512
  }
4494
4513
  if (elm.type === "schematic_port") {
4514
+ if (connectedPortIds.has(elm.schematic_port_id)) {
4515
+ continue;
4516
+ }
4517
+ const dirVec = elm.facing_direction ? getUnitVectorFromDirection(elm.facing_direction) : {
4518
+ x: 0,
4519
+ y: 0
4520
+ };
4495
4521
  obstacles.push({
4496
4522
  type: "rect",
4497
4523
  layers: ["top"],
4498
- center: elm.center,
4499
- width: 0.1,
4500
- height: 0.1,
4524
+ center: {
4525
+ x: elm.center.x - dirVec.x * 0.1,
4526
+ y: elm.center.y - dirVec.y * 0.1
4527
+ },
4528
+ width: 0.1 + Math.abs(dirVec.x) * 0.3,
4529
+ height: 0.1 + Math.abs(dirVec.y) * 0.3,
4501
4530
  connectedTo: []
4502
4531
  });
4503
4532
  }
@@ -4521,25 +4550,6 @@ var getSchematicObstaclesForTrace = (trace) => {
4521
4550
  connectedTo: []
4522
4551
  });
4523
4552
  }
4524
- if (elm.type === "schematic_net_label" && elm.symbol_name) {
4525
- obstacles.push({
4526
- type: "rect",
4527
- layers: ["top"],
4528
- center: elm.center,
4529
- width: 0.25,
4530
- height: 0.6,
4531
- connectedTo: []
4532
- });
4533
- } else if (elm.type === "schematic_net_label") {
4534
- obstacles.push({
4535
- type: "rect",
4536
- layers: ["top"],
4537
- center: elm.center,
4538
- width: (elm.text?.length ?? 0) * 0.1,
4539
- height: 0.2,
4540
- connectedTo: []
4541
- });
4542
- }
4543
4553
  }
4544
4554
  return obstacles;
4545
4555
  };
@@ -5015,12 +5025,16 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
5015
5025
  }
5016
5026
  const existingFromNetLabel = db.schematic_net_label.list().find((label) => label.source_net_id === fromPort.source_port_id);
5017
5027
  const existingToNetLabel = db.schematic_net_label.list().find((label) => label.source_net_id === toPort.source_port_id);
5018
- if (existingFromNetLabel && existingFromNetLabel.text !== this.props.schDisplayLabel || existingToNetLabel && existingToNetLabel?.text !== this.props.schDisplayLabel) {
5028
+ const [firstPort, secondPort] = connectedPorts.map(({ port }) => port);
5029
+ const isFirstPortSchematicBox = firstPort.parent?.config.shouldRenderAsSchematicBox;
5030
+ const pinFullName = isFirstPortSchematicBox ? `${firstPort?.parent?.props.name}_${firstPort?.props.name}` : `${secondPort?.parent?.props.name}_${secondPort?.props.name}`;
5031
+ const netLabelText = this.props.schDisplayLabel ?? pinFullName;
5032
+ if (existingFromNetLabel && existingFromNetLabel.text !== netLabelText || existingToNetLabel && existingToNetLabel?.text !== netLabelText) {
5019
5033
  throw new Error(
5020
- `Cannot create net label for port ${existingFromNetLabel ? fromPortName : toPortName} because it already has a net label with text "${existingFromNetLabel ? existingFromNetLabel.text : existingToNetLabel?.text}".`
5034
+ `Cannot create net label "${netLabelText}" for port ${existingFromNetLabel ? fromPortName : toPortName} because it already has a net label with text "${existingFromNetLabel ? existingFromNetLabel.text : existingToNetLabel?.text}".`
5021
5035
  );
5022
5036
  }
5023
- if (this.props.schDisplayLabel?.toLocaleLowerCase().includes("gnd") || this.props.schDisplayLabel?.toLocaleLowerCase().includes("ground")) {
5037
+ if (netLabelText?.toLocaleLowerCase().includes("gnd") || netLabelText?.toLocaleLowerCase().includes("ground")) {
5024
5038
  createDownwardNetLabelGroundSymbol(
5025
5039
  {
5026
5040
  fromPort,
@@ -5034,9 +5048,6 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
5034
5048
  );
5035
5049
  return;
5036
5050
  }
5037
- const [firstPort, secondPort] = connectedPorts.map(({ port }) => port);
5038
- const isFirstPortSchematicBox = firstPort.parent?.config.shouldRenderAsSchematicBox;
5039
- const pinFullName = isFirstPortSchematicBox ? `${firstPort?.parent?.props.name}_${firstPort?.props.name}` : `${secondPort?.parent?.props.name}_${secondPort?.props.name}`;
5040
5051
  db.schematic_net_label.insert({
5041
5052
  text: this.props.schDisplayLabel ?? pinFullName,
5042
5053
  source_net_id: toPort.source_port_id,
@@ -5052,7 +5063,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
5052
5063
  anchor_side: getEnteringEdgeFromDirection(fromPort.facingDirection) ?? "bottom"
5053
5064
  });
5054
5065
  }
5055
- _isPassiveToChipConnection() {
5066
+ _isSymbolToChipConnection() {
5056
5067
  const { allPortsFound, ports } = this._findConnectedPorts();
5057
5068
  if (!allPortsFound || ports.length !== 2) return false;
5058
5069
  const [port1, port2] = ports;
@@ -5061,6 +5072,15 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
5061
5072
  const isPort2Chip = port2.parent.config.shouldRenderAsSchematicBox;
5062
5073
  return isPort1Chip && !isPort2Chip || !isPort1Chip && isPort2Chip;
5063
5074
  }
5075
+ _isSymbolToSymbolConnection() {
5076
+ const { allPortsFound, ports } = this._findConnectedPorts();
5077
+ if (!allPortsFound || ports.length !== 2) return false;
5078
+ const [port1, port2] = ports;
5079
+ if (!port1?.parent || !port2?.parent) return false;
5080
+ const isPort1Symbol = !port1.parent.config.shouldRenderAsSchematicBox;
5081
+ const isPort2Symbol = !port2.parent.config.shouldRenderAsSchematicBox;
5082
+ return isPort1Symbol && isPort2Symbol;
5083
+ }
5064
5084
  doInitialSchematicTraceRender() {
5065
5085
  if (this.root?.schematicDisabled) return;
5066
5086
  const { db } = this.root;
@@ -5106,7 +5126,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
5106
5126
  layer: "top"
5107
5127
  }));
5108
5128
  const bounds = computeObstacleBounds(obstacles);
5109
- const BOUNDS_MARGIN = 1;
5129
+ const BOUNDS_MARGIN = 2;
5110
5130
  const simpleRouteJsonInput = {
5111
5131
  minTraceWidth: 0.1,
5112
5132
  obstacles,
@@ -5120,17 +5140,52 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
5120
5140
  layerCount: 1
5121
5141
  };
5122
5142
  let Autorouter = MultilayerIjump;
5143
+ let skipOtherTraceInteraction = false;
5123
5144
  if (this.getSubcircuit().props._schDirectLineRoutingEnabled) {
5124
5145
  Autorouter = DirectLineRouter;
5146
+ skipOtherTraceInteraction = true;
5125
5147
  }
5126
5148
  const autorouter = new Autorouter({
5127
5149
  input: simpleRouteJsonInput,
5150
+ MAX_ITERATIONS: 100,
5128
5151
  OBSTACLE_MARGIN: 0.1,
5129
5152
  isRemovePathLoopsEnabled: true,
5130
- isShortenPathWithShortcutsEnabled: false
5153
+ isShortenPathWithShortcutsEnabled: true,
5154
+ marginsWithCosts: [
5155
+ {
5156
+ margin: 1,
5157
+ enterCost: 0,
5158
+ travelCostFactor: 1
5159
+ },
5160
+ {
5161
+ margin: 0.3,
5162
+ enterCost: 0,
5163
+ travelCostFactor: 1
5164
+ },
5165
+ {
5166
+ margin: 0.2,
5167
+ enterCost: 0,
5168
+ travelCostFactor: 2
5169
+ },
5170
+ {
5171
+ margin: 0.1,
5172
+ enterCost: 0,
5173
+ travelCostFactor: 3
5174
+ }
5175
+ ]
5131
5176
  });
5132
- const results = autorouter.solveAndMapToTraces();
5133
- if (results.length === 0) return;
5177
+ let results = autorouter.solveAndMapToTraces();
5178
+ if (results.length === 0) {
5179
+ if (this._isSymbolToChipConnection() || this._isSymbolToSymbolConnection()) {
5180
+ this._doInitialSchematicTraceRenderWithDisplayLabel();
5181
+ return;
5182
+ }
5183
+ const directLineRouter = new DirectLineRouter({
5184
+ input: simpleRouteJsonInput
5185
+ });
5186
+ results = directLineRouter.solveAndMapToTraces();
5187
+ skipOtherTraceInteraction = true;
5188
+ }
5134
5189
  const [{ route }] = results;
5135
5190
  const edges = [];
5136
5191
  for (let i = 0; i < route.length - 1; i++) {
@@ -5140,13 +5195,16 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
5140
5195
  });
5141
5196
  }
5142
5197
  const source_trace_id = this.source_trace_id;
5143
- pushEdgesOfSchematicTraceToPreventOverlap({ edges, db, source_trace_id });
5144
- createSchematicTraceCrossingSegments({ edges, db, source_trace_id });
5145
- const junctions = createSchematicTraceJunctions({
5146
- edges,
5147
- db,
5148
- source_trace_id: this.source_trace_id
5149
- });
5198
+ let junctions = [];
5199
+ if (!skipOtherTraceInteraction) {
5200
+ pushEdgesOfSchematicTraceToPreventOverlap({ edges, db, source_trace_id });
5201
+ createSchematicTraceCrossingSegments({ edges, db, source_trace_id });
5202
+ junctions = createSchematicTraceJunctions({
5203
+ edges,
5204
+ db,
5205
+ source_trace_id: this.source_trace_id
5206
+ });
5207
+ }
5150
5208
  const lastEdge = edges[edges.length - 1];
5151
5209
  const lastEdgePort = portsWithPosition[portsWithPosition.length - 1];
5152
5210
  const lastDominantDirection = getDominantDirection(lastEdge);
@@ -5166,17 +5224,16 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
5166
5224
  if (!this.source_trace_id) {
5167
5225
  throw new Error("Missing source_trace_id for schematic trace insertion.");
5168
5226
  }
5169
- if (countComplexElements(junctions, edges) >= 5 && this._isPassiveToChipConnection()) {
5227
+ if (this.getSubcircuit()._parsedProps.schTraceAutoLabelEnabled && countComplexElements(junctions, edges) >= 5 && (this._isSymbolToChipConnection() || this._isSymbolToSymbolConnection())) {
5170
5228
  this._doInitialSchematicTraceRenderWithDisplayLabel();
5171
- db.schematic_trace.delete(this.schematic_trace_id);
5172
- } else {
5173
- const trace = db.schematic_trace.insert({
5174
- source_trace_id: this.source_trace_id,
5175
- edges,
5176
- junctions
5177
- });
5178
- this.schematic_trace_id = trace.schematic_trace_id;
5229
+ return;
5179
5230
  }
5231
+ const trace = db.schematic_trace.insert({
5232
+ source_trace_id: this.source_trace_id,
5233
+ edges,
5234
+ junctions
5235
+ });
5236
+ this.schematic_trace_id = trace.schematic_trace_id;
5180
5237
  }
5181
5238
  };
5182
5239
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.257",
4
+ "version": "0.0.258",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -27,7 +27,7 @@
27
27
  "@types/react": "^19.0.1",
28
28
  "@types/react-reconciler": "^0.28.8",
29
29
  "bun-match-svg": "0.0.8",
30
- "circuit-to-svg": "^0.0.97",
30
+ "circuit-to-svg": "^0.0.99",
31
31
  "debug": "^4.3.6",
32
32
  "graphics-debug": "^0.0.4",
33
33
  "howfat": "^0.3.8",
@@ -42,9 +42,9 @@
42
42
  "dependencies": {
43
43
  "@lume/kiwi": "^0.4.3",
44
44
  "@tscircuit/footprinter": "^0.0.97",
45
- "@tscircuit/infgrid-ijump-astar": "^0.0.27",
45
+ "@tscircuit/infgrid-ijump-astar": "^0.0.33",
46
46
  "@tscircuit/math-utils": "^0.0.5",
47
- "@tscircuit/props": "^0.0.128",
47
+ "@tscircuit/props": "^0.0.129",
48
48
  "@tscircuit/schematic-autolayout": "^0.0.6",
49
49
  "@tscircuit/soup-util": "^0.0.41",
50
50
  "circuit-json": "^0.0.128",
@@ -54,7 +54,7 @@
54
54
  "performance-now": "^2.1.0",
55
55
  "react": "^18.3.1",
56
56
  "react-reconciler": "^0.29.2",
57
- "schematic-symbols": "^0.0.111",
57
+ "schematic-symbols": "^0.0.113",
58
58
  "transformation-matrix": "^2.16.1",
59
59
  "zod": "^3.23.8"
60
60
  }