@tscircuit/core 0.0.229 → 0.0.231

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 CHANGED
@@ -2,14 +2,38 @@
2
2
 
3
3
  [tscircuit](https://github.com/tscircuit/tscircuit) · [Development Guide](./docs/DEVELOPMENT.md)
4
4
 
5
- A rewrite of [tscircuit builder](https://github.com/tscircuit/builder) with a ThreeJS/react-three-like API and architecture.
5
+ The core logic used to build Circuit JSON from tscircuit React elements.
6
+
7
+ You can use `core` to create [Circuit JSON](https://github.com/tscircuit/circuit-json), which can then
8
+ be converted into Gerbers, viewed online, and much more.
6
9
 
7
10
  ## Usage
8
11
 
9
12
  ```tsx
10
- import { Board, Resistor, Led, Trace, Project } from "@tscircuit/core"
13
+ import { Circuit } from "@tscircuit/core"
14
+
15
+ const circuit = new Circuit()
16
+
17
+ circuit.add(
18
+ <board width="10mm" height="10mm">
19
+ <resistor name="R1" resistance="10k" footprint="0402" />
20
+ <led name="L1" footprint="0402" />
21
+
22
+ <trace from=".R1 > .pin1" to="net.VCC" />
23
+ <trace from=".R1 > .pin2" to=".L1 > .pos" />
24
+ <trace from=".L1 > .neg" to="net.GND" />
25
+ </board>
26
+ )
27
+
28
+ circuit.getCircuitJson()
29
+ ```
30
+
31
+ ## Non-React Usage
32
+
33
+ ```tsx
34
+ import { Board, Resistor, Led, Trace, Circuit } from "@tscircuit/core"
11
35
 
12
- const project = new Project()
36
+ const circuit = new Circuit()
13
37
 
14
38
  const board = new Board({
15
39
  width: "10mm",
@@ -27,5 +51,5 @@ const trace = new Trace({ width: "0.2mm" })
27
51
  trace.connect(R1.output, LED1.anode)
28
52
  board.add(trace)
29
53
 
30
- project.getJson() // [{ type: "board", ...}, { type: "resistor", ...}, ...]
54
+ circuit.getJson() // [{ type: "board", ...}, { type: "resistor", ...}, ...]
31
55
  ```
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import * as _tscircuit_props from '@tscircuit/props';
2
- import { subcircuitGroupProps, 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, smtPadProps, traceHintProps, viaProps, batteryProps, pinHeaderProps, inductorProps, potentiometerProps, pushButtonProps, crystalProps, CapacitorProps, ChipProps, ResistorProps } from '@tscircuit/props';
2
+ import { subcircuitGroupProps, 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, inductorProps, potentiometerProps, pushButtonProps, crystalProps, CapacitorProps, ChipProps, ResistorProps, ManualEditEvent, manual_edit_file } from '@tscircuit/props';
3
3
  import React, { ReactElement } from 'react';
4
4
  import * as zod from 'zod';
5
5
  import { z, ZodType } from 'zod';
6
6
  import { symbols, SchSymbol, BaseSymbolName } from 'schematic-symbols';
7
- import { PcbTraceError, PcbPlacementError, LayerRef, AnyCircuitElement, AnySourceComponent, PcbTrace, RouteHintPoint } from 'circuit-json';
7
+ import { PcbTraceError, PcbPlacementError, PcbManualEditConflictError, LayerRef, AnyCircuitElement, AnySourceComponent, PcbTrace, RouteHintPoint, CircuitJson } from 'circuit-json';
8
8
  import { Matrix } from 'transformation-matrix';
9
9
  import { SoupUtilObjects } from '@tscircuit/soup-util';
10
10
  import * as _tscircuit_layout from '@tscircuit/layout';
@@ -56,7 +56,7 @@ declare abstract class Renderable implements IRenderable {
56
56
  */
57
57
  runRenderPhase(phase: RenderPhase): void;
58
58
  runRenderPhaseForChildren(phase: RenderPhase): void;
59
- renderError(message: string | Omit<PcbTraceError, "pcb_error_id"> | Omit<PcbPlacementError, "pcb_error_id">): void;
59
+ renderError(message: string | Omit<PcbTraceError, "pcb_error_id"> | Omit<PcbPlacementError, "pcb_error_id"> | Omit<PcbManualEditConflictError, "pcb_error_id">): void;
60
60
  }
61
61
 
62
62
  type ReactSubtree = {
@@ -81,7 +81,7 @@ interface SchematicBoxDimensions {
81
81
  };
82
82
  }
83
83
 
84
- type RootCircuitEventName = "asyncEffectComplete" | "renderable:renderLifecycle:anyEvent" | `renderable:renderLifecycle:${RenderPhase}:start` | `renderable:renderLifecycle:${RenderPhase}:end`;
84
+ type RootCircuitEventName = "asyncEffectComplete" | "renderable:renderLifecycle:anyEvent" | `renderable:renderLifecycle:${RenderPhase}:start` | `renderable:renderLifecycle:${RenderPhase}:end` | "external:evalError";
85
85
  declare class Circuit {
86
86
  firstChild: PrimitiveComponent | null;
87
87
  children: PrimitiveComponent[];
@@ -5123,6 +5123,50 @@ declare class SilkscreenText extends PrimitiveComponent<typeof silkscreenTextPro
5123
5123
  };
5124
5124
  }
5125
5125
 
5126
+ declare class SilkscreenLine extends PrimitiveComponent<typeof silkscreenLineProps> {
5127
+ pcb_silkscreen_line_id: string | null;
5128
+ get config(): {
5129
+ componentName: string;
5130
+ zodProps: zod.ZodObject<zod.objectUtil.extendShape<Omit<{
5131
+ pcbX: zod.ZodOptional<zod.ZodEffects<zod.ZodUnion<[zod.ZodString, zod.ZodNumber]>, number, string | number>>;
5132
+ pcbY: zod.ZodOptional<zod.ZodEffects<zod.ZodUnion<[zod.ZodString, zod.ZodNumber]>, number, string | number>>;
5133
+ pcbRotation: zod.ZodOptional<zod.ZodEffects<zod.ZodUnion<[zod.ZodString, zod.ZodNumber]>, number, string | number>>;
5134
+ layer: zod.ZodOptional<zod.ZodEffects<zod.ZodUnion<[zod.ZodEnum<["top", "bottom", "inner1", "inner2", "inner3", "inner4", "inner5", "inner6"]>, zod.ZodObject<{
5135
+ name: zod.ZodEnum<["top", "bottom", "inner1", "inner2", "inner3", "inner4", "inner5", "inner6"]>;
5136
+ }, "strip", zod.ZodTypeAny, {
5137
+ name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6";
5138
+ }, {
5139
+ name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6";
5140
+ }>]>, "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6", "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | {
5141
+ name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6";
5142
+ }>>;
5143
+ }, "pcbX" | "pcbY" | "pcbRotation">, {
5144
+ strokeWidth: zod.ZodEffects<zod.ZodUnion<[zod.ZodString, zod.ZodNumber]>, number, string | number>;
5145
+ x1: zod.ZodEffects<zod.ZodUnion<[zod.ZodString, zod.ZodNumber]>, number, string | number>;
5146
+ y1: zod.ZodEffects<zod.ZodUnion<[zod.ZodString, zod.ZodNumber]>, number, string | number>;
5147
+ x2: zod.ZodEffects<zod.ZodUnion<[zod.ZodString, zod.ZodNumber]>, number, string | number>;
5148
+ y2: zod.ZodEffects<zod.ZodUnion<[zod.ZodString, zod.ZodNumber]>, number, string | number>;
5149
+ }>, "strip", zod.ZodTypeAny, {
5150
+ x1: number;
5151
+ y1: number;
5152
+ x2: number;
5153
+ y2: number;
5154
+ strokeWidth: number;
5155
+ layer?: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | undefined;
5156
+ }, {
5157
+ x1: string | number;
5158
+ y1: string | number;
5159
+ x2: string | number;
5160
+ y2: string | number;
5161
+ strokeWidth: string | number;
5162
+ layer?: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | {
5163
+ name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6";
5164
+ } | undefined;
5165
+ }>;
5166
+ };
5167
+ doInitialPcbPrimitiveRender(): void;
5168
+ }
5169
+
5126
5170
  declare class SmtPad extends PrimitiveComponent<typeof smtPadProps> {
5127
5171
  pcb_smtpad_id: string | null;
5128
5172
  matchedPort: Port | null;
@@ -7877,6 +7921,7 @@ declare class Crystal extends NormalComponent<typeof crystalProps, PolarizedPass
7877
7921
  }>, {
7878
7922
  frequency: zod.ZodEffects<zod.ZodUnion<[zod.ZodString, zod.ZodNumber]>, number, string | number>;
7879
7923
  loadCapacitance: zod.ZodEffects<zod.ZodUnion<[zod.ZodString, zod.ZodNumber]>, number, string | number>;
7924
+ pinVariant: zod.ZodOptional<zod.ZodEnum<["2pin", "4pin"]>>;
7880
7925
  }>, "strip", zod.ZodTypeAny, {
7881
7926
  name: string;
7882
7927
  frequency: number;
@@ -7946,6 +7991,7 @@ declare class Crystal extends NormalComponent<typeof crystalProps, PolarizedPass
7946
7991
  } | undefined;
7947
7992
  children?: any;
7948
7993
  symbolName?: string | undefined;
7994
+ pinVariant?: "2pin" | "4pin" | undefined;
7949
7995
  }, {
7950
7996
  name: string;
7951
7997
  frequency: string | number;
@@ -8017,6 +8063,7 @@ declare class Crystal extends NormalComponent<typeof crystalProps, PolarizedPass
8017
8063
  } | undefined;
8018
8064
  children?: any;
8019
8065
  symbolName?: string | undefined;
8066
+ pinVariant?: "2pin" | "4pin" | undefined;
8020
8067
  }>;
8021
8068
  sourceFtype: Ftype;
8022
8069
  };
@@ -8330,6 +8377,12 @@ declare const useLed: <PropsFromHook extends Omit<{
8330
8377
 
8331
8378
  declare const useResistor: <PropsFromHook extends Omit<ResistorProps, "name"> | undefined = undefined>(name: string, props?: PropsFromHook | undefined) => ComponentWithPins<ResistorProps, "left" | "right" | "pin1" | "pin2", PropsFromHook>;
8332
8379
 
8380
+ declare const applyEditEventsToManualEditsFile: ({ circuitJson, editEvents, manualEditsFile, }: {
8381
+ circuitJson: CircuitJson;
8382
+ editEvents: ManualEditEvent[];
8383
+ manualEditsFile: z.infer<typeof manual_edit_file>;
8384
+ }) => z.infer<typeof manual_edit_file>;
8385
+
8333
8386
  interface TscircuitElements {
8334
8387
  resistor: _tscircuit_props.ResistorProps;
8335
8388
  capacitor: _tscircuit_props.CapacitorProps;
@@ -8389,4 +8442,4 @@ declare module "react/jsx-runtime" {
8389
8442
  }
8390
8443
  }
8391
8444
 
8392
- export { Battery, Board, Capacitor, Chip, Circuit, type ComponentWithPins, Constraint, Crystal, Diode, FabricationNotePath, FabricationNoteText, Footprint, Group, Hole, type IRenderable, Inductor, Jumper, Keepout, Led, Net, NetAlias, NormalComponent, PinHeader, type PinLabelSpec, PlatedHole, Port, Potentiometer, PowerSource, PrimitiveComponent, Project, PushButton, Renderable, Resistor, SilkscreenCircle, SilkscreenPath, SilkscreenRect, SilkscreenText, SmtPad, Subcircuit, Trace, TraceHint, Via, createUseComponent, useCapacitor, useChip, useDiode, useLed, useRenderedCircuit, useResistor };
8445
+ export { Battery, Board, Capacitor, Chip, Circuit, type ComponentWithPins, Constraint, Crystal, Diode, FabricationNotePath, FabricationNoteText, Footprint, Group, Hole, type IRenderable, Inductor, Jumper, Keepout, Led, Net, NetAlias, NormalComponent, PinHeader, type PinLabelSpec, PlatedHole, Port, Potentiometer, PowerSource, PrimitiveComponent, Project, PushButton, Renderable, Resistor, SilkscreenCircle, SilkscreenLine, SilkscreenPath, SilkscreenRect, SilkscreenText, SmtPad, Subcircuit, Trace, TraceHint, Via, applyEditEventsToManualEditsFile, createUseComponent, useCapacitor, useChip, useDiode, useLed, useRenderedCircuit, useResistor };
package/dist/index.js CHANGED
@@ -36,6 +36,7 @@ __export(components_exports, {
36
36
  Renderable: () => Renderable,
37
37
  Resistor: () => Resistor,
38
38
  SilkscreenCircle: () => SilkscreenCircle,
39
+ SilkscreenLine: () => SilkscreenLine,
39
40
  SilkscreenPath: () => SilkscreenPath,
40
41
  SilkscreenRect: () => SilkscreenRect,
41
42
  SilkscreenText: () => SilkscreenText,
@@ -2957,6 +2958,15 @@ var NormalComponent = class extends PrimitiveComponent {
2957
2958
  this.pcb_missing_footprint_error_id = footprint_error.pcb_missing_footprint_error_id;
2958
2959
  }
2959
2960
  this.pcb_component_id = pcb_component.pcb_component_id;
2961
+ const manualPlacement = this.getSubcircuit()._getManualPlacementForComponent(this);
2962
+ if (this.props.pcbX !== void 0 && this.props.pcbY !== void 0 && manualPlacement) {
2963
+ this.renderError({
2964
+ type: "pcb_manual_edit_conflict_error",
2965
+ message: `${this.getString()} has both manual placement and explicit coordinates. pcbX and pcbY will be used. Remove pcbX/pcbY or clear the manual placement.`,
2966
+ pcb_component_id: this.pcb_component_id,
2967
+ source_component_id: this.source_component_id
2968
+ });
2969
+ }
2960
2970
  }
2961
2971
  /**
2962
2972
  * At this stage, the smtpads/pcb primitives are placed, so we can compute
@@ -3710,6 +3720,7 @@ import {
3710
3720
  getObstaclesFromSoup as getObstaclesFromSoup3
3711
3721
  } from "@tscircuit/infgrid-ijump-astar";
3712
3722
  import { traceProps } from "@tscircuit/props";
3723
+ import "circuit-json";
3713
3724
  import { getFullConnectivityMapFromCircuitJson } from "circuit-json-to-connectivity-map";
3714
3725
 
3715
3726
  // lib/utils/autorouting/DirectLineRouter.ts
@@ -4182,6 +4193,118 @@ var countComplexElements = (junctions, edges) => {
4182
4193
  return count;
4183
4194
  };
4184
4195
 
4196
+ // lib/components/primitive-components/Trace/create-downward-net-label-ground-symbol.ts
4197
+ var calculateOffsets = (port) => {
4198
+ const schBoxOffset = {
4199
+ left: { x: -0.5, y: 0 },
4200
+ up: { x: 0.5, y: 0.5 },
4201
+ right: { x: 0.5, y: 0 },
4202
+ down: { x: 0, y: -0.5 }
4203
+ }[port.facingDirection];
4204
+ const schBoxVertOffset = port.parent?.config.shouldRenderAsSchematicBox ? 3 : 1;
4205
+ const schBoxHorzOffset = port.parent?.config.shouldRenderAsSchematicBox && (port.facingDirection === "left" || port.facingDirection === "right") ? 3 : 1;
4206
+ const horzPortDirection = schBoxOffset.x;
4207
+ const vertPortDirectionOffset = schBoxOffset.y;
4208
+ const handleUp = port.facingDirection === "up" ? 0.5 : 0;
4209
+ return {
4210
+ schBoxVertOffset,
4211
+ schBoxHorzOffset,
4212
+ horzPortDirection,
4213
+ vertPortDirectionOffset,
4214
+ handleUp
4215
+ };
4216
+ };
4217
+ var createDownwardNetLabelGroundSymbol = ({
4218
+ fromPort,
4219
+ toPort,
4220
+ fromAnchorPos,
4221
+ toAnchorPos,
4222
+ schDisplayLabel,
4223
+ source_trace_id
4224
+ }, { db }) => {
4225
+ const fromOffsets = calculateOffsets(fromPort);
4226
+ db.schematic_net_label.insert({
4227
+ anchor_side: "top",
4228
+ center: {
4229
+ x: fromAnchorPos.x + fromOffsets.horzPortDirection * fromOffsets.schBoxHorzOffset,
4230
+ y: fromAnchorPos.y + fromOffsets.vertPortDirectionOffset * fromOffsets.schBoxVertOffset
4231
+ },
4232
+ source_net_id: fromPort.source_port_id,
4233
+ text: schDisplayLabel,
4234
+ anchor_position: {
4235
+ x: fromAnchorPos.x + fromOffsets.horzPortDirection * fromOffsets.schBoxHorzOffset,
4236
+ y: fromAnchorPos.y + fromOffsets.vertPortDirectionOffset * fromOffsets.schBoxVertOffset
4237
+ },
4238
+ symbol_name: "ground_horz"
4239
+ });
4240
+ db.schematic_trace.insert({
4241
+ edges: [
4242
+ {
4243
+ from: { x: fromAnchorPos.x, y: fromAnchorPos.y },
4244
+ to: {
4245
+ x: fromAnchorPos.x,
4246
+ y: fromAnchorPos.y + fromOffsets.handleUp * fromOffsets.schBoxVertOffset
4247
+ }
4248
+ },
4249
+ {
4250
+ from: { x: fromAnchorPos.x, y: fromAnchorPos.y },
4251
+ to: {
4252
+ x: fromAnchorPos.x + fromOffsets.horzPortDirection * fromOffsets.schBoxHorzOffset,
4253
+ y: fromAnchorPos.y + fromOffsets.vertPortDirectionOffset * fromOffsets.schBoxVertOffset
4254
+ }
4255
+ }
4256
+ ],
4257
+ junctions: [
4258
+ {
4259
+ x: fromAnchorPos.x + fromOffsets.horzPortDirection * fromOffsets.schBoxHorzOffset,
4260
+ y: fromAnchorPos.y + fromOffsets.vertPortDirectionOffset * fromOffsets.schBoxVertOffset
4261
+ }
4262
+ ],
4263
+ source_trace_id
4264
+ });
4265
+ const toOffsets = calculateOffsets(toPort);
4266
+ db.schematic_net_label.insert({
4267
+ anchor_side: "top",
4268
+ center: {
4269
+ x: toAnchorPos.x + toOffsets.horzPortDirection * toOffsets.schBoxHorzOffset,
4270
+ y: toAnchorPos.y + toOffsets.vertPortDirectionOffset * toOffsets.schBoxVertOffset
4271
+ },
4272
+ source_net_id: toPort.source_port_id,
4273
+ text: schDisplayLabel,
4274
+ anchor_position: {
4275
+ x: toAnchorPos.x + toOffsets.horzPortDirection * toOffsets.schBoxHorzOffset,
4276
+ y: toAnchorPos.y + toOffsets.vertPortDirectionOffset * toOffsets.schBoxVertOffset
4277
+ },
4278
+ symbol_name: "ground_horz"
4279
+ });
4280
+ const toHandleUp = toPort.facingDirection === "up" ? 0.5 : 0;
4281
+ db.schematic_trace.insert({
4282
+ edges: [
4283
+ {
4284
+ from: { x: toAnchorPos.x, y: toAnchorPos.y },
4285
+ to: {
4286
+ x: toAnchorPos.x,
4287
+ y: toAnchorPos.y + toHandleUp * toOffsets.schBoxVertOffset
4288
+ }
4289
+ },
4290
+ {
4291
+ from: { x: toAnchorPos.x, y: toAnchorPos.y },
4292
+ to: {
4293
+ x: toAnchorPos.x + toOffsets.horzPortDirection * toOffsets.schBoxHorzOffset,
4294
+ y: toAnchorPos.y + toOffsets.vertPortDirectionOffset * toOffsets.schBoxVertOffset
4295
+ }
4296
+ }
4297
+ ],
4298
+ junctions: [
4299
+ {
4300
+ x: toAnchorPos.x + toOffsets.horzPortDirection * toOffsets.schBoxHorzOffset,
4301
+ y: toAnchorPos.y + toOffsets.vertPortDirectionOffset * toOffsets.schBoxVertOffset
4302
+ }
4303
+ ],
4304
+ source_trace_id
4305
+ });
4306
+ };
4307
+
4185
4308
  // lib/components/primitive-components/Trace/Trace.ts
4186
4309
  var portToObjective = (port) => {
4187
4310
  const portPosition = port._getGlobalPcbPositionAfterLayout();
@@ -4645,23 +4768,28 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
4645
4768
  }
4646
4769
  const existingFromNetLabel = db.schematic_net_label.list().find((label) => label.source_net_id === fromPort.source_port_id);
4647
4770
  const existingToNetLabel = db.schematic_net_label.list().find((label) => label.source_net_id === toPort.source_port_id);
4648
- if (this.props.schDisplayLabel) {
4649
- if (existingFromNetLabel && existingFromNetLabel.text !== this.props.schDisplayLabel || existingToNetLabel && existingToNetLabel?.text !== this.props.schDisplayLabel) {
4650
- throw new Error(
4651
- `Cannot create net label for port ${existingFromNetLabel ? fromPortName : toPortName} because it already has a net label with text "${existingFromNetLabel ? existingFromNetLabel.text : existingToNetLabel?.text}".`
4652
- );
4653
- }
4771
+ if (existingFromNetLabel && existingFromNetLabel.text !== this.props.schDisplayLabel || existingToNetLabel && existingToNetLabel?.text !== this.props.schDisplayLabel) {
4772
+ throw new Error(
4773
+ `Cannot create net label for port ${existingFromNetLabel ? fromPortName : toPortName} because it already has a net label with text "${existingFromNetLabel ? existingFromNetLabel.text : existingToNetLabel?.text}".`
4774
+ );
4775
+ }
4776
+ if (this.props.schDisplayLabel?.toLocaleLowerCase().includes("gnd") || this.props.schDisplayLabel?.toLocaleLowerCase().includes("ground")) {
4777
+ createDownwardNetLabelGroundSymbol(
4778
+ {
4779
+ fromPort,
4780
+ toPort,
4781
+ fromAnchorPos,
4782
+ toAnchorPos,
4783
+ schDisplayLabel: this.props.schDisplayLabel,
4784
+ source_trace_id: this.source_trace_id
4785
+ },
4786
+ { db }
4787
+ );
4788
+ return;
4654
4789
  }
4655
4790
  const [firstPort, secondPort] = connectedPorts.map(({ port }) => port);
4656
4791
  const isFirstPortSchematicBox = firstPort.parent?.config.shouldRenderAsSchematicBox;
4657
4792
  const pinFullName = isFirstPortSchematicBox ? `${firstPort?.parent?.props.name}_${firstPort?.props.name}` : `${secondPort?.parent?.props.name}_${secondPort?.props.name}`;
4658
- db.schematic_net_label.insert({
4659
- text: this.props.schDisplayLabel ?? pinFullName,
4660
- source_net_id: fromPort.source_port_id,
4661
- anchor_position: fromAnchorPos,
4662
- center: fromAnchorPos,
4663
- anchor_side: getEnteringEdgeFromDirection(fromPort.facingDirection) ?? "bottom"
4664
- });
4665
4793
  db.schematic_net_label.insert({
4666
4794
  text: this.props.schDisplayLabel ?? pinFullName,
4667
4795
  source_net_id: toPort.source_port_id,
@@ -4669,6 +4797,13 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
4669
4797
  center: toAnchorPos,
4670
4798
  anchor_side: getEnteringEdgeFromDirection(toPort.facingDirection) ?? "bottom"
4671
4799
  });
4800
+ db.schematic_net_label.insert({
4801
+ text: this.props.schDisplayLabel ?? pinFullName,
4802
+ source_net_id: fromPort.source_port_id,
4803
+ anchor_position: fromAnchorPos,
4804
+ center: fromAnchorPos,
4805
+ anchor_side: getEnteringEdgeFromDirection(fromPort.facingDirection) ?? "bottom"
4806
+ });
4672
4807
  }
4673
4808
  _isPassiveToChipConnection() {
4674
4809
  const { allPortsFound, ports } = this._findConnectedPorts();
@@ -4737,6 +4872,25 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
4737
4872
  connectedTo: []
4738
4873
  });
4739
4874
  }
4875
+ if (elm.type === "schematic_net_label" && elm.symbol_name) {
4876
+ obstacles.push({
4877
+ type: "rect",
4878
+ layers: ["top"],
4879
+ center: elm.center,
4880
+ width: 0.25,
4881
+ height: 0.6,
4882
+ connectedTo: []
4883
+ });
4884
+ } else if (elm.type === "schematic_net_label") {
4885
+ obstacles.push({
4886
+ type: "rect",
4887
+ layers: ["top"],
4888
+ center: elm.center,
4889
+ width: (elm.text?.length ?? 0) * 0.1,
4890
+ height: 0.2,
4891
+ connectedTo: []
4892
+ });
4893
+ }
4740
4894
  }
4741
4895
  const portsWithPosition = connectedPorts.map(({ port }) => ({
4742
4896
  port,
@@ -5392,6 +5546,39 @@ var SilkscreenText = class extends PrimitiveComponent {
5392
5546
  }
5393
5547
  };
5394
5548
 
5549
+ // lib/components/primitive-components/SilkscreenLine.ts
5550
+ import { silkscreenLineProps } from "@tscircuit/props";
5551
+ var SilkscreenLine = class extends PrimitiveComponent {
5552
+ pcb_silkscreen_line_id = null;
5553
+ get config() {
5554
+ return {
5555
+ componentName: "SilkscreenLine",
5556
+ zodProps: silkscreenLineProps
5557
+ };
5558
+ }
5559
+ doInitialPcbPrimitiveRender() {
5560
+ if (this.root?.pcbDisabled) return;
5561
+ const { db } = this.root;
5562
+ const { _parsedProps: props } = this;
5563
+ const layer = props.layer ?? "top";
5564
+ if (layer !== "top" && layer !== "bottom") {
5565
+ throw new Error(
5566
+ `Invalid layer "${layer}" for SilkscreenLine. Must be "top" or "bottom".`
5567
+ );
5568
+ }
5569
+ const pcb_silkscreen_line = db.pcb_silkscreen_line.insert({
5570
+ pcb_component_id: this.parent?.pcb_component_id,
5571
+ layer,
5572
+ x1: props.x1,
5573
+ y1: props.y1,
5574
+ x2: props.x2,
5575
+ y2: props.y2,
5576
+ stroke_width: props.strokeWidth ?? 0.1
5577
+ });
5578
+ this.pcb_silkscreen_line_id = pcb_silkscreen_line.pcb_silkscreen_line_id;
5579
+ }
5580
+ };
5581
+
5395
5582
  // lib/components/primitive-components/Via.ts
5396
5583
  import { viaProps } from "@tscircuit/props";
5397
5584
  var Via = class extends PrimitiveComponent {
@@ -5935,6 +6122,47 @@ var useResistor = createUseComponent(
5935
6122
  resistorPins2
5936
6123
  );
5937
6124
 
6125
+ // lib/utils/edit-events/apply-edit-events-to-manual-edits-file.ts
6126
+ import "zod";
6127
+ import { su as su2 } from "@tscircuit/soup-util";
6128
+ var applyEditEventsToManualEditsFile = ({
6129
+ circuitJson,
6130
+ editEvents,
6131
+ manualEditsFile
6132
+ }) => {
6133
+ const updatedManualEditsFile = {
6134
+ ...manualEditsFile,
6135
+ schematic_placements: [...manualEditsFile.schematic_placements ?? []]
6136
+ };
6137
+ for (const editEvent of editEvents) {
6138
+ if (editEvent.edit_event_type === "edit_schematic_component_location") {
6139
+ const { schematic_component_id, new_center } = editEvent;
6140
+ const schematic_component2 = su2(circuitJson).schematic_component.get(
6141
+ schematic_component_id
6142
+ );
6143
+ if (!schematic_component2) continue;
6144
+ const source_component = su2(circuitJson).source_component.get(
6145
+ schematic_component2.source_component_id
6146
+ );
6147
+ if (!source_component) continue;
6148
+ const existingPlacementIndex = updatedManualEditsFile.schematic_placements?.findIndex(
6149
+ (p) => p.selector === source_component.name
6150
+ );
6151
+ const newPlacement = {
6152
+ selector: source_component.name,
6153
+ center: new_center,
6154
+ relative_to: "group_center"
6155
+ };
6156
+ if (existingPlacementIndex >= 0) {
6157
+ updatedManualEditsFile.schematic_placements[existingPlacementIndex] = newPlacement;
6158
+ } else {
6159
+ updatedManualEditsFile.schematic_placements.push(newPlacement);
6160
+ }
6161
+ }
6162
+ }
6163
+ return updatedManualEditsFile;
6164
+ };
6165
+
5938
6166
  // lib/register-catalogue.ts
5939
6167
  extendCatalogue(components_exports);
5940
6168
  extendCatalogue({
@@ -5972,6 +6200,7 @@ export {
5972
6200
  Renderable,
5973
6201
  Resistor,
5974
6202
  SilkscreenCircle,
6203
+ SilkscreenLine,
5975
6204
  SilkscreenPath,
5976
6205
  SilkscreenRect,
5977
6206
  SilkscreenText,
@@ -5980,6 +6209,7 @@ export {
5980
6209
  Trace,
5981
6210
  TraceHint,
5982
6211
  Via,
6212
+ applyEditEventsToManualEditsFile,
5983
6213
  createUseComponent,
5984
6214
  useCapacitor,
5985
6215
  useChip,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.229",
4
+ "version": "0.0.231",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -15,7 +15,8 @@
15
15
  "scripts": {
16
16
  "build": "tsup-node index.ts --format esm --dts",
17
17
  "format": "biome format . --write",
18
- "measure-bundle": "howfat -r table ."
18
+ "measure-bundle": "howfat -r table .",
19
+ "pkg-pr-new-release": "bunx pkg-pr-new publish --comment=off --peerDeps"
19
20
  },
20
21
  "devDependencies": {
21
22
  "@biomejs/biome": "^1.8.3",
@@ -26,10 +27,11 @@
26
27
  "@types/react": "^19.0.1",
27
28
  "@types/react-reconciler": "^0.28.8",
28
29
  "bun-match-svg": "0.0.8",
29
- "circuit-to-svg": "^0.0.87",
30
+ "circuit-to-svg": "^0.0.93",
30
31
  "debug": "^4.3.6",
31
32
  "howfat": "^0.3.8",
32
33
  "looks-same": "^9.0.1",
34
+ "pkg-pr-new": "^0.0.37",
33
35
  "ts-expect": "^1.3.0",
34
36
  "tsup": "^8.2.4"
35
37
  },
@@ -41,17 +43,17 @@
41
43
  "@tscircuit/footprinter": "^0.0.92",
42
44
  "@tscircuit/infgrid-ijump-astar": "^0.0.26",
43
45
  "@tscircuit/math-utils": "^0.0.5",
44
- "@tscircuit/props": "^0.0.109",
46
+ "@tscircuit/props": "^0.0.115",
45
47
  "@tscircuit/schematic-autolayout": "^0.0.6",
46
48
  "@tscircuit/soup-util": "^0.0.41",
47
- "circuit-json": "^0.0.108",
49
+ "circuit-json": "^0.0.117",
48
50
  "circuit-json-to-connectivity-map": "^0.0.17",
49
51
  "format-si-unit": "^0.0.2",
50
52
  "nanoid": "^5.0.7",
51
53
  "performance-now": "^2.1.0",
52
54
  "react": "^18.3.1",
53
55
  "react-reconciler": "^0.29.2",
54
- "schematic-symbols": "^0.0.98",
56
+ "schematic-symbols": "^0.0.99",
55
57
  "transformation-matrix": "^2.16.1",
56
58
  "zod": "^3.23.8"
57
59
  }