@tscircuit/core 0.0.1073 → 0.0.1075

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
@@ -512,6 +512,11 @@ declare abstract class PrimitiveComponent<ZodProps extends ZodType = any> extend
512
512
  private _shouldAllowBoardVariablesByDefault;
513
513
  private _isInsideFootprint;
514
514
  private _isInsideNonBoardSubcircuit;
515
+ /**
516
+ * Check if this component has a user-defined PCB position.
517
+ * Position can be specified via pcbX/pcbY or edge-based props.
518
+ */
519
+ _hasUserDefinedPcbPosition(): boolean;
515
520
  resolvePcbCoordinate(rawValue: unknown, axis: "pcbX" | "pcbY", options?: {
516
521
  allowBoardVariables?: boolean;
517
522
  allowComponentVariables?: boolean;
@@ -6112,6 +6117,11 @@ declare class Subpanel extends Group<typeof subpanelProps> {
6112
6117
  add(component: PrimitiveComponent): void;
6113
6118
  _cachedGridWidth: number;
6114
6119
  _cachedGridHeight: number;
6120
+ _panelPositionOffset: {
6121
+ x: number;
6122
+ y: number;
6123
+ } | null;
6124
+ _computePcbGlobalTransformBeforeLayout(): Matrix;
6115
6125
  /**
6116
6126
  * Get all board instances from this subpanel and nested subpanels
6117
6127
  */
package/dist/index.js CHANGED
@@ -1285,6 +1285,14 @@ var PrimitiveComponent2 = class extends Renderable {
1285
1285
  }
1286
1286
  return false;
1287
1287
  }
1288
+ /**
1289
+ * Check if this component has a user-defined PCB position.
1290
+ * Position can be specified via pcbX/pcbY or edge-based props.
1291
+ */
1292
+ _hasUserDefinedPcbPosition() {
1293
+ const props = this._parsedProps;
1294
+ return props.pcbX !== void 0 || props.pcbY !== void 0 || props.pcbLeftEdgeX !== void 0 || props.pcbRightEdgeX !== void 0 || props.pcbTopEdgeY !== void 0 || props.pcbBottomEdgeY !== void 0;
1295
+ }
1288
1296
  resolvePcbCoordinate(rawValue, axis, options = {}) {
1289
1297
  return this._resolvePcbCoordinate(rawValue, axis, options);
1290
1298
  }
@@ -18094,7 +18102,7 @@ import { identity as identity5 } from "transformation-matrix";
18094
18102
  var package_default = {
18095
18103
  name: "@tscircuit/core",
18096
18104
  type: "module",
18097
- version: "0.0.1072",
18105
+ version: "0.0.1074",
18098
18106
  types: "dist/index.d.ts",
18099
18107
  main: "dist/index.js",
18100
18108
  module: "dist/index.js",
@@ -18128,7 +18136,7 @@ var package_default = {
18128
18136
  "@tscircuit/alphabet": "0.0.18",
18129
18137
  "@tscircuit/capacity-autorouter": "^0.0.299",
18130
18138
  "@tscircuit/checks": "0.0.100",
18131
- "@tscircuit/circuit-json-util": "^0.0.80",
18139
+ "@tscircuit/circuit-json-util": "^0.0.81",
18132
18140
  "@tscircuit/common": "^0.0.20",
18133
18141
  "@tscircuit/copper-pour-solver": "^0.0.20",
18134
18142
  "@tscircuit/footprinter": "^0.0.316",
@@ -18138,7 +18146,7 @@ var package_default = {
18138
18146
  "@tscircuit/math-utils": "^0.0.29",
18139
18147
  "@tscircuit/miniflex": "^0.0.4",
18140
18148
  "@tscircuit/ngspice-spice-engine": "^0.0.8",
18141
- "@tscircuit/props": "^0.0.485",
18149
+ "@tscircuit/props": "^0.0.487",
18142
18150
  "@tscircuit/schematic-match-adapt": "^0.0.16",
18143
18151
  "@tscircuit/schematic-trace-solver": "^v0.0.45",
18144
18152
  "@tscircuit/solver-utils": "^0.0.3",
@@ -19013,9 +19021,12 @@ var Board = class extends Group6 {
19013
19021
  const { db } = this.root;
19014
19022
  const routingDisabled = this.root?.pcbRoutingDisabled || this.getInheritedProperty("routingDisabled");
19015
19023
  const pcbDisabled = this.root?.pcbDisabled;
19016
- const shouldRunNetlistChecks = true;
19017
- const shouldRunPlacementChecks = !pcbDisabled;
19018
- const shouldRunRoutingChecks = !pcbDisabled && !routingDisabled;
19024
+ const netlistDrcChecksDisabled = this.root?.platform?.netlistDrcChecksDisabled ?? this.getInheritedProperty("netlistDrcChecksDisabled");
19025
+ const placementDrcChecksDisabled = this.root?.platform?.placementDrcChecksDisabled ?? this.getInheritedProperty("placementDrcChecksDisabled");
19026
+ const routingDrcChecksDisabled = this.root?.platform?.routingDrcChecksDisabled ?? this.getInheritedProperty("routingDrcChecksDisabled");
19027
+ const shouldRunNetlistChecks = !netlistDrcChecksDisabled;
19028
+ const shouldRunPlacementChecks = !pcbDisabled && !placementDrcChecksDisabled;
19029
+ const shouldRunRoutingChecks = !pcbDisabled && !routingDisabled && !routingDrcChecksDisabled;
19019
19030
  if (shouldRunRoutingChecks && this._hasIncompleteAsyncEffectsInSubtreeForPhase("PcbTraceRender"))
19020
19031
  return;
19021
19032
  const hasTracesToRoute = this._hasTracesToRoute();
@@ -19213,6 +19224,7 @@ import { distance as distance12 } from "circuit-json";
19213
19224
  // lib/components/normal-components/Subpanel.ts
19214
19225
  import { subpanelProps } from "@tscircuit/props";
19215
19226
  import { distance as distance11 } from "circuit-json";
19227
+ import { compose as compose8, identity as identity6, translate as translate8 } from "transformation-matrix";
19216
19228
 
19217
19229
  // lib/utils/panels/generate-panel-tabs-and-mouse-bites.ts
19218
19230
  import * as Flatten from "@flatten-js/core";
@@ -19423,7 +19435,7 @@ function generatePanelTabsAndMouseBites(boards, options) {
19423
19435
  };
19424
19436
  }
19425
19437
 
19426
- // lib/utils/panels/pack-boards-into-grid.ts
19438
+ // lib/utils/panels/pack-into-grid.ts
19427
19439
  import { distance as distance10 } from "circuit-json";
19428
19440
 
19429
19441
  // lib/utils/panels/get-board-dimensions-from-props.ts
@@ -19455,52 +19467,9 @@ var getBoardDimensionsFromProps = (board) => {
19455
19467
  };
19456
19468
  };
19457
19469
 
19458
- // lib/utils/panels/pack-boards-into-grid.ts
19459
- function calculateOptimalGrid({
19460
- boardsWithDims,
19461
- availableWidth,
19462
- availableHeight,
19463
- boardGap,
19464
- minCellWidth,
19465
- minCellHeight
19466
- }) {
19467
- const boardCount = boardsWithDims.length;
19468
- if (boardCount === 0) {
19469
- return { rows: 0, cols: 0 };
19470
- }
19471
- const maxBoardWidth = Math.max(
19472
- ...boardsWithDims.map((b) => b.width),
19473
- minCellWidth
19474
- );
19475
- const maxBoardHeight = Math.max(
19476
- ...boardsWithDims.map((b) => b.height),
19477
- minCellHeight
19478
- );
19479
- const maxCols = Math.max(
19480
- 1,
19481
- Math.floor((availableWidth + boardGap) / (maxBoardWidth + boardGap))
19482
- );
19483
- const maxRows = Math.max(
19484
- 1,
19485
- Math.floor((availableHeight + boardGap) / (maxBoardHeight + boardGap))
19486
- );
19487
- let bestCols = maxCols;
19488
- let bestRows = Math.ceil(boardCount / bestCols);
19489
- if (bestRows > maxRows) {
19490
- bestRows = maxRows;
19491
- bestCols = Math.ceil(boardCount / bestRows);
19492
- if (bestCols > maxCols) {
19493
- bestCols = maxCols;
19494
- bestRows = Math.ceil(boardCount / bestCols);
19495
- }
19496
- }
19497
- return {
19498
- rows: Math.max(1, bestRows),
19499
- cols: Math.max(1, bestCols)
19500
- };
19501
- }
19502
- var packBoardsIntoGrid = ({
19503
- boards,
19470
+ // lib/utils/panels/pack-into-grid.ts
19471
+ function packIntoGrid({
19472
+ items,
19504
19473
  db,
19505
19474
  row,
19506
19475
  col,
@@ -19509,109 +19478,161 @@ var packBoardsIntoGrid = ({
19509
19478
  boardGap,
19510
19479
  availablePanelWidth,
19511
19480
  availablePanelHeight
19512
- }) => {
19513
- const boardsWithDims = boards.map((board) => {
19514
- let width;
19515
- let height;
19516
- if (db && board.pcb_board_id) {
19517
- const pcbBoard = db.pcb_board.get(board.pcb_board_id);
19518
- if (pcbBoard?.width !== void 0 && pcbBoard?.height !== void 0) {
19519
- width = pcbBoard.width;
19520
- height = pcbBoard.height;
19521
- }
19522
- }
19523
- if (width === void 0 || height === void 0) {
19524
- const propsDims = getBoardDimensionsFromProps(board);
19525
- width = propsDims.width;
19526
- height = propsDims.height;
19527
- }
19528
- if (width === 0 && height === 0) {
19529
- return null;
19530
- }
19531
- return { board, width, height };
19532
- }).filter((b) => b !== null);
19533
- if (boardsWithDims.length === 0) {
19534
- return {
19535
- positions: [],
19536
- gridWidth: 0,
19537
- gridHeight: 0
19538
- };
19481
+ }) {
19482
+ const itemsWithDims = items.map((item) => {
19483
+ const dims = getItemDimensions(item, db);
19484
+ return { item, width: dims.width, height: dims.height };
19485
+ }).filter((item) => !(item.width === 0 && item.height === 0));
19486
+ if (itemsWithDims.length === 0) {
19487
+ return { positions: [], gridWidth: 0, gridHeight: 0 };
19539
19488
  }
19540
- const explicitRow = row;
19541
- const explicitCol = col;
19542
19489
  let cols;
19543
19490
  let rows;
19544
- if (explicitCol !== void 0) {
19545
- cols = explicitCol;
19546
- rows = explicitRow ?? Math.ceil(boardsWithDims.length / cols);
19547
- } else if (explicitRow !== void 0) {
19548
- rows = explicitRow;
19549
- cols = Math.ceil(boardsWithDims.length / rows);
19491
+ const minCellWidth = cellWidth ? distance10.parse(cellWidth) : 0;
19492
+ const minCellHeight = cellHeight ? distance10.parse(cellHeight) : 0;
19493
+ if (col !== void 0) {
19494
+ cols = col;
19495
+ rows = row ?? Math.ceil(itemsWithDims.length / cols);
19496
+ } else if (row !== void 0) {
19497
+ rows = row;
19498
+ cols = Math.ceil(itemsWithDims.length / rows);
19550
19499
  } else if (availablePanelWidth !== void 0 && availablePanelHeight !== void 0) {
19551
- const result = calculateOptimalGrid({
19552
- boardsWithDims,
19553
- availableWidth: availablePanelWidth,
19554
- availableHeight: availablePanelHeight,
19555
- boardGap,
19556
- minCellWidth: cellWidth ? distance10.parse(cellWidth) : 0,
19557
- minCellHeight: cellHeight ? distance10.parse(cellHeight) : 0
19558
- });
19559
- cols = result.cols;
19560
- rows = result.rows;
19500
+ const maxItemWidth = Math.max(
19501
+ ...itemsWithDims.map((b) => b.width),
19502
+ minCellWidth
19503
+ );
19504
+ const maxItemHeight = Math.max(
19505
+ ...itemsWithDims.map((b) => b.height),
19506
+ minCellHeight
19507
+ );
19508
+ const maxCols = Math.max(
19509
+ 1,
19510
+ Math.floor((availablePanelWidth + boardGap) / (maxItemWidth + boardGap))
19511
+ );
19512
+ const maxRows = Math.max(
19513
+ 1,
19514
+ Math.floor(
19515
+ (availablePanelHeight + boardGap) / (maxItemHeight + boardGap)
19516
+ )
19517
+ );
19518
+ cols = maxCols;
19519
+ rows = Math.ceil(itemsWithDims.length / cols);
19520
+ if (rows > maxRows) {
19521
+ rows = maxRows;
19522
+ cols = Math.ceil(itemsWithDims.length / rows);
19523
+ if (cols > maxCols) {
19524
+ cols = maxCols;
19525
+ rows = Math.ceil(itemsWithDims.length / cols);
19526
+ }
19527
+ }
19528
+ cols = Math.max(1, cols);
19529
+ rows = Math.max(1, rows);
19561
19530
  } else {
19562
- cols = Math.ceil(Math.sqrt(boardsWithDims.length));
19563
- rows = Math.ceil(boardsWithDims.length / cols);
19531
+ cols = Math.ceil(Math.sqrt(itemsWithDims.length));
19532
+ rows = Math.ceil(itemsWithDims.length / cols);
19564
19533
  }
19565
19534
  const colWidths = Array(cols).fill(0);
19566
19535
  const rowHeights = Array(rows).fill(0);
19567
- boardsWithDims.forEach((b, i) => {
19536
+ itemsWithDims.forEach((item, i) => {
19568
19537
  const colIdx = i % cols;
19569
19538
  const rowIdx = Math.floor(i / cols);
19570
- if (rowIdx < rowHeights.length && b.height > rowHeights[rowIdx]) {
19571
- rowHeights[rowIdx] = b.height;
19539
+ if (rowIdx < rowHeights.length && item.height > rowHeights[rowIdx]) {
19540
+ rowHeights[rowIdx] = item.height;
19572
19541
  }
19573
- if (colIdx < colWidths.length && b.width > colWidths[colIdx]) {
19574
- colWidths[colIdx] = b.width;
19542
+ if (colIdx < colWidths.length && item.width > colWidths[colIdx]) {
19543
+ colWidths[colIdx] = item.width;
19575
19544
  }
19576
19545
  });
19577
- const minCellWidth = cellWidth ? distance10.parse(cellWidth) : 0;
19578
- const minCellHeight = cellHeight ? distance10.parse(cellHeight) : 0;
19579
19546
  for (let i = 0; i < colWidths.length; i++) {
19580
19547
  colWidths[i] = Math.max(colWidths[i], minCellWidth);
19581
19548
  }
19582
19549
  for (let i = 0; i < rowHeights.length; i++) {
19583
19550
  rowHeights[i] = Math.max(rowHeights[i], minCellHeight);
19584
19551
  }
19585
- const totalGridWidth = colWidths.reduce((a, b) => a + b, 0) + (cols > 1 ? (cols - 1) * boardGap : 0);
19586
- const totalGridHeight = rowHeights.reduce((a, b) => a + b, 0) + (rows > 1 ? (rows - 1) * boardGap : 0);
19587
- const startX = -totalGridWidth / 2;
19588
- const startY = -totalGridHeight / 2;
19589
- const rowYOffsets = [startY];
19590
- for (let i = 1; i < rows; i++) {
19591
- rowYOffsets.push(rowYOffsets[i - 1] + rowHeights[i - 1] + boardGap);
19592
- }
19552
+ const gridWidth = colWidths.reduce((a, b) => a + b, 0) + (cols > 1 ? (cols - 1) * boardGap : 0);
19553
+ const gridHeight = rowHeights.reduce((a, b) => a + b, 0) + (rows > 1 ? (rows - 1) * boardGap : 0);
19554
+ const startX = -gridWidth / 2;
19555
+ const startY = -gridHeight / 2;
19593
19556
  const colXOffsets = [startX];
19594
19557
  for (let i = 1; i < cols; i++) {
19595
19558
  colXOffsets.push(colXOffsets[i - 1] + colWidths[i - 1] + boardGap);
19596
19559
  }
19560
+ const rowYOffsets = [startY];
19561
+ for (let i = 1; i < rows; i++) {
19562
+ rowYOffsets.push(rowYOffsets[i - 1] + rowHeights[i - 1] + boardGap);
19563
+ }
19597
19564
  const positions = [];
19598
- boardsWithDims.forEach((b, i) => {
19565
+ itemsWithDims.forEach((itemWithDims, i) => {
19599
19566
  const colIdx = i % cols;
19600
19567
  const rowIdx = Math.floor(i / cols);
19601
19568
  if (rowIdx >= rowYOffsets.length || colIdx >= colXOffsets.length) return;
19602
- const cellX = colXOffsets[colIdx];
19603
- const cellY = rowYOffsets[rowIdx];
19604
- const currentCellWidth = colWidths[colIdx];
19605
- const currentCellHeight = rowHeights[rowIdx];
19606
- const boardX = cellX + currentCellWidth / 2;
19607
- const boardY = cellY + currentCellHeight / 2;
19608
- positions.push({
19609
- board: b.board,
19610
- pos: { x: boardX, y: boardY }
19611
- });
19569
+ const x = colXOffsets[colIdx] + colWidths[colIdx] / 2;
19570
+ const y = rowYOffsets[rowIdx] + rowHeights[rowIdx] / 2;
19571
+ positions.push({ item: itemWithDims.item, pos: { x, y } });
19612
19572
  });
19613
- return { positions, gridWidth: totalGridWidth, gridHeight: totalGridHeight };
19614
- };
19573
+ return { positions, gridWidth, gridHeight };
19574
+ }
19575
+ function getItemDimensions(item, db) {
19576
+ if (item.componentName === "Board") {
19577
+ const board = item;
19578
+ if (db && board.pcb_board_id) {
19579
+ const pcbBoard = db.pcb_board.get(board.pcb_board_id);
19580
+ if (pcbBoard?.width !== void 0 && pcbBoard?.height !== void 0) {
19581
+ return { width: pcbBoard.width, height: pcbBoard.height };
19582
+ }
19583
+ }
19584
+ return getBoardDimensionsFromProps(board);
19585
+ }
19586
+ if (item.componentName === "Subpanel") {
19587
+ const subpanel = item;
19588
+ const props = subpanel._parsedProps;
19589
+ if (props.width !== void 0 && props.height !== void 0) {
19590
+ return {
19591
+ width: distance10.parse(props.width),
19592
+ height: distance10.parse(props.height)
19593
+ };
19594
+ }
19595
+ const directBoards = subpanel._getDirectBoardChildren();
19596
+ if (directBoards.length === 0) {
19597
+ const allBoards = subpanel._getAllBoardInstances();
19598
+ if (allBoards.length === 0) return { width: 0, height: 0 };
19599
+ let minX = Infinity;
19600
+ let minY = Infinity;
19601
+ let maxX = -Infinity;
19602
+ let maxY = -Infinity;
19603
+ for (const board of allBoards) {
19604
+ const dims = getBoardDimensionsFromProps(board);
19605
+ if (dims.width === 0 || dims.height === 0) continue;
19606
+ const offset = board._panelPositionOffset ?? { x: 0, y: 0 };
19607
+ minX = Math.min(minX, offset.x - dims.width / 2);
19608
+ maxX = Math.max(maxX, offset.x + dims.width / 2);
19609
+ minY = Math.min(minY, offset.y - dims.height / 2);
19610
+ maxY = Math.max(maxY, offset.y + dims.height / 2);
19611
+ }
19612
+ if (minX === Infinity) return { width: 0, height: 0 };
19613
+ return { width: maxX - minX, height: maxY - minY };
19614
+ }
19615
+ if (directBoards.length === 1) {
19616
+ return getBoardDimensionsFromProps(directBoards[0]);
19617
+ }
19618
+ if (subpanel._cachedGridWidth > 0 && subpanel._cachedGridHeight > 0) {
19619
+ const edgePadding = distance10.parse(props.edgePadding ?? 5);
19620
+ return {
19621
+ width: subpanel._cachedGridWidth + edgePadding * 2,
19622
+ height: subpanel._cachedGridHeight + edgePadding * 2
19623
+ };
19624
+ }
19625
+ let totalWidth = 0;
19626
+ let totalHeight = 0;
19627
+ for (const board of directBoards) {
19628
+ const dims = getBoardDimensionsFromProps(board);
19629
+ totalWidth = Math.max(totalWidth, dims.width);
19630
+ totalHeight = Math.max(totalHeight, dims.height);
19631
+ }
19632
+ return { width: totalWidth, height: totalHeight };
19633
+ }
19634
+ return { width: 0, height: 0 };
19635
+ }
19615
19636
 
19616
19637
  // lib/components/normal-components/Subpanel.ts
19617
19638
  var Subpanel = class _Subpanel extends Group6 {
@@ -19642,6 +19663,17 @@ var Subpanel = class _Subpanel extends Group6 {
19642
19663
  }
19643
19664
  _cachedGridWidth = 0;
19644
19665
  _cachedGridHeight = 0;
19666
+ _panelPositionOffset = null;
19667
+ _computePcbGlobalTransformBeforeLayout() {
19668
+ if (this._panelPositionOffset) {
19669
+ const parentTransform = this.parent?._computePcbGlobalTransformBeforeLayout?.() ?? identity6();
19670
+ return compose8(
19671
+ parentTransform,
19672
+ translate8(this._panelPositionOffset.x, this._panelPositionOffset.y)
19673
+ );
19674
+ }
19675
+ return super._computePcbGlobalTransformBeforeLayout();
19676
+ }
19645
19677
  /**
19646
19678
  * Get all board instances from this subpanel and nested subpanels
19647
19679
  */
@@ -19681,35 +19713,30 @@ var Subpanel = class _Subpanel extends Group6 {
19681
19713
  doInitialPanelBoardLayout() {
19682
19714
  if (this.root?.pcbDisabled) return;
19683
19715
  const layoutMode = this._parsedProps.layoutMode ?? "none";
19684
- const childBoardInstances = this._getDirectBoardChildren();
19716
+ const gridItems = this.children.filter(
19717
+ (c) => c instanceof Board || c instanceof _Subpanel
19718
+ );
19685
19719
  if (layoutMode !== "none") {
19686
- for (const board of childBoardInstances) {
19687
- const hasPcbX = board._parsedProps.pcbX !== void 0;
19688
- const hasPcbY = board._parsedProps.pcbY !== void 0;
19689
- if (hasPcbX || hasPcbY) {
19690
- const properties = [];
19691
- if (hasPcbX) properties.push("pcbX");
19692
- if (hasPcbY) properties.push("pcbY");
19693
- const propertyNames = properties.join(" and ");
19720
+ for (const child of gridItems) {
19721
+ if (!(child instanceof Board)) continue;
19722
+ if (child._hasUserDefinedPcbPosition()) {
19694
19723
  this.root.db.source_property_ignored_warning.insert({
19695
- source_component_id: board.source_component_id,
19696
- property_name: propertyNames,
19697
- message: `Board has manual positioning (${propertyNames}) but ${this._errorComponentName} layout mode is "${layoutMode}". Manual positioning will be ignored.`,
19724
+ source_component_id: child.source_component_id,
19725
+ property_name: "pcbX/pcbY",
19726
+ message: `Board has manual positioning but ${this._errorComponentName} layout mode is "${layoutMode}". Manual positioning will be ignored.`,
19698
19727
  error_type: "source_property_ignored_warning"
19699
19728
  });
19700
19729
  }
19701
19730
  }
19702
19731
  }
19703
- if (layoutMode === "none" && childBoardInstances.length > 1) {
19704
- const boardsWithoutPosition = childBoardInstances.filter((board) => {
19705
- const hasPcbX = board._parsedProps.pcbX !== void 0;
19706
- const hasPcbY = board._parsedProps.pcbY !== void 0;
19707
- return !hasPcbX && !hasPcbY;
19708
- });
19709
- if (boardsWithoutPosition.length > 1) {
19732
+ if (layoutMode === "none" && gridItems.length > 1) {
19733
+ const unpositionedItems = gridItems.filter(
19734
+ (c) => !c._hasUserDefinedPcbPosition()
19735
+ );
19736
+ if (unpositionedItems.length > 1) {
19710
19737
  this.root.db.pcb_placement_error.insert({
19711
19738
  error_type: "pcb_placement_error",
19712
- message: `Multiple boards in ${this._errorComponentName} without pcbX/pcbY positions. When layoutMode="none", each board must have explicit pcbX and pcbY coordinates to avoid overlapping. Either set pcbX/pcbY on each board, or use layoutMode="grid" for automatic positioning.`
19739
+ message: `Multiple boards/subpanels in ${this._errorComponentName} without positions. When layoutMode="none", each item must have explicit positioning. Use layoutMode="grid" for automatic positioning.`
19713
19740
  });
19714
19741
  }
19715
19742
  }
@@ -19743,8 +19770,8 @@ var Subpanel = class _Subpanel extends Group6 {
19743
19770
  availablePanelWidth = panelWidth - edgePaddingLeft - edgePaddingRight;
19744
19771
  availablePanelHeight = panelHeight - edgePaddingTop - edgePaddingBottom;
19745
19772
  }
19746
- const { positions, gridWidth, gridHeight } = packBoardsIntoGrid({
19747
- boards: childBoardInstances,
19773
+ const { positions, gridWidth, gridHeight } = packIntoGrid({
19774
+ items: gridItems,
19748
19775
  row: this._parsedProps.row,
19749
19776
  col: this._parsedProps.col,
19750
19777
  cellWidth: this._parsedProps.cellWidth,
@@ -19755,28 +19782,40 @@ var Subpanel = class _Subpanel extends Group6 {
19755
19782
  });
19756
19783
  this._cachedGridWidth = gridWidth;
19757
19784
  this._cachedGridHeight = gridHeight;
19758
- for (const { board, pos } of positions) {
19759
- board._panelPositionOffset = pos;
19785
+ for (const { item, pos } of positions) {
19786
+ item._panelPositionOffset = pos;
19760
19787
  }
19761
19788
  }
19762
19789
  doInitialPanelLayout() {
19763
19790
  if (this.root?.pcbDisabled) return;
19764
19791
  const { db } = this.root;
19765
- const childBoardInstances = this._getDirectBoardChildren();
19766
19792
  const layoutMode = this._parsedProps.layoutMode ?? "none";
19767
19793
  if (layoutMode === "grid") {
19768
- for (const board of childBoardInstances) {
19769
- if (!board.pcb_board_id || !board._panelPositionOffset) continue;
19770
- db.pcb_board.update(board.pcb_board_id, {
19771
- position_mode: "relative_to_panel_anchor",
19772
- display_offset_x: `${board._panelPositionOffset.x}mm`,
19773
- display_offset_y: `${board._panelPositionOffset.y}mm`
19774
- });
19794
+ for (const child of this.children) {
19795
+ if (child instanceof Board) {
19796
+ if (!child.pcb_board_id || !child._panelPositionOffset) continue;
19797
+ db.pcb_board.update(child.pcb_board_id, {
19798
+ position_mode: "relative_to_panel_anchor",
19799
+ display_offset_x: `${child._panelPositionOffset.x}mm`,
19800
+ display_offset_y: `${child._panelPositionOffset.y}mm`
19801
+ });
19802
+ } else if (child instanceof _Subpanel && child._panelPositionOffset) {
19803
+ for (const board of child._getAllBoardInstances()) {
19804
+ if (!board.pcb_board_id) continue;
19805
+ const boardOffset = board._panelPositionOffset ?? { x: 0, y: 0 };
19806
+ db.pcb_board.update(board.pcb_board_id, {
19807
+ position_mode: "relative_to_panel_anchor",
19808
+ display_offset_x: `${child._panelPositionOffset.x + boardOffset.x}mm`,
19809
+ display_offset_y: `${child._panelPositionOffset.y + boardOffset.y}mm`
19810
+ });
19811
+ }
19812
+ }
19775
19813
  }
19776
19814
  this._updatePanelDimensions();
19777
19815
  } else {
19778
19816
  const panelGlobalPos = this._getGlobalPcbPositionBeforeLayout();
19779
- for (const board of childBoardInstances) {
19817
+ for (const board of this._getDirectBoardChildren()) {
19818
+ if (!board.pcb_board_id) continue;
19780
19819
  const boardDb = db.pcb_board.get(board.pcb_board_id);
19781
19820
  if (!boardDb) continue;
19782
19821
  const relativeX = boardDb.center.x - panelGlobalPos.x;
@@ -21076,8 +21115,8 @@ var BreakoutPoint = class extends PrimitiveComponent2 {
21076
21115
  import { netLabelProps } from "@tscircuit/props";
21077
21116
  import {
21078
21117
  applyToPoint as applyToPoint19,
21079
- identity as identity6,
21080
- translate as translate8
21118
+ identity as identity7,
21119
+ translate as translate9
21081
21120
  } from "transformation-matrix";
21082
21121
  import { calculateElbow as calculateElbow2 } from "calculate-elbow";
21083
21122
  var NetLabel = class extends PrimitiveComponent2 {
@@ -21127,10 +21166,10 @@ var NetLabel = class extends PrimitiveComponent2 {
21127
21166
  if (connectedPorts.length > 0) {
21128
21167
  const portPos = connectedPorts[0]._getGlobalSchematicPositionBeforeLayout();
21129
21168
  const parentCenter = applyToPoint19(
21130
- this.parent?.computeSchematicGlobalTransform?.() ?? identity6(),
21169
+ this.parent?.computeSchematicGlobalTransform?.() ?? identity7(),
21131
21170
  { x: 0, y: 0 }
21132
21171
  );
21133
- return translate8(portPos.x - parentCenter.x, portPos.y - parentCenter.y);
21172
+ return translate9(portPos.x - parentCenter.x, portPos.y - parentCenter.y);
21134
21173
  }
21135
21174
  }
21136
21175
  return super.computeSchematicPropsTransform();
@@ -23317,7 +23356,7 @@ var SchematicCell = class extends PrimitiveComponent2 {
23317
23356
 
23318
23357
  // lib/components/primitive-components/Symbol/Symbol.ts
23319
23358
  import { symbolProps } from "@tscircuit/props";
23320
- import { compose as compose8, translate as translate9, scale as scale2 } from "transformation-matrix";
23359
+ import { compose as compose9, translate as translate10, scale as scale2 } from "transformation-matrix";
23321
23360
  var SymbolComponent = class extends PrimitiveComponent2 {
23322
23361
  isPrimitiveContainer = true;
23323
23362
  schematic_symbol_id;
@@ -23427,10 +23466,10 @@ var SymbolComponent = class extends PrimitiveComponent2 {
23427
23466
  const scaleX = targetWidth !== void 0 && currentWidth > 0 ? targetWidth / currentWidth : 1;
23428
23467
  const scaleY = targetHeight !== void 0 && currentHeight > 0 ? targetHeight / currentHeight : 1;
23429
23468
  const globalPos = this._getGlobalSchematicPositionBeforeLayout();
23430
- this.userCoordinateToResizedSymbolTransformMat = compose8(
23431
- translate9(globalPos.x, globalPos.y),
23469
+ this.userCoordinateToResizedSymbolTransformMat = compose9(
23470
+ translate10(globalPos.x, globalPos.y),
23432
23471
  scale2(scaleX, scaleY),
23433
- translate9(-currentCenterX, -currentCenterY)
23472
+ translate10(-currentCenterX, -currentCenterY)
23434
23473
  );
23435
23474
  }
23436
23475
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.1073",
4
+ "version": "0.0.1075",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -35,7 +35,7 @@
35
35
  "@tscircuit/alphabet": "0.0.18",
36
36
  "@tscircuit/capacity-autorouter": "^0.0.299",
37
37
  "@tscircuit/checks": "0.0.100",
38
- "@tscircuit/circuit-json-util": "^0.0.80",
38
+ "@tscircuit/circuit-json-util": "^0.0.81",
39
39
  "@tscircuit/common": "^0.0.20",
40
40
  "@tscircuit/copper-pour-solver": "^0.0.20",
41
41
  "@tscircuit/footprinter": "^0.0.316",
@@ -45,7 +45,7 @@
45
45
  "@tscircuit/math-utils": "^0.0.29",
46
46
  "@tscircuit/miniflex": "^0.0.4",
47
47
  "@tscircuit/ngspice-spice-engine": "^0.0.8",
48
- "@tscircuit/props": "^0.0.485",
48
+ "@tscircuit/props": "^0.0.487",
49
49
  "@tscircuit/schematic-match-adapt": "^0.0.16",
50
50
  "@tscircuit/schematic-trace-solver": "^v0.0.45",
51
51
  "@tscircuit/solver-utils": "^0.0.3",