@tscircuit/core 0.0.437 → 0.0.439

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");
@@ -5909,7 +5910,7 @@ import { identity as identity3 } from "transformation-matrix";
5909
5910
  import {
5910
5911
  groupProps
5911
5912
  } from "@tscircuit/props";
5912
- import * as SAL from "@tscircuit/schematic-autolayout";
5913
+ import "@tscircuit/schematic-autolayout";
5913
5914
 
5914
5915
  // lib/utils/autorouting/CapacityMeshAutorouter.ts
5915
5916
  import { CapacityMeshSolver } from "@tscircuit/capacity-autorouter";
@@ -6061,7 +6062,7 @@ var CapacityMeshAutorouter = class {
6061
6062
 
6062
6063
  // lib/components/primitive-components/Group/Group.ts
6063
6064
  import "circuit-json";
6064
- import { ConnectivityMap as ConnectivityMap2 } from "circuit-json-to-connectivity-map";
6065
+ import "circuit-json-to-connectivity-map";
6065
6066
  import Debug5 from "debug";
6066
6067
  import "zod";
6067
6068
 
@@ -6592,6 +6593,405 @@ var normalizePinLabels = (inputPinLabels) => {
6592
6593
 
6593
6594
  // lib/components/primitive-components/Group/Group.ts
6594
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
6595
6995
  var Group = class extends NormalComponent {
6596
6996
  pcb_group_id = null;
6597
6997
  schematic_group_id = null;
@@ -6683,33 +7083,7 @@ var Group = class extends NormalComponent {
6683
7083
  }
6684
7084
  }
6685
7085
  doInitialSourceAddConnectivityMapKey() {
6686
- if (!this.isSubcircuit) return;
6687
- const { db } = this.root;
6688
- const traces = this.selectAll("trace");
6689
- const connMap = new ConnectivityMap2({});
6690
- connMap.addConnections(
6691
- traces.map((t) => {
6692
- const source_trace = db.source_trace.get(
6693
- t.source_trace_id
6694
- );
6695
- if (!source_trace) return null;
6696
- return [
6697
- source_trace.source_trace_id,
6698
- ...source_trace.connected_source_port_ids,
6699
- ...source_trace.connected_source_net_ids
6700
- ];
6701
- }).filter((c) => c !== null)
6702
- );
6703
- for (const trace of traces) {
6704
- if (!trace.source_trace_id) continue;
6705
- const connNetId = connMap.getNetConnectedToId(trace.source_trace_id);
6706
- if (!connNetId) continue;
6707
- const { name: subcircuitName } = this._parsedProps;
6708
- trace.subcircuit_connectivity_map_key = `${subcircuitName ?? `unnamedsubcircuit${this._renderId}`}_${connNetId}`;
6709
- db.source_trace.update(trace.source_trace_id, {
6710
- subcircuit_connectivity_map_key: trace.subcircuit_connectivity_map_key
6711
- });
6712
- }
7086
+ Group_doInitialSourceAddConnectivityMapKey(this);
6713
7087
  }
6714
7088
  _areChildSubcircuitsRouted() {
6715
7089
  const subcircuitChildren = this.selectAll("group").filter(
@@ -7055,36 +7429,69 @@ var Group = class extends NormalComponent {
7055
7429
  });
7056
7430
  this.schematic_group_id = schematic_group.schematic_group_id;
7057
7431
  for (const child of this.children) {
7058
- db.schematic_component.update(child.schematic_component_id, {
7059
- schematic_group_id: schematic_group.schematic_group_id
7060
- });
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
+ }
7061
7437
  }
7062
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
+ }
7063
7449
  doInitialSchematicLayout() {
7064
- if (!this.isSubcircuit) return;
7065
7450
  const props = this._parsedProps;
7066
- if (!props.schAutoLayoutEnabled) return;
7067
- const { db } = this.root;
7068
- const descendants = this.getDescendants();
7069
- const components = [];
7070
- const ports = [];
7071
- for (const descendant of descendants) {
7072
- if ("schematic_component_id" in descendant) {
7073
- const component = db.schematic_component.get(
7074
- descendant.schematic_component_id
7075
- );
7076
- if (component) {
7077
- const schPorts = db.schematic_port.list().filter(
7078
- (p) => p.schematic_component_id === component.schematic_component_id
7079
- );
7080
- components.push(component);
7081
- ports.push(...schPorts);
7082
- }
7083
- }
7451
+ const schematicLayoutMode = this._getSchematicLayoutMode();
7452
+ if (schematicLayoutMode === "match-adapt") {
7453
+ this._doInitialSchematicLayoutMatchAdapt();
7454
+ }
7455
+ if (schematicLayoutMode === "grid") {
7456
+ this._doInitialSchematicLayoutGrid();
7457
+ }
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);
7084
7487
  }
7085
- const scene = SAL.convertSoupToScene(db.toArray());
7086
- const laidOutScene = SAL.ascendingCentralLrBug1(scene);
7087
- SAL.mutateSoupForScene(db.toArray(), laidOutScene);
7488
+ const padding = 2;
7489
+ return {
7490
+ minX: minX - padding,
7491
+ maxX: maxX + padding,
7492
+ minY: minY - padding,
7493
+ maxY: maxY + padding
7494
+ };
7088
7495
  }
7089
7496
  _getAutorouterConfig() {
7090
7497
  const defaults = {
@@ -7179,6 +7586,9 @@ var Board = class extends Group {
7179
7586
  get isSubcircuit() {
7180
7587
  return true;
7181
7588
  }
7589
+ get isGroup() {
7590
+ return true;
7591
+ }
7182
7592
  get config() {
7183
7593
  return {
7184
7594
  componentName: "Board",
@@ -7729,6 +8139,8 @@ var Resistor = class extends NormalComponent {
7729
8139
  this._createNetsFromProps([
7730
8140
  this.props.pullupFor,
7731
8141
  this.props.pullupTo,
8142
+ this.props.pulldownFor,
8143
+ this.props.pulldownTo,
7732
8144
  ...this._getNetsFromConnectionsProp()
7733
8145
  ]);
7734
8146
  }
@@ -7747,6 +8159,20 @@ var Resistor = class extends NormalComponent {
7747
8159
  })
7748
8160
  );
7749
8161
  }
8162
+ if (this.props.pulldownFor && this.props.pulldownTo) {
8163
+ this.add(
8164
+ new Trace2({
8165
+ from: `${this.getSubcircuitSelector()} > port.1`,
8166
+ to: this.props.pulldownFor
8167
+ })
8168
+ );
8169
+ this.add(
8170
+ new Trace2({
8171
+ from: `${this.getSubcircuitSelector()} > port.2`,
8172
+ to: this.props.pulldownTo
8173
+ })
8174
+ );
8175
+ }
7750
8176
  this._createTracesFromConnectionsProp();
7751
8177
  }
7752
8178
  doInitialSourceRender() {
@@ -8825,7 +9251,7 @@ import { identity as identity4 } from "transformation-matrix";
8825
9251
  var package_default = {
8826
9252
  name: "@tscircuit/core",
8827
9253
  type: "module",
8828
- version: "0.0.436",
9254
+ version: "0.0.438",
8829
9255
  types: "dist/index.d.ts",
8830
9256
  main: "dist/index.js",
8831
9257
  module: "dist/index.js",
@@ -8859,6 +9285,7 @@ var package_default = {
8859
9285
  "@tscircuit/math-utils": "^0.0.18",
8860
9286
  "@tscircuit/props": "^0.0.204",
8861
9287
  "@tscircuit/schematic-autolayout": "^0.0.6",
9288
+ "@tscircuit/schematic-match-adapt": "^0.0.9",
8862
9289
  "@tscircuit/simple-3d-svg": "^0.0.6",
8863
9290
  "@types/bun": "latest",
8864
9291
  "@types/debug": "^4.1.12",
@@ -8867,7 +9294,7 @@ var package_default = {
8867
9294
  "@types/react-reconciler": "^0.28.9",
8868
9295
  "bun-match-svg": "0.0.8",
8869
9296
  "chokidar-cli": "^3.0.0",
8870
- "circuit-json": "^0.0.190",
9297
+ "circuit-json": "^0.0.194",
8871
9298
  "circuit-json-to-connectivity-map": "^0.0.22",
8872
9299
  "circuit-json-to-simple-3d": "^0.0.2",
8873
9300
  "circuit-to-svg": "^0.0.138",
@@ -8880,7 +9307,7 @@ var package_default = {
8880
9307
  "pkg-pr-new": "^0.0.37",
8881
9308
  react: "^19.0.0",
8882
9309
  "react-dom": "^19.0.0",
8883
- "schematic-symbols": "^0.0.142",
9310
+ "schematic-symbols": "^0.0.143",
8884
9311
  "ts-expect": "^1.3.0",
8885
9312
  tsup: "^8.2.4"
8886
9313
  },
@@ -8894,6 +9321,7 @@ var package_default = {
8894
9321
  "@tscircuit/math-utils": "*",
8895
9322
  "@tscircuit/props": "*",
8896
9323
  "@tscircuit/schematic-autolayout": "*",
9324
+ "@tscircuit/schematic-match-adapt": "*",
8897
9325
  "circuit-json-to-connectivity-map": "*",
8898
9326
  "circuit-json": "*",
8899
9327
  "schematic-symbols": "*"
@@ -9020,7 +9448,15 @@ var RootCircuit = class {
9020
9448
  "${e.message}"`
9021
9449
  );
9022
9450
  });
9023
- return circuitToSvg.convertCircuitJsonToPcbSvg(this.getCircuitJson());
9451
+ if (options.view === "pcb") {
9452
+ return circuitToSvg.convertCircuitJsonToPcbSvg(this.getCircuitJson());
9453
+ }
9454
+ if (options.view === "schematic") {
9455
+ return circuitToSvg.convertCircuitJsonToSchematicSvg(
9456
+ this.getCircuitJson()
9457
+ );
9458
+ }
9459
+ throw new Error(`Invalid view: ${options.view}`);
9024
9460
  }
9025
9461
  getCoreVersion() {
9026
9462
  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.437",
4
+ "version": "0.0.439",
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": "*"