@tscircuit/core 0.0.436 → 0.0.438

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
@@ -5,7 +5,7 @@ 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, PcbManualEditConflictWarning, LayerRef, AnyCircuitElement, AnySourceComponent, PcbTraceRoutePoint, PcbTrace as PcbTrace$1, PcbVia, RouteHintPoint, CircuitJson } from 'circuit-json';
8
+ import { PcbTraceError, PcbPlacementError, PcbManualEditConflictWarning, LayerRef, AnyCircuitElement, AnySourceComponent, PcbTraceRoutePoint, PcbTrace as PcbTrace$1, PcbVia, SchematicPort, SchematicComponent, RouteHintPoint, CircuitJson } from 'circuit-json';
9
9
  import { Matrix } from 'transformation-matrix';
10
10
  import { CircuitJsonUtilObjects } from '@tscircuit/circuit-json-util';
11
11
  import * as _tscircuit_layout from '@tscircuit/layout';
@@ -226,7 +226,7 @@ declare class RootCircuit {
226
226
  getCircuitJson(): AnyCircuitElement[];
227
227
  toJson(): AnyCircuitElement[];
228
228
  getSvg(options: {
229
- view: "pcb";
229
+ view: "pcb" | "schematic";
230
230
  layer?: string;
231
231
  }): Promise<string>;
232
232
  getCoreVersion(): string;
@@ -267,6 +267,7 @@ interface ISubcircuit extends PrimitiveComponent {
267
267
  interface IGroup extends PrimitiveComponent {
268
268
  source_group_id: string | null;
269
269
  pcb_group_id: string | null;
270
+ _getSchematicLayoutMode(): "match-adapt" | "flex" | "grid" | "none";
270
271
  }
271
272
 
272
273
  type Ftype = Extract<AnySourceComponent, {
@@ -1051,7 +1052,20 @@ declare class Group<Props extends z.ZodType<any, any, any> = typeof groupProps>
1051
1052
  _updatePcbTraceRenderFromSimpleRouteJson(): void;
1052
1053
  _updatePcbTraceRenderFromPcbTraces(): void;
1053
1054
  doInitialSchematicComponentRender(): void;
1055
+ _getSchematicLayoutMode(): "match-adapt" | "flex" | "grid" | "none";
1054
1056
  doInitialSchematicLayout(): void;
1057
+ _doInitialSchematicLayoutMatchAdapt(): void;
1058
+ _doInitialSchematicLayoutGrid(): void;
1059
+ _determineSideFromPosition(port: SchematicPort, component: SchematicComponent): "left" | "right" | "top" | "bottom";
1060
+ _calculateSchematicBounds(boxes: Array<{
1061
+ centerX: number;
1062
+ centerY: number;
1063
+ }>): {
1064
+ minX: number;
1065
+ maxX: number;
1066
+ minY: number;
1067
+ maxY: number;
1068
+ };
1055
1069
  _getAutorouterConfig(): AutorouterConfig;
1056
1070
  /**
1057
1071
  * Trace-by-trace autorouting is where each trace routes itself in a well-known
@@ -1070,6 +1084,7 @@ declare class Board extends Group<typeof boardProps> {
1070
1084
  _drcChecksComplete: boolean;
1071
1085
  _connectedSchematicPortPairs: Set<string>;
1072
1086
  get isSubcircuit(): boolean;
1087
+ get isGroup(): boolean;
1073
1088
  get config(): {
1074
1089
  componentName: string;
1075
1090
  zodProps: zod.ZodObject<{
@@ -13129,7 +13144,7 @@ declare const normalizePinLabels: (inputPinLabels: string[][]) => string[][];
13129
13144
  type Nums16 = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "10" | "11" | "12" | "13" | "14" | "15" | "16";
13130
13145
  type Nums40 = "0" | "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";
13131
13146
  type PinNumbers100 = "pin0" | "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";
13132
- type CommonPinNames = "pos" | "neg" | "V5" | "V3_3" | "PWR" | "VCC" | "VDD" | "GND" | "SHLD" | `D${Nums40}` | `GP${Nums40}` | `GPIO${Nums40}` | "DP" | "DN" | "VIN" | "VOUT" | "VREF" | "VIN" | "VOUT" | "VREF" | "VUSB" | "VIN" | "VOUT" | "VREF" | "OUT" | "DISCH" | "EN" | "IN" | "CLK" | "DATA" | "THRES" | "TRIG" | "RESET" | "DM" | "DP" | "CC1" | "CC2" | `A${Nums40}` | `B${Nums40}` | PinNumbers100;
13147
+ type CommonPinNames = "pos" | "neg" | "V5" | "V3_3" | "PWR" | "VCC" | "VDD" | "GND" | "SHLD" | `D${Nums40}` | `GP${Nums40}` | `GPIO${Nums40}` | "DP" | "DN" | "VIN" | "VOUT" | "VREF" | "VIN" | "VOUT" | "VREF" | "VUSB" | "VIN" | "VOUT" | "VREF" | "OUT" | "DISCH" | "EN" | "IN" | "CLK" | "DATA" | "THRES" | "TRIG" | "RESET" | "DM" | "DP" | "CC1" | "CC2" | "N_CS" | "N_WP" | "N_HOLD" | "SCL" | "SDA" | "MOSI" | "MISO" | "SCK" | "CS" | `A${Nums40}` | `B${Nums40}` | PinNumbers100;
13133
13148
  type TransistorPinNames = "base" | "collector" | "emitter";
13134
13149
 
13135
13150
  type NonPolarizedSel = Record<`R${Nums40}`, {
@@ -13154,7 +13169,7 @@ type PolarizedSel = Record<`C${Nums40}` | `L${Nums40}` | `LED${Nums40}` | `D${Nu
13154
13169
  pos: string;
13155
13170
  neg: string;
13156
13171
  }>;
13157
- type CommonNetNames = "VCC" | "GND" | "VDD" | "PWR" | "V5" | "V3_3" | "VIN" | "SHLD" | "EN";
13172
+ type CommonNetNames = "VCC" | "GND" | "VDD" | "PWR" | "V5" | "V3_3" | "VIN" | "SHLD" | "EN" | "SCL" | "SDA" | "MOSI" | "MISO" | "SCK" | "CS" | "FLASH_SDO" | "FLASH_SDI" | "FLASH_SCK" | "FLASH_N_CS" | "FLASH_N_WP" | "FLASH_N_HOLD";
13158
13173
  type TransistorSel = Record<`Q${Nums40}`, Record<TransistorPinNames, string>>;
13159
13174
  type JumperSel = Record<`J${Nums40}` | `CN${Nums40}`, Record<PinNumbers100 | CommonPinNames, string> & ChipFnSel>;
13160
13175
  type ChipSel = Record<`U${Nums40}`, Record<CommonPinNames, string> & ChipFnSel>;
package/dist/index.js CHANGED
@@ -4898,6 +4898,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
4898
4898
  }
4899
4899
  doInitialSchematicTraceRender() {
4900
4900
  if (this.root?.schematicDisabled) return;
4901
+ if (this.getGroup()?._getSchematicLayoutMode() === "match-adapt") return;
4901
4902
  const { db } = this.root;
4902
4903
  const { _parsedProps: props, parent } = this;
4903
4904
  if (!parent) throw new Error("Trace has no parent");
@@ -5809,6 +5810,7 @@ var NormalComponent = class extends PrimitiveComponent2 {
5809
5810
  });
5810
5811
  }
5811
5812
  async _getSupplierPartNumbers(partsEngine, source_component, footprinterString) {
5813
+ if (this.props.doNotPlace) return {};
5812
5814
  const cacheEngine = this.root?.platform?.localCacheEngine;
5813
5815
  const cacheKey = this._getPartsEngineCacheKey(
5814
5816
  source_component,
@@ -5839,6 +5841,7 @@ var NormalComponent = class extends PrimitiveComponent2 {
5839
5841
  return supplierPartNumbers;
5840
5842
  }
5841
5843
  doInitialPartsEngineRender() {
5844
+ if (this.props.doNotPlace) return;
5842
5845
  const partsEngine = this.getInheritedProperty("partsEngine");
5843
5846
  if (!partsEngine) return;
5844
5847
  const { db } = this.root;
@@ -5866,6 +5869,7 @@ var NormalComponent = class extends PrimitiveComponent2 {
5866
5869
  });
5867
5870
  }
5868
5871
  updatePartsEngineRender() {
5872
+ if (this.props.doNotPlace) return;
5869
5873
  const { db } = this.root;
5870
5874
  const source_component = db.source_component.get(this.source_component_id);
5871
5875
  if (!source_component) return;
@@ -5906,7 +5910,7 @@ import { identity as identity3 } from "transformation-matrix";
5906
5910
  import {
5907
5911
  groupProps
5908
5912
  } from "@tscircuit/props";
5909
- import * as SAL from "@tscircuit/schematic-autolayout";
5913
+ import "@tscircuit/schematic-autolayout";
5910
5914
 
5911
5915
  // lib/utils/autorouting/CapacityMeshAutorouter.ts
5912
5916
  import { CapacityMeshSolver } from "@tscircuit/capacity-autorouter";
@@ -6058,7 +6062,7 @@ var CapacityMeshAutorouter = class {
6058
6062
 
6059
6063
  // lib/components/primitive-components/Group/Group.ts
6060
6064
  import "circuit-json";
6061
- import { ConnectivityMap as ConnectivityMap2 } from "circuit-json-to-connectivity-map";
6065
+ import "circuit-json-to-connectivity-map";
6062
6066
  import Debug5 from "debug";
6063
6067
  import "zod";
6064
6068
 
@@ -6589,6 +6593,405 @@ var normalizePinLabels = (inputPinLabels) => {
6589
6593
 
6590
6594
  // lib/components/primitive-components/Group/Group.ts
6591
6595
  import "@tscircuit/checks";
6596
+
6597
+ // lib/components/primitive-components/Group/Group_doInitialSchematicLayoutMatchAdapt.ts
6598
+ import {
6599
+ SchematicLayoutPipelineSolver,
6600
+ reorderChipPinsToCcw,
6601
+ convertCircuitJsonToInputNetlist,
6602
+ getRefKey as getRefKey2
6603
+ } from "@tscircuit/schematic-match-adapt";
6604
+
6605
+ // lib/utils/schematic/deriveSourceTraceIdFromMatchAdaptPath.ts
6606
+ import {
6607
+ getRefKey,
6608
+ parseRefKey
6609
+ } from "@tscircuit/schematic-match-adapt";
6610
+ function getConnectivityNetIdFromPortRef(pref, db) {
6611
+ if ("boxId" in pref) {
6612
+ const { boxId: sourceComponentName, pinNumber } = pref;
6613
+ const sourceComp = db.source_component.getWhere({
6614
+ name: sourceComponentName
6615
+ });
6616
+ if (!sourceComp) {
6617
+ throw new Error(
6618
+ `Source component "${sourceComponentName}" not found, but returned from match-adapt ${JSON.stringify(pref)}`
6619
+ );
6620
+ }
6621
+ const sourcePort = db.source_port.getWhere({
6622
+ source_component_id: sourceComp.source_component_id,
6623
+ pin_number: pinNumber
6624
+ });
6625
+ return {
6626
+ subcircuit_connectivity_map_key: sourcePort?.subcircuit_connectivity_map_key ?? null,
6627
+ source_port_id: sourcePort.source_port_id
6628
+ };
6629
+ }
6630
+ if ("netId" in pref) {
6631
+ const { netId: sourceNetName } = pref;
6632
+ const sourceNet = db.source_net.getWhere({ name: sourceNetName });
6633
+ return null;
6634
+ }
6635
+ if ("junctionId" in pref) {
6636
+ const { junctionId } = pref;
6637
+ return null;
6638
+ }
6639
+ return null;
6640
+ }
6641
+ function deriveSourceTraceIdFromMatchAdaptPath({
6642
+ path,
6643
+ db,
6644
+ layoutConnMap
6645
+ }) {
6646
+ let bestRef = getConnectivityNetIdFromPortRef(path.to, db) ?? getConnectivityNetIdFromPortRef(path.from, db);
6647
+ if (!bestRef) {
6648
+ const layoutConnNetId = layoutConnMap.getNetConnectedToId(
6649
+ getRefKey(path.to)
6650
+ );
6651
+ const layoutConnectedRefs = layoutConnMap.getIdsConnectedToNet(layoutConnNetId).map((prefStr) => parseRefKey(prefStr));
6652
+ bestRef = layoutConnectedRefs.map((ref) => getConnectivityNetIdFromPortRef(ref, db)).find(Boolean);
6653
+ }
6654
+ if (!bestRef?.subcircuit_connectivity_map_key) {
6655
+ throw new Error(
6656
+ `No connectivity net id found for match-adapt path ${JSON.stringify(path)}`
6657
+ );
6658
+ }
6659
+ const sourceTraces = db.source_trace.list({
6660
+ subcircuit_connectivity_map_key: bestRef.subcircuit_connectivity_map_key
6661
+ });
6662
+ for (const sourceTrace of sourceTraces) {
6663
+ if (sourceTrace.connected_source_port_ids.includes(bestRef.source_port_id)) {
6664
+ return sourceTrace.source_trace_id;
6665
+ }
6666
+ }
6667
+ if (sourceTraces.length > 0) {
6668
+ return sourceTraces[0].source_trace_id;
6669
+ }
6670
+ throw new Error(
6671
+ `No source trace found for match-adapt path "${JSON.stringify(path)}"`
6672
+ );
6673
+ }
6674
+
6675
+ // lib/components/primitive-components/Group/Group_doInitialSchematicLayoutMatchAdapt.ts
6676
+ import { cju } from "@tscircuit/circuit-json-util";
6677
+ import { ConnectivityMap as ConnectivityMap2 } from "circuit-json-to-connectivity-map";
6678
+ function Group_doInitialSchematicLayoutMatchAdapt(group) {
6679
+ const { db } = group.root;
6680
+ let subtreeCircuitJson = structuredClone(db.toArray());
6681
+ subtreeCircuitJson = reorderChipPinsToCcw(subtreeCircuitJson);
6682
+ const inputNetlist = convertCircuitJsonToInputNetlist(subtreeCircuitJson);
6683
+ const solver = new SchematicLayoutPipelineSolver({
6684
+ inputNetlist
6685
+ });
6686
+ let solvedLayout = null;
6687
+ try {
6688
+ solver.solve();
6689
+ solvedLayout = solver.getLayout();
6690
+ } catch (e) {
6691
+ db.schematic_layout_error.insert({
6692
+ message: `Match-adapt layout failed: ${e.toString()}`,
6693
+ source_group_id: group.source_group_id,
6694
+ schematic_group_id: group.schematic_group_id
6695
+ });
6696
+ return;
6697
+ }
6698
+ const { boxes, junctions, netLabels, paths } = solvedLayout;
6699
+ const layoutConnMap = new ConnectivityMap2({});
6700
+ for (const path of paths) {
6701
+ layoutConnMap.addConnections([[getRefKey2(path.from), getRefKey2(path.to)]]);
6702
+ }
6703
+ for (const junction of junctions) {
6704
+ for (const path of paths) {
6705
+ for (const pathPoint of path.points) {
6706
+ if (Math.abs(pathPoint.x - junction.x) < 1e-3 && Math.abs(pathPoint.y - junction.y) < 1e-3) {
6707
+ layoutConnMap.addConnections([
6708
+ [getRefKey2(path.from), getRefKey2(junction)],
6709
+ [getRefKey2(path.to), getRefKey2(junction)]
6710
+ ]);
6711
+ }
6712
+ }
6713
+ }
6714
+ }
6715
+ for (const box of boxes) {
6716
+ const srcComp = db.source_component.list().find((c) => c.name === box.boxId);
6717
+ if (!srcComp) continue;
6718
+ const schComp = db.schematic_component.getWhere({
6719
+ source_component_id: srcComp.source_component_id
6720
+ });
6721
+ if (!schComp) continue;
6722
+ const schCompMoveDelta = {
6723
+ x: box.centerX - schComp.center.x + 0.1,
6724
+ // TODO figure out why +0.1
6725
+ y: box.centerY - schComp.center.y - 0.1
6726
+ };
6727
+ db.schematic_component.update(schComp.schematic_component_id, {
6728
+ center: {
6729
+ x: schComp.center.x + schCompMoveDelta.x,
6730
+ y: schComp.center.y + schCompMoveDelta.y
6731
+ }
6732
+ });
6733
+ const schematicPorts = db.schematic_port.list({
6734
+ schematic_component_id: schComp.schematic_component_id
6735
+ });
6736
+ for (const schematicPort of schematicPorts) {
6737
+ db.schematic_port.update(schematicPort.schematic_port_id, {
6738
+ center: {
6739
+ x: schematicPort.center.x + schCompMoveDelta.x,
6740
+ y: schematicPort.center.y + schCompMoveDelta.y
6741
+ }
6742
+ });
6743
+ }
6744
+ const schematicTexts = db.schematic_text.list({
6745
+ schematic_component_id: schComp.schematic_component_id
6746
+ });
6747
+ for (const schematicText of schematicTexts) {
6748
+ db.schematic_text.update(schematicText.schematic_text_id, {
6749
+ position: {
6750
+ x: schematicText.position.x + schCompMoveDelta.x,
6751
+ y: schematicText.position.y + schCompMoveDelta.y
6752
+ }
6753
+ });
6754
+ }
6755
+ }
6756
+ for (const nl of netLabels) {
6757
+ const srcNet = db.source_net.list().find((n) => n.name === nl.netId);
6758
+ db.schematic_net_label.insert({
6759
+ text: nl.netId,
6760
+ source_net_id: srcNet?.source_net_id,
6761
+ anchor_position: { x: nl.x, y: nl.y },
6762
+ center: { x: nl.x, y: nl.y },
6763
+ anchor_side: nl.anchorPosition
6764
+ });
6765
+ }
6766
+ for (const path of paths) {
6767
+ if (!path.points || path.points.length < 2) continue;
6768
+ const sourceTraceId = deriveSourceTraceIdFromMatchAdaptPath({
6769
+ path,
6770
+ db: cju(subtreeCircuitJson),
6771
+ layoutConnMap
6772
+ });
6773
+ let edges = [];
6774
+ for (let i = 0; i < path.points.length - 1; i++) {
6775
+ edges.push({
6776
+ from: {
6777
+ x: path.points[i].x,
6778
+ y: path.points[i].y
6779
+ },
6780
+ to: {
6781
+ x: path.points[i + 1].x,
6782
+ y: path.points[i + 1].y
6783
+ }
6784
+ });
6785
+ }
6786
+ const otherCrossingEdges = getOtherSchematicTraces({
6787
+ db,
6788
+ source_trace_id: sourceTraceId,
6789
+ differentNetOnly: true
6790
+ }).flatMap((t) => t.edges);
6791
+ if (otherCrossingEdges.length > 0) {
6792
+ edges = createSchematicTraceCrossingSegments({
6793
+ edges,
6794
+ otherEdges: otherCrossingEdges
6795
+ });
6796
+ }
6797
+ const junctions2 = createSchematicTraceJunctions({
6798
+ edges,
6799
+ db,
6800
+ source_trace_id: sourceTraceId
6801
+ });
6802
+ db.schematic_trace.insert({
6803
+ source_trace_id: sourceTraceId,
6804
+ edges,
6805
+ junctions: junctions2
6806
+ });
6807
+ }
6808
+ }
6809
+
6810
+ // lib/components/primitive-components/Group/Group_doInitialSourceAddConnectivityMapKey.ts
6811
+ import { ConnectivityMap as ConnectivityMap3 } from "circuit-json-to-connectivity-map";
6812
+ function Group_doInitialSourceAddConnectivityMapKey(group) {
6813
+ if (!group.isSubcircuit) return;
6814
+ const { db } = group.root;
6815
+ const traces = group.selectAll("trace");
6816
+ const connMap = new ConnectivityMap3({});
6817
+ connMap.addConnections(
6818
+ traces.map((t) => {
6819
+ const source_trace = db.source_trace.get(
6820
+ t.source_trace_id
6821
+ );
6822
+ if (!source_trace) return null;
6823
+ return [
6824
+ source_trace.source_trace_id,
6825
+ ...source_trace.connected_source_port_ids,
6826
+ ...source_trace.connected_source_net_ids
6827
+ ];
6828
+ }).filter((c) => c !== null)
6829
+ );
6830
+ const { name: subcircuitName } = group._parsedProps;
6831
+ for (const trace of traces) {
6832
+ if (!trace.source_trace_id) continue;
6833
+ const connNetId = connMap.getNetConnectedToId(trace.source_trace_id);
6834
+ if (!connNetId) continue;
6835
+ trace.subcircuit_connectivity_map_key = `${subcircuitName ?? `unnamedsubcircuit${group._renderId}`}_${connNetId}`;
6836
+ db.source_trace.update(trace.source_trace_id, {
6837
+ subcircuit_connectivity_map_key: trace.subcircuit_connectivity_map_key
6838
+ });
6839
+ }
6840
+ const allSourcePortIds = /* @__PURE__ */ new Set();
6841
+ for (const trace of traces) {
6842
+ if (!trace.source_trace_id) continue;
6843
+ const source_trace = db.source_trace.get(
6844
+ trace.source_trace_id
6845
+ );
6846
+ if (!source_trace) continue;
6847
+ for (const id of source_trace.connected_source_port_ids) {
6848
+ allSourcePortIds.add(id);
6849
+ }
6850
+ }
6851
+ for (const portId of allSourcePortIds) {
6852
+ const connNetId = connMap.getNetConnectedToId(portId);
6853
+ if (!connNetId) continue;
6854
+ const connectivityMapKey = `${subcircuitName ?? `unnamedsubcircuit${group._renderId}`}_${connNetId}`;
6855
+ db.source_port.update(portId, {
6856
+ subcircuit_connectivity_map_key: connectivityMapKey
6857
+ });
6858
+ }
6859
+ const allSourceNetIds = /* @__PURE__ */ new Set();
6860
+ for (const trace of traces) {
6861
+ if (!trace.source_trace_id) continue;
6862
+ const source_trace = db.source_trace.get(
6863
+ trace.source_trace_id
6864
+ );
6865
+ if (!source_trace) continue;
6866
+ for (const source_net_id of source_trace.connected_source_net_ids) {
6867
+ allSourceNetIds.add(source_net_id);
6868
+ }
6869
+ }
6870
+ for (const netId of allSourceNetIds) {
6871
+ const connNetId = connMap.getNetConnectedToId(netId);
6872
+ if (!connNetId) continue;
6873
+ const connectivityMapKey = `${subcircuitName ?? `unnamedsubcircuit${group._renderId}`}_${connNetId}`;
6874
+ db.source_net.update(netId, {
6875
+ subcircuit_connectivity_map_key: connectivityMapKey
6876
+ });
6877
+ }
6878
+ }
6879
+
6880
+ // lib/components/primitive-components/Group/Group_doInitialSchematicLayoutGrid.ts
6881
+ function Group_doInitialSchematicLayoutGrid(group) {
6882
+ const { db } = group.root;
6883
+ const props = group._parsedProps;
6884
+ const schematicChildren = group.children.filter(
6885
+ (child) => child.schematic_component_id
6886
+ );
6887
+ if (schematicChildren.length === 0) return;
6888
+ let maxCellWidth = 0;
6889
+ let maxCellHeight = 0;
6890
+ for (const child of schematicChildren) {
6891
+ const schComp = db.schematic_component.get(child.schematic_component_id);
6892
+ if (schComp?.size) {
6893
+ maxCellWidth = Math.max(maxCellWidth, schComp.size.width);
6894
+ maxCellHeight = Math.max(maxCellHeight, schComp.size.height);
6895
+ }
6896
+ }
6897
+ if (maxCellWidth === 0 && schematicChildren.length > 0) maxCellWidth = 1;
6898
+ if (maxCellHeight === 0 && schematicChildren.length > 0) maxCellHeight = 1;
6899
+ let gridColsOption = props.gridCols;
6900
+ let gridRowsOption = void 0;
6901
+ let gridGapOption = props.gridGap;
6902
+ if (props.schLayout?.grid) {
6903
+ gridColsOption = props.schLayout.grid.cols ?? gridColsOption;
6904
+ gridRowsOption = props.schLayout.grid.rows;
6905
+ gridGapOption = props.schLayout.grid.gap ?? gridGapOption;
6906
+ }
6907
+ let numCols;
6908
+ let numRows;
6909
+ if (gridColsOption !== void 0 && gridRowsOption !== void 0) {
6910
+ numCols = gridColsOption;
6911
+ numRows = gridRowsOption;
6912
+ } else if (gridColsOption !== void 0) {
6913
+ numCols = gridColsOption;
6914
+ numRows = Math.ceil(schematicChildren.length / numCols);
6915
+ } else if (gridRowsOption !== void 0) {
6916
+ numRows = gridRowsOption;
6917
+ numCols = Math.ceil(schematicChildren.length / numRows);
6918
+ } else {
6919
+ numCols = Math.ceil(Math.sqrt(schematicChildren.length));
6920
+ numRows = Math.ceil(schematicChildren.length / numCols);
6921
+ }
6922
+ if (numCols === 0 && schematicChildren.length > 0) numCols = 1;
6923
+ if (numRows === 0 && schematicChildren.length > 0)
6924
+ numRows = schematicChildren.length;
6925
+ let gridGapX;
6926
+ let gridGapY;
6927
+ if (typeof gridGapOption === "number") {
6928
+ gridGapX = gridGapOption;
6929
+ gridGapY = gridGapOption;
6930
+ } else if (typeof gridGapOption === "object" && gridGapOption !== null) {
6931
+ gridGapX = gridGapOption.x;
6932
+ gridGapY = gridGapOption.y;
6933
+ } else {
6934
+ gridGapX = 1;
6935
+ gridGapY = 1;
6936
+ }
6937
+ const totalGridWidth = numCols * maxCellWidth + Math.max(0, numCols - 1) * gridGapX;
6938
+ const totalGridHeight = numRows * maxCellHeight + Math.max(0, numRows - 1) * gridGapY;
6939
+ const groupCenter = group._getGlobalSchematicPositionBeforeLayout();
6940
+ const firstCellCenterX = groupCenter.x - totalGridWidth / 2 + maxCellWidth / 2;
6941
+ const firstCellCenterY = groupCenter.y + totalGridHeight / 2 - maxCellHeight / 2;
6942
+ for (let i = 0; i < schematicChildren.length; i++) {
6943
+ const child = schematicChildren[i];
6944
+ if (!child.schematic_component_id) continue;
6945
+ const row = Math.floor(i / numCols);
6946
+ const col = i % numCols;
6947
+ if (row >= numRows || col >= numCols) {
6948
+ console.warn(
6949
+ `Schematic grid layout: Child ${child.getString()} at index ${i} (row ${row}, col ${col}) exceeds specified grid dimensions (${numRows}x${numCols}). Skipping placement.`
6950
+ );
6951
+ continue;
6952
+ }
6953
+ const targetCellCenterX = firstCellCenterX + col * (maxCellWidth + gridGapX);
6954
+ const targetCellCenterY = firstCellCenterY - row * (maxCellHeight + gridGapY);
6955
+ const schComp = db.schematic_component.get(child.schematic_component_id);
6956
+ if (schComp) {
6957
+ const oldChildCenter = schComp.center;
6958
+ const newChildCenter = { x: targetCellCenterX, y: targetCellCenterY };
6959
+ db.schematic_component.update(child.schematic_component_id, {
6960
+ center: newChildCenter
6961
+ });
6962
+ const deltaX = newChildCenter.x - oldChildCenter.x;
6963
+ const deltaY = newChildCenter.y - oldChildCenter.y;
6964
+ const schPorts = db.schematic_port.list({
6965
+ schematic_component_id: child.schematic_component_id
6966
+ });
6967
+ for (const port of schPorts) {
6968
+ db.schematic_port.update(port.schematic_port_id, {
6969
+ center: { x: port.center.x + deltaX, y: port.center.y + deltaY }
6970
+ });
6971
+ }
6972
+ const schTexts = db.schematic_text.list({
6973
+ schematic_component_id: child.schematic_component_id
6974
+ });
6975
+ for (const text of schTexts) {
6976
+ db.schematic_text.update(text.schematic_text_id, {
6977
+ position: {
6978
+ x: text.position.x + deltaX,
6979
+ y: text.position.y + deltaY
6980
+ }
6981
+ });
6982
+ }
6983
+ }
6984
+ }
6985
+ if (group.schematic_group_id) {
6986
+ db.schematic_group.update(group.schematic_group_id, {
6987
+ width: totalGridWidth,
6988
+ height: totalGridHeight,
6989
+ center: groupCenter
6990
+ });
6991
+ }
6992
+ }
6993
+
6994
+ // lib/components/primitive-components/Group/Group.ts
6592
6995
  var Group = class extends NormalComponent {
6593
6996
  pcb_group_id = null;
6594
6997
  schematic_group_id = null;
@@ -6680,33 +7083,7 @@ var Group = class extends NormalComponent {
6680
7083
  }
6681
7084
  }
6682
7085
  doInitialSourceAddConnectivityMapKey() {
6683
- if (!this.isSubcircuit) return;
6684
- const { db } = this.root;
6685
- const traces = this.selectAll("trace");
6686
- const connMap = new ConnectivityMap2({});
6687
- connMap.addConnections(
6688
- traces.map((t) => {
6689
- const source_trace = db.source_trace.get(
6690
- t.source_trace_id
6691
- );
6692
- if (!source_trace) return null;
6693
- return [
6694
- source_trace.source_trace_id,
6695
- ...source_trace.connected_source_port_ids,
6696
- ...source_trace.connected_source_net_ids
6697
- ];
6698
- }).filter((c) => c !== null)
6699
- );
6700
- for (const trace of traces) {
6701
- if (!trace.source_trace_id) continue;
6702
- const connNetId = connMap.getNetConnectedToId(trace.source_trace_id);
6703
- if (!connNetId) continue;
6704
- const { name: subcircuitName } = this._parsedProps;
6705
- trace.subcircuit_connectivity_map_key = `${subcircuitName ?? `unnamedsubcircuit${this._renderId}`}_${connNetId}`;
6706
- db.source_trace.update(trace.source_trace_id, {
6707
- subcircuit_connectivity_map_key: trace.subcircuit_connectivity_map_key
6708
- });
6709
- }
7086
+ Group_doInitialSourceAddConnectivityMapKey(this);
6710
7087
  }
6711
7088
  _areChildSubcircuitsRouted() {
6712
7089
  const subcircuitChildren = this.selectAll("group").filter(
@@ -7052,36 +7429,69 @@ var Group = class extends NormalComponent {
7052
7429
  });
7053
7430
  this.schematic_group_id = schematic_group.schematic_group_id;
7054
7431
  for (const child of this.children) {
7055
- db.schematic_component.update(child.schematic_component_id, {
7056
- schematic_group_id: schematic_group.schematic_group_id
7057
- });
7432
+ if (child.schematic_component_id) {
7433
+ db.schematic_component.update(child.schematic_component_id, {
7434
+ schematic_group_id: schematic_group.schematic_group_id
7435
+ });
7436
+ }
7058
7437
  }
7059
7438
  }
7439
+ _getSchematicLayoutMode() {
7440
+ const props = this._parsedProps;
7441
+ if (props.schLayout?.matchAdapt) return "match-adapt";
7442
+ if (props.schLayout?.flex) return "flex";
7443
+ if (props.schLayout?.grid) return "grid";
7444
+ if (props.matchAdapt) return "match-adapt";
7445
+ if (props.flex) return "flex";
7446
+ if (props.grid) return "grid";
7447
+ return "none";
7448
+ }
7060
7449
  doInitialSchematicLayout() {
7061
- if (!this.isSubcircuit) return;
7062
7450
  const props = this._parsedProps;
7063
- if (!props.schAutoLayoutEnabled) return;
7064
- const { db } = this.root;
7065
- const descendants = this.getDescendants();
7066
- const components = [];
7067
- const ports = [];
7068
- for (const descendant of descendants) {
7069
- if ("schematic_component_id" in descendant) {
7070
- const component = db.schematic_component.get(
7071
- descendant.schematic_component_id
7072
- );
7073
- if (component) {
7074
- const schPorts = db.schematic_port.list().filter(
7075
- (p) => p.schematic_component_id === component.schematic_component_id
7076
- );
7077
- components.push(component);
7078
- ports.push(...schPorts);
7079
- }
7080
- }
7451
+ const schematicLayoutMode = this._getSchematicLayoutMode();
7452
+ if (schematicLayoutMode === "match-adapt") {
7453
+ this._doInitialSchematicLayoutMatchAdapt();
7454
+ }
7455
+ if (schematicLayoutMode === "grid") {
7456
+ this._doInitialSchematicLayoutGrid();
7081
7457
  }
7082
- const scene = SAL.convertSoupToScene(db.toArray());
7083
- const laidOutScene = SAL.ascendingCentralLrBug1(scene);
7084
- SAL.mutateSoupForScene(db.toArray(), laidOutScene);
7458
+ }
7459
+ _doInitialSchematicLayoutMatchAdapt() {
7460
+ Group_doInitialSchematicLayoutMatchAdapt(this);
7461
+ }
7462
+ _doInitialSchematicLayoutGrid() {
7463
+ Group_doInitialSchematicLayoutGrid(this);
7464
+ }
7465
+ _determineSideFromPosition(port, component) {
7466
+ if (!port.center || !component.center) return "left";
7467
+ const dx = port.center.x - component.center.x;
7468
+ const dy = port.center.y - component.center.y;
7469
+ if (Math.abs(dx) > Math.abs(dy)) {
7470
+ return dx > 0 ? "right" : "left";
7471
+ }
7472
+ return dy > 0 ? "bottom" : "top";
7473
+ }
7474
+ _calculateSchematicBounds(boxes) {
7475
+ if (boxes.length === 0) {
7476
+ return { minX: 0, maxX: 0, minY: 0, maxY: 0 };
7477
+ }
7478
+ let minX = Infinity;
7479
+ let maxX = -Infinity;
7480
+ let minY = Infinity;
7481
+ let maxY = -Infinity;
7482
+ for (const box of boxes) {
7483
+ minX = Math.min(minX, box.centerX);
7484
+ maxX = Math.max(maxX, box.centerX);
7485
+ minY = Math.min(minY, box.centerY);
7486
+ maxY = Math.max(maxY, box.centerY);
7487
+ }
7488
+ const padding = 2;
7489
+ return {
7490
+ minX: minX - padding,
7491
+ maxX: maxX + padding,
7492
+ minY: minY - padding,
7493
+ maxY: maxY + padding
7494
+ };
7085
7495
  }
7086
7496
  _getAutorouterConfig() {
7087
7497
  const defaults = {
@@ -7176,6 +7586,9 @@ var Board = class extends Group {
7176
7586
  get isSubcircuit() {
7177
7587
  return true;
7178
7588
  }
7589
+ get isGroup() {
7590
+ return true;
7591
+ }
7179
7592
  get config() {
7180
7593
  return {
7181
7594
  componentName: "Board",
@@ -8822,7 +9235,7 @@ import { identity as identity4 } from "transformation-matrix";
8822
9235
  var package_default = {
8823
9236
  name: "@tscircuit/core",
8824
9237
  type: "module",
8825
- version: "0.0.435",
9238
+ version: "0.0.437",
8826
9239
  types: "dist/index.d.ts",
8827
9240
  main: "dist/index.js",
8828
9241
  module: "dist/index.js",
@@ -8856,6 +9269,7 @@ var package_default = {
8856
9269
  "@tscircuit/math-utils": "^0.0.18",
8857
9270
  "@tscircuit/props": "^0.0.204",
8858
9271
  "@tscircuit/schematic-autolayout": "^0.0.6",
9272
+ "@tscircuit/schematic-match-adapt": "^0.0.9",
8859
9273
  "@tscircuit/simple-3d-svg": "^0.0.6",
8860
9274
  "@types/bun": "latest",
8861
9275
  "@types/debug": "^4.1.12",
@@ -8864,7 +9278,7 @@ var package_default = {
8864
9278
  "@types/react-reconciler": "^0.28.9",
8865
9279
  "bun-match-svg": "0.0.8",
8866
9280
  "chokidar-cli": "^3.0.0",
8867
- "circuit-json": "^0.0.190",
9281
+ "circuit-json": "^0.0.194",
8868
9282
  "circuit-json-to-connectivity-map": "^0.0.22",
8869
9283
  "circuit-json-to-simple-3d": "^0.0.2",
8870
9284
  "circuit-to-svg": "^0.0.138",
@@ -8877,7 +9291,7 @@ var package_default = {
8877
9291
  "pkg-pr-new": "^0.0.37",
8878
9292
  react: "^19.0.0",
8879
9293
  "react-dom": "^19.0.0",
8880
- "schematic-symbols": "^0.0.142",
9294
+ "schematic-symbols": "^0.0.143",
8881
9295
  "ts-expect": "^1.3.0",
8882
9296
  tsup: "^8.2.4"
8883
9297
  },
@@ -8891,6 +9305,7 @@ var package_default = {
8891
9305
  "@tscircuit/math-utils": "*",
8892
9306
  "@tscircuit/props": "*",
8893
9307
  "@tscircuit/schematic-autolayout": "*",
9308
+ "@tscircuit/schematic-match-adapt": "*",
8894
9309
  "circuit-json-to-connectivity-map": "*",
8895
9310
  "circuit-json": "*",
8896
9311
  "schematic-symbols": "*"
@@ -9017,7 +9432,15 @@ var RootCircuit = class {
9017
9432
  "${e.message}"`
9018
9433
  );
9019
9434
  });
9020
- return circuitToSvg.convertCircuitJsonToPcbSvg(this.getCircuitJson());
9435
+ if (options.view === "pcb") {
9436
+ return circuitToSvg.convertCircuitJsonToPcbSvg(this.getCircuitJson());
9437
+ }
9438
+ if (options.view === "schematic") {
9439
+ return circuitToSvg.convertCircuitJsonToSchematicSvg(
9440
+ this.getCircuitJson()
9441
+ );
9442
+ }
9443
+ throw new Error(`Invalid view: ${options.view}`);
9021
9444
  }
9022
9445
  getCoreVersion() {
9023
9446
  const [major, minor, patch] = package_default.version.split(".").map(Number);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.436",
4
+ "version": "0.0.438",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -35,6 +35,7 @@
35
35
  "@tscircuit/math-utils": "^0.0.18",
36
36
  "@tscircuit/props": "^0.0.204",
37
37
  "@tscircuit/schematic-autolayout": "^0.0.6",
38
+ "@tscircuit/schematic-match-adapt": "^0.0.9",
38
39
  "@tscircuit/simple-3d-svg": "^0.0.6",
39
40
  "@types/bun": "latest",
40
41
  "@types/debug": "^4.1.12",
@@ -43,7 +44,7 @@
43
44
  "@types/react-reconciler": "^0.28.9",
44
45
  "bun-match-svg": "0.0.8",
45
46
  "chokidar-cli": "^3.0.0",
46
- "circuit-json": "^0.0.190",
47
+ "circuit-json": "^0.0.194",
47
48
  "circuit-json-to-connectivity-map": "^0.0.22",
48
49
  "circuit-json-to-simple-3d": "^0.0.2",
49
50
  "circuit-to-svg": "^0.0.138",
@@ -56,7 +57,7 @@
56
57
  "pkg-pr-new": "^0.0.37",
57
58
  "react": "^19.0.0",
58
59
  "react-dom": "^19.0.0",
59
- "schematic-symbols": "^0.0.142",
60
+ "schematic-symbols": "^0.0.143",
60
61
  "ts-expect": "^1.3.0",
61
62
  "tsup": "^8.2.4"
62
63
  },
@@ -70,6 +71,7 @@
70
71
  "@tscircuit/math-utils": "*",
71
72
  "@tscircuit/props": "*",
72
73
  "@tscircuit/schematic-autolayout": "*",
74
+ "@tscircuit/schematic-match-adapt": "*",
73
75
  "circuit-json-to-connectivity-map": "*",
74
76
  "circuit-json": "*",
75
77
  "schematic-symbols": "*"