@tscircuit/core 0.0.871 → 0.0.873

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.js CHANGED
@@ -86,7 +86,7 @@ __export(components_exports, {
86
86
  // lib/components/base-components/NormalComponent/NormalComponent.ts
87
87
  import { fp } from "@tscircuit/footprinter";
88
88
  import {
89
- distance as distance5,
89
+ distance as distance7,
90
90
  pcb_manual_edit_conflict_warning,
91
91
  pcb_component_invalid_layer_error,
92
92
  point3 as point32,
@@ -1937,6 +1937,7 @@ var SmtPad = class extends PrimitiveComponent2 {
1937
1937
  const { _parsedProps: props } = this;
1938
1938
  const isCoveredWithSolderMask = props.coveredWithSolderMask ?? false;
1939
1939
  const shouldCreateSolderPaste = !isCoveredWithSolderMask;
1940
+ const soldermaskMargin = props.solderMaskMargin;
1940
1941
  const subcircuit = this.getSubcircuit();
1941
1942
  const position = this._getGlobalPcbPositionBeforeLayout();
1942
1943
  const globalTransform = this._computePcbGlobalTransformBeforeLayout();
@@ -1967,6 +1968,7 @@ var SmtPad = class extends PrimitiveComponent2 {
1967
1968
  radius: props.radius,
1968
1969
  port_hints: portHints,
1969
1970
  is_covered_with_solder_mask: isCoveredWithSolderMask,
1971
+ soldermask_margin: soldermaskMargin,
1970
1972
  x: position.x,
1971
1973
  y: position.y,
1972
1974
  subcircuit_id: subcircuit?.subcircuit_id ?? void 0
@@ -1999,6 +2001,7 @@ var SmtPad = class extends PrimitiveComponent2 {
1999
2001
  ccw_rotation: finalRotationDegrees,
2000
2002
  port_hints: portHints,
2001
2003
  is_covered_with_solder_mask: isCoveredWithSolderMask,
2004
+ soldermask_margin: soldermaskMargin,
2002
2005
  subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
2003
2006
  pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0
2004
2007
  });
@@ -2013,6 +2016,7 @@ var SmtPad = class extends PrimitiveComponent2 {
2013
2016
  corner_radius: props.cornerRadius ?? void 0,
2014
2017
  port_hints: portHints,
2015
2018
  is_covered_with_solder_mask: isCoveredWithSolderMask,
2019
+ soldermask_margin: soldermaskMargin,
2016
2020
  x: position.x,
2017
2021
  y: position.y,
2018
2022
  subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
@@ -2066,6 +2070,7 @@ var SmtPad = class extends PrimitiveComponent2 {
2066
2070
  ccw_rotation: padRotation,
2067
2071
  port_hints: portHints,
2068
2072
  is_covered_with_solder_mask: isCoveredWithSolderMask,
2073
+ soldermask_margin: soldermaskMargin,
2069
2074
  subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
2070
2075
  pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0
2071
2076
  });
@@ -2103,6 +2108,7 @@ var SmtPad = class extends PrimitiveComponent2 {
2103
2108
  points: transformedPoints,
2104
2109
  port_hints: portHints,
2105
2110
  is_covered_with_solder_mask: isCoveredWithSolderMask,
2111
+ soldermask_margin: soldermaskMargin,
2106
2112
  subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
2107
2113
  pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0
2108
2114
  });
@@ -2120,6 +2126,7 @@ var SmtPad = class extends PrimitiveComponent2 {
2120
2126
  width: props.width,
2121
2127
  port_hints: portHints,
2122
2128
  is_covered_with_solder_mask: isCoveredWithSolderMask,
2129
+ soldermask_margin: soldermaskMargin,
2123
2130
  subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
2124
2131
  pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0
2125
2132
  });
@@ -2407,6 +2414,7 @@ var PcbTrace = class extends PrimitiveComponent2 {
2407
2414
 
2408
2415
  // lib/components/primitive-components/PlatedHole.ts
2409
2416
  import { platedHoleProps } from "@tscircuit/props";
2417
+ import "circuit-json";
2410
2418
  var PlatedHole = class extends PrimitiveComponent2 {
2411
2419
  pcb_plated_hole_id = null;
2412
2420
  matchedPort = null;
@@ -2502,6 +2510,8 @@ var PlatedHole = class extends PrimitiveComponent2 {
2502
2510
  const position = this._getGlobalPcbPositionBeforeLayout();
2503
2511
  const pcb_component_id = this.parent?.pcb_component_id ?? this.getPrimitiveContainer()?.pcb_component_id;
2504
2512
  const subcircuit = this.getSubcircuit();
2513
+ const soldermaskMargin = props.solderMaskMargin;
2514
+ const isCoveredWithSolderMask = props.coveredWithSolderMask ?? false;
2505
2515
  if (props.shape === "circle") {
2506
2516
  const pcb_plated_hole = db.pcb_plated_hole.insert({
2507
2517
  pcb_component_id,
@@ -2514,6 +2524,8 @@ var PlatedHole = class extends PrimitiveComponent2 {
2514
2524
  x: position.x,
2515
2525
  y: position.y,
2516
2526
  layers: ["top", "bottom"],
2527
+ soldermask_margin: soldermaskMargin,
2528
+ is_covered_with_solder_mask: isCoveredWithSolderMask,
2517
2529
  subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
2518
2530
  pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0
2519
2531
  });
@@ -2553,6 +2565,8 @@ var PlatedHole = class extends PrimitiveComponent2 {
2553
2565
  x: position.x,
2554
2566
  y: position.y,
2555
2567
  layers: ["top", "bottom"],
2568
+ soldermask_margin: soldermaskMargin,
2569
+ is_covered_with_solder_mask: isCoveredWithSolderMask,
2556
2570
  subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
2557
2571
  pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0,
2558
2572
  hole_shape: "rotated_pill",
@@ -2578,6 +2592,8 @@ var PlatedHole = class extends PrimitiveComponent2 {
2578
2592
  x: position.x,
2579
2593
  y: position.y,
2580
2594
  layers: ["top", "bottom"],
2595
+ soldermask_margin: soldermaskMargin,
2596
+ is_covered_with_solder_mask: isCoveredWithSolderMask,
2581
2597
  subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
2582
2598
  pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0,
2583
2599
  ccw_rotation: props.pcbRotation ?? 0
@@ -2618,6 +2634,8 @@ var PlatedHole = class extends PrimitiveComponent2 {
2618
2634
  x: position.x,
2619
2635
  y: position.y,
2620
2636
  layers: ["top", "bottom"],
2637
+ soldermask_margin: soldermaskMargin,
2638
+ is_covered_with_solder_mask: isCoveredWithSolderMask,
2621
2639
  subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
2622
2640
  pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0,
2623
2641
  hole_offset_x: props.holeOffsetX,
@@ -2640,6 +2658,8 @@ var PlatedHole = class extends PrimitiveComponent2 {
2640
2658
  x: position.x,
2641
2659
  y: position.y,
2642
2660
  layers: ["top", "bottom"],
2661
+ soldermask_margin: soldermaskMargin,
2662
+ is_covered_with_solder_mask: isCoveredWithSolderMask,
2643
2663
  subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
2644
2664
  pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0
2645
2665
  });
@@ -2668,6 +2688,8 @@ var PlatedHole = class extends PrimitiveComponent2 {
2668
2688
  x: position.x,
2669
2689
  y: position.y,
2670
2690
  layers: ["top", "bottom"],
2691
+ soldermask_margin: soldermaskMargin,
2692
+ is_covered_with_solder_mask: isCoveredWithSolderMask,
2671
2693
  subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
2672
2694
  pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0
2673
2695
  });
@@ -2741,6 +2763,7 @@ var Keepout = class extends PrimitiveComponent2 {
2741
2763
 
2742
2764
  // lib/components/primitive-components/Hole.ts
2743
2765
  import { holeProps } from "@tscircuit/props";
2766
+ import "circuit-json";
2744
2767
  var Hole = class extends PrimitiveComponent2 {
2745
2768
  pcb_hole_id = null;
2746
2769
  isPcbPrimitive = true;
@@ -2777,6 +2800,8 @@ var Hole = class extends PrimitiveComponent2 {
2777
2800
  const { _parsedProps: props } = this;
2778
2801
  const subcircuit = this.getSubcircuit();
2779
2802
  const position = this._getGlobalPcbPositionBeforeLayout();
2803
+ const soldermaskMargin = props.solderMaskMargin;
2804
+ const isCoveredWithSolderMask = props.coveredWithSolderMask ?? false;
2780
2805
  if (props.shape === "pill") {
2781
2806
  if (props.pcbRotation && props.pcbRotation !== 0) {
2782
2807
  const inserted_hole = db.pcb_hole.insert({
@@ -2787,6 +2812,8 @@ var Hole = class extends PrimitiveComponent2 {
2787
2812
  x: position.x,
2788
2813
  y: position.y,
2789
2814
  ccw_rotation: props.pcbRotation,
2815
+ soldermask_margin: soldermaskMargin,
2816
+ is_covered_with_solder_mask: isCoveredWithSolderMask,
2790
2817
  subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
2791
2818
  pcb_group_id: subcircuit?.getGroup()?.pcb_group_id ?? void 0
2792
2819
  });
@@ -2799,6 +2826,8 @@ var Hole = class extends PrimitiveComponent2 {
2799
2826
  hole_height: props.height,
2800
2827
  x: position.x,
2801
2828
  y: position.y,
2829
+ soldermask_margin: soldermaskMargin,
2830
+ is_covered_with_solder_mask: isCoveredWithSolderMask,
2802
2831
  subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
2803
2832
  pcb_group_id: subcircuit?.getGroup()?.pcb_group_id ?? void 0
2804
2833
  });
@@ -2812,6 +2841,8 @@ var Hole = class extends PrimitiveComponent2 {
2812
2841
  hole_height: props.height,
2813
2842
  x: position.x,
2814
2843
  y: position.y,
2844
+ soldermask_margin: soldermaskMargin,
2845
+ is_covered_with_solder_mask: isCoveredWithSolderMask,
2815
2846
  subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
2816
2847
  pcb_group_id: subcircuit?.getGroup()?.pcb_group_id ?? void 0
2817
2848
  });
@@ -2823,6 +2854,8 @@ var Hole = class extends PrimitiveComponent2 {
2823
2854
  hole_diameter: props.diameter,
2824
2855
  x: position.x,
2825
2856
  y: position.y,
2857
+ soldermask_margin: soldermaskMargin,
2858
+ is_covered_with_solder_mask: isCoveredWithSolderMask,
2826
2859
  subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
2827
2860
  pcb_group_id: subcircuit?.getGroup()?.pcb_group_id ?? void 0
2828
2861
  });
@@ -4679,7 +4712,7 @@ var Footprint = class extends PrimitiveComponent2 {
4679
4712
  // lib/components/primitive-components/CadModel.ts
4680
4713
  import { cadmodelProps, point3 } from "@tscircuit/props";
4681
4714
  import { z as z7 } from "zod";
4682
- import { distance as distance2 } from "circuit-json";
4715
+ import { distance as distance4 } from "circuit-json";
4683
4716
  import { decomposeTSR as decomposeTSR4 } from "transformation-matrix";
4684
4717
 
4685
4718
  // lib/components/base-components/NormalComponent/utils/getFileExtension.ts
@@ -4756,7 +4789,7 @@ var CadModel = class extends PrimitiveComponent2 {
4756
4789
  z: props.pcbZ ?? 0,
4757
4790
  ...typeof props.positionOffset === "object" ? props.positionOffset : {}
4758
4791
  });
4759
- const zOffsetFromSurface = props.zOffsetFromSurface !== void 0 ? distance2.parse(props.zOffsetFromSurface) : 0;
4792
+ const zOffsetFromSurface = props.zOffsetFromSurface !== void 0 ? distance4.parse(props.zOffsetFromSurface) : 0;
4760
4793
  const layer = parent.props.layer === "bottom" ? "bottom" : "top";
4761
4794
  const ext = props.modelUrl ? getFileExtension(props.modelUrl) : void 0;
4762
4795
  const urlProps = {};
@@ -5069,7 +5102,7 @@ var getEnteringEdgeFromDirection = (direction) => {
5069
5102
  };
5070
5103
 
5071
5104
  // lib/utils/schematic/getStubEdges.ts
5072
- import { distance as distance3 } from "@tscircuit/math-utils";
5105
+ import { distance as distance5 } from "@tscircuit/math-utils";
5073
5106
  var getStubEdges = ({
5074
5107
  firstEdge,
5075
5108
  firstEdgePort,
@@ -5116,7 +5149,7 @@ var getStubEdges = ({
5116
5149
  });
5117
5150
  }
5118
5151
  }
5119
- edges = edges.filter((e) => distance3(e.from, e.to) > 0.01);
5152
+ edges = edges.filter((e) => distance5(e.from, e.to) > 0.01);
5120
5153
  return edges;
5121
5154
  };
5122
5155
 
@@ -5658,7 +5691,7 @@ import { calculateElbow } from "calculate-elbow";
5658
5691
  import { doesLineIntersectLine as doesLineIntersectLine3 } from "@tscircuit/math-utils";
5659
5692
 
5660
5693
  // lib/components/primitive-components/Trace/trace-utils/create-schematic-trace-crossing-segments.ts
5661
- import { distance as distance4, doesLineIntersectLine } from "@tscircuit/math-utils";
5694
+ import { distance as distance6, doesLineIntersectLine } from "@tscircuit/math-utils";
5662
5695
 
5663
5696
  // lib/components/primitive-components/Trace/trace-utils/get-other-schematic-traces.ts
5664
5697
  var getOtherSchematicTraces = ({
@@ -5725,7 +5758,7 @@ var createSchematicTraceCrossingSegments = ({
5725
5758
  otherEdgesIntersections.push({
5726
5759
  otherEdge,
5727
5760
  crossingPoint: crossingPoint2,
5728
- distanceFromEdgeFrom: distance4(edge.from, crossingPoint2)
5761
+ distanceFromEdgeFrom: distance6(edge.from, crossingPoint2)
5729
5762
  });
5730
5763
  }
5731
5764
  }
@@ -5750,7 +5783,7 @@ var createSchematicTraceCrossingSegments = ({
5750
5783
  x: crossingPoint.x + crossingUnitVec.x * crossingSegmentLength / 2,
5751
5784
  y: crossingPoint.y + crossingUnitVec.y * crossingSegmentLength / 2
5752
5785
  };
5753
- const overshot = distance4(afterCrossing, edge.to) < crossingSegmentLength;
5786
+ const overshot = distance6(afterCrossing, edge.to) < crossingSegmentLength;
5754
5787
  const newEdges = [
5755
5788
  { from: edge.from, to: beforeCrossing },
5756
5789
  { from: beforeCrossing, to: afterCrossing, is_crossing: true },
@@ -8740,7 +8773,7 @@ var NormalComponent3 = class extends PrimitiveComponent2 {
8740
8773
  z: 0,
8741
8774
  ...typeof cadModel?.positionOffset === "object" ? cadModel.positionOffset : {}
8742
8775
  });
8743
- const zOffsetFromSurface = cadModel && typeof cadModel === "object" && "zOffsetFromSurface" in cadModel ? cadModel.zOffsetFromSurface !== void 0 ? distance5.parse(
8776
+ const zOffsetFromSurface = cadModel && typeof cadModel === "object" && "zOffsetFromSurface" in cadModel ? cadModel.zOffsetFromSurface !== void 0 ? distance7.parse(
8744
8777
  cadModel.zOffsetFromSurface
8745
8778
  ) : 0 : 0;
8746
8779
  const computedLayer = this.props.layer === "bottom" ? "bottom" : "top";
@@ -9164,7 +9197,7 @@ var CapacityMeshAutorouter = class {
9164
9197
 
9165
9198
  // lib/components/primitive-components/Group/Group.ts
9166
9199
  import {
9167
- distance as distance6
9200
+ distance as distance8
9168
9201
  } from "circuit-json";
9169
9202
  import Debug13 from "debug";
9170
9203
  import "zod";
@@ -13193,8 +13226,8 @@ var Group6 = class extends NormalComponent3 {
13193
13226
  const groupProps2 = props;
13194
13227
  const hasOutline = groupProps2.outline && groupProps2.outline.length > 0;
13195
13228
  const numericOutline = hasOutline ? groupProps2.outline.map((point) => ({
13196
- x: distance6.parse(point.x),
13197
- y: distance6.parse(point.y)
13229
+ x: distance8.parse(point.x),
13230
+ y: distance8.parse(point.y)
13198
13231
  })) : void 0;
13199
13232
  const pcb_group = db.pcb_group.insert({
13200
13233
  is_subcircuit: this.isSubcircuit,
@@ -13224,8 +13257,8 @@ var Group6 = class extends NormalComponent3 {
13224
13257
  const hasExplicitPositioning = this._parsedProps.pcbX !== void 0 || this._parsedProps.pcbY !== void 0;
13225
13258
  if (hasOutline) {
13226
13259
  const numericOutline = props.outline.map((point) => ({
13227
- x: distance6.parse(point.x),
13228
- y: distance6.parse(point.y)
13260
+ x: distance8.parse(point.x),
13261
+ y: distance8.parse(point.y)
13229
13262
  }));
13230
13263
  const outlineBounds = getBoundsFromPoints3(numericOutline);
13231
13264
  if (!outlineBounds) return;
@@ -14297,17 +14330,12 @@ var Board = class extends Group6 {
14297
14330
 
14298
14331
  // lib/components/normal-components/Panel.ts
14299
14332
  import { panelProps } from "@tscircuit/props";
14300
- import { distance as distance7 } from "circuit-json";
14333
+ import { distance as distance9 } from "circuit-json";
14301
14334
 
14302
14335
  // lib/utils/panels/generate-panel-tabs-and-mouse-bites.ts
14303
- var TAB_CONFIG = {
14304
- TAB_WIDTH: 4,
14305
- TAB_DEPTH: 0.5,
14306
- TAB_TO_SPACE_RATIO: 5,
14307
- MOUSE_BITE_DIAMETER: 0.2,
14308
- MOUSE_BITE_SPACING: 0.1,
14309
- MOUSE_BITES_PER_GAP: 5
14310
- };
14336
+ var DEFAULT_PANEL_MARGIN = 5;
14337
+ var DEFAULT_TAB_LENGTH = 5;
14338
+ var DEFAULT_TAB_WIDTH = 2;
14311
14339
  function rectanglesOverlap(rect1, rect2) {
14312
14340
  const r1Left = rect1.center.x - rect1.width / 2;
14313
14341
  const r1Right = rect1.center.x + rect1.width / 2;
@@ -14330,7 +14358,12 @@ function pointOverlapsRectangle(point, radius, rect) {
14330
14358
  const distanceY = point.y - closestY;
14331
14359
  return distanceX * distanceX + distanceY * distanceY <= radius * radius;
14332
14360
  }
14333
- function generateTabsForEdge(board, edge, existingTabs, otherBoards) {
14361
+ function generateTabsForEdge({
14362
+ board,
14363
+ edge,
14364
+ otherBoards,
14365
+ options
14366
+ }) {
14334
14367
  const tabs = [];
14335
14368
  if (!board.width || !board.height) return tabs;
14336
14369
  const boardLeft = board.center.x - board.width / 2;
@@ -14349,9 +14382,15 @@ function generateTabsForEdge(board, edge, existingTabs, otherBoards) {
14349
14382
  isHorizontal = false;
14350
14383
  edgeCenter = edge === "right" ? boardRight : boardLeft;
14351
14384
  }
14352
- const totalTabWidth = TAB_CONFIG.TAB_WIDTH;
14353
- const minSpacingForMouseBites = TAB_CONFIG.MOUSE_BITES_PER_GAP * TAB_CONFIG.MOUSE_BITE_DIAMETER + (TAB_CONFIG.MOUSE_BITES_PER_GAP - 1) * TAB_CONFIG.MOUSE_BITE_SPACING;
14354
- const fixedSpacing = minSpacingForMouseBites * 1.1;
14385
+ const totalTabWidth = options.tabLength;
14386
+ let fixedSpacing = options.boardGap;
14387
+ if (options.mouseBites) {
14388
+ const mouseBiteDiameter = options.tabWidth * 0.45;
14389
+ const mouseBiteSpacing = mouseBiteDiameter * 0.1;
14390
+ const mouseBitesPerGap = Math.max(2, Math.ceil(options.tabLength / 2));
14391
+ const minSpacingForMouseBites = mouseBitesPerGap * mouseBiteDiameter + (mouseBitesPerGap - 1) * mouseBiteSpacing;
14392
+ fixedSpacing = minSpacingForMouseBites * 1.1;
14393
+ }
14355
14394
  let numTabs = Math.floor(
14356
14395
  (edgeLength - fixedSpacing) / (totalTabWidth + fixedSpacing)
14357
14396
  );
@@ -14376,13 +14415,13 @@ function generateTabsForEdge(board, edge, existingTabs, otherBoards) {
14376
14415
  axisStart = Math.max(axisStart, boardStart);
14377
14416
  axisEnd = Math.min(axisEnd, boardEnd);
14378
14417
  if (isCornerTab) {
14379
- if (isFirstTab) axisStart -= TAB_CONFIG.TAB_DEPTH;
14380
- if (isLastTab) axisEnd += TAB_CONFIG.TAB_DEPTH;
14418
+ if (isFirstTab) axisStart -= options.tabWidth;
14419
+ if (isLastTab) axisEnd += options.tabWidth;
14381
14420
  }
14382
14421
  if (axisEnd <= axisStart) continue;
14383
14422
  const axisCenterOffset = (axisStart + axisEnd) / 2;
14384
14423
  const axisLength = axisEnd - axisStart;
14385
- const crossAxisOffset = edge === "top" || edge === "right" ? TAB_CONFIG.TAB_DEPTH / 2 : -TAB_CONFIG.TAB_DEPTH / 2;
14424
+ const crossAxisOffset = edge === "top" || edge === "right" ? options.tabWidth / 2 : -options.tabWidth / 2;
14386
14425
  const tabCenter = isHorizontal ? {
14387
14426
  x: board.center.x + axisCenterOffset,
14388
14427
  y: edgeCenter + crossAxisOffset
@@ -14390,8 +14429,8 @@ function generateTabsForEdge(board, edge, existingTabs, otherBoards) {
14390
14429
  x: edgeCenter + crossAxisOffset,
14391
14430
  y: board.center.y + axisCenterOffset
14392
14431
  };
14393
- const tabWidth = isHorizontal ? axisLength : TAB_CONFIG.TAB_DEPTH;
14394
- const tabHeight = isHorizontal ? TAB_CONFIG.TAB_DEPTH : axisLength;
14432
+ const tabWidth = isHorizontal ? axisLength : options.tabWidth;
14433
+ const tabHeight = isHorizontal ? options.tabWidth : axisLength;
14395
14434
  const newTab = {
14396
14435
  center: tabCenter,
14397
14436
  width: tabWidth,
@@ -14416,7 +14455,13 @@ function generateTabsForEdge(board, edge, existingTabs, otherBoards) {
14416
14455
  }
14417
14456
  return tabs;
14418
14457
  }
14419
- function generateMouseBitesForEdge(board, edge, edgeTabs, allTabs, allBoards, existingMouseBites) {
14458
+ function generateMouseBitesForEdge({
14459
+ board,
14460
+ edge,
14461
+ edgeTabs,
14462
+ allBoards,
14463
+ options
14464
+ }) {
14420
14465
  const mouseBites = [];
14421
14466
  if (edgeTabs.length === 0) return mouseBites;
14422
14467
  if (!board.width || !board.height) return mouseBites;
@@ -14425,8 +14470,11 @@ function generateMouseBitesForEdge(board, edge, edgeTabs, allTabs, allBoards, ex
14425
14470
  const boardBottom = board.center.y - board.height / 2;
14426
14471
  const boardTop = board.center.y + board.height / 2;
14427
14472
  const isHorizontal = edge === "top" || edge === "bottom";
14473
+ const mouseBiteDiameter = options.tabWidth * 0.45;
14474
+ const mouseBiteSpacing = mouseBiteDiameter * 0.1;
14475
+ const mouseBitesPerGap = Math.max(2, Math.ceil(options.tabLength / 2));
14428
14476
  let mouseBitePosition;
14429
- const radius = TAB_CONFIG.MOUSE_BITE_DIAMETER / 2;
14477
+ const radius = mouseBiteDiameter / 2;
14430
14478
  if (edge === "top") {
14431
14479
  mouseBitePosition = boardTop;
14432
14480
  } else if (edge === "bottom") {
@@ -14456,14 +14504,14 @@ function generateMouseBitesForEdge(board, edge, edgeTabs, allTabs, allBoards, ex
14456
14504
  gapEnd = tab2.center.y - tab2.height / 2;
14457
14505
  }
14458
14506
  const gapLength = gapEnd - gapStart;
14459
- const totalMouseBiteWidth = TAB_CONFIG.MOUSE_BITES_PER_GAP * TAB_CONFIG.MOUSE_BITE_DIAMETER;
14460
- const totalSpacing = (TAB_CONFIG.MOUSE_BITES_PER_GAP - 1) * TAB_CONFIG.MOUSE_BITE_SPACING;
14507
+ const totalMouseBiteWidth = mouseBitesPerGap * mouseBiteDiameter;
14508
+ const totalSpacing = (mouseBitesPerGap - 1) * mouseBiteSpacing;
14461
14509
  if (gapLength < totalMouseBiteWidth + totalSpacing) continue;
14462
14510
  const gapCenter = (gapStart + gapEnd) / 2;
14463
- for (let j = 0; j < TAB_CONFIG.MOUSE_BITES_PER_GAP; j++) {
14464
- const posOffset = (j - (TAB_CONFIG.MOUSE_BITES_PER_GAP - 1) / 2) * (TAB_CONFIG.MOUSE_BITE_DIAMETER + TAB_CONFIG.MOUSE_BITE_SPACING);
14511
+ for (let j = 0; j < mouseBitesPerGap; j++) {
14512
+ const posOffset = (j - (mouseBitesPerGap - 1) / 2) * (mouseBiteDiameter + mouseBiteSpacing);
14465
14513
  const newMouseBite = isHorizontal ? { x: gapCenter + posOffset, y: mouseBitePosition } : { x: mouseBitePosition, y: gapCenter + posOffset };
14466
- const radius2 = TAB_CONFIG.MOUSE_BITE_DIAMETER / 2;
14514
+ const radius2 = mouseBiteDiameter / 2;
14467
14515
  let overlapsBoard = false;
14468
14516
  for (const otherBoard of allBoards) {
14469
14517
  if (!otherBoard.width || !otherBoard.height) continue;
@@ -14483,45 +14531,50 @@ function generateMouseBitesForEdge(board, edge, edgeTabs, allTabs, allBoards, ex
14483
14531
  }
14484
14532
  return mouseBites;
14485
14533
  }
14486
- function generatePanelTabsAndMouseBites(boards) {
14534
+ function generatePanelTabsAndMouseBites(boards, options) {
14487
14535
  const allTabCutouts = [];
14488
14536
  const allMouseBites = [];
14489
14537
  for (let boardIndex = 0; boardIndex < boards.length; boardIndex++) {
14490
14538
  const board = boards[boardIndex];
14491
14539
  const otherBoards = boards.filter((_, i) => i !== boardIndex);
14492
14540
  for (const edge of ["top", "bottom", "left", "right"]) {
14493
- const edgeTabs = generateTabsForEdge(
14494
- board,
14495
- edge,
14496
- allTabCutouts,
14497
- otherBoards
14498
- );
14499
- allTabCutouts.push(...edgeTabs);
14500
- const edgeMouseBites = generateMouseBitesForEdge(
14541
+ const edgeTabs = generateTabsForEdge({
14501
14542
  board,
14502
14543
  edge,
14503
- edgeTabs,
14504
- allTabCutouts,
14505
14544
  otherBoards,
14506
- allMouseBites
14507
- );
14508
- allMouseBites.push(...edgeMouseBites);
14545
+ options
14546
+ });
14547
+ allTabCutouts.push(...edgeTabs);
14548
+ if (options.mouseBites) {
14549
+ const edgeMouseBites = generateMouseBitesForEdge({
14550
+ board,
14551
+ edge,
14552
+ edgeTabs,
14553
+ allBoards: otherBoards,
14554
+ options
14555
+ });
14556
+ allMouseBites.push(...edgeMouseBites);
14557
+ }
14509
14558
  }
14510
14559
  }
14511
- const tabCutouts = allTabCutouts.map((tab, index) => ({
14512
- type: "pcb_cutout",
14513
- pcb_cutout_id: `panel_tab_${index}`,
14514
- shape: "rect",
14515
- center: tab.center,
14516
- width: tab.width,
14517
- height: tab.height,
14518
- corner_radius: 0.25
14519
- }));
14560
+ const tabCutouts = allTabCutouts.map((tab, index) => {
14561
+ const tabWidthDimension = Math.min(tab.width, tab.height);
14562
+ return {
14563
+ type: "pcb_cutout",
14564
+ pcb_cutout_id: `panel_tab_${index}`,
14565
+ shape: "rect",
14566
+ center: tab.center,
14567
+ width: tab.width,
14568
+ height: tab.height,
14569
+ corner_radius: tabWidthDimension / 2
14570
+ };
14571
+ });
14572
+ const mouseBiteDiameter = options.tabWidth * 0.45;
14520
14573
  const mouseBiteHoles = allMouseBites.map((bite, index) => ({
14521
14574
  type: "pcb_hole",
14522
14575
  pcb_hole_id: `panel_mouse_bite_${index}`,
14523
14576
  hole_shape: "circle",
14524
- hole_diameter: TAB_CONFIG.MOUSE_BITE_DIAMETER,
14577
+ hole_diameter: mouseBiteDiameter,
14525
14578
  x: bite.x,
14526
14579
  y: bite.y
14527
14580
  }));
@@ -14567,6 +14620,8 @@ var Panel = class extends Group6 {
14567
14620
  (b) => b.props.pcbX === void 0 && b.props.pcbY === void 0
14568
14621
  );
14569
14622
  if (unpositionedBoards.length > 0 && !hasAnyPositionedBoards) {
14623
+ const tabWidth = this._parsedProps.tabWidth ?? DEFAULT_TAB_WIDTH;
14624
+ const boardGap = this._parsedProps.boardGap ?? tabWidth;
14570
14625
  const gridCols = Math.ceil(Math.sqrt(unpositionedBoards.length));
14571
14626
  const gridRows = Math.ceil(unpositionedBoards.length / gridCols);
14572
14627
  const colWidths = Array(gridCols).fill(0);
@@ -14580,17 +14635,17 @@ var Panel = class extends Group6 {
14580
14635
  colWidths[col] = Math.max(colWidths[col], pcbBoard.width);
14581
14636
  rowHeights[row] = Math.max(rowHeights[row], pcbBoard.height);
14582
14637
  });
14583
- const totalGridWidth = colWidths.reduce((a, b) => a + b, 0) + (gridCols > 1 ? (gridCols - 1) * TAB_CONFIG.TAB_DEPTH : 0);
14584
- const totalGridHeight = rowHeights.reduce((a, b) => a + b, 0) + (gridRows > 1 ? (gridRows - 1) * TAB_CONFIG.TAB_DEPTH : 0);
14638
+ const totalGridWidth = colWidths.reduce((a, b) => a + b, 0) + (gridCols > 1 ? (gridCols - 1) * boardGap : 0);
14639
+ const totalGridHeight = rowHeights.reduce((a, b) => a + b, 0) + (gridRows > 1 ? (gridRows - 1) * boardGap : 0);
14585
14640
  const startX = -totalGridWidth / 2;
14586
14641
  const startY = -totalGridHeight / 2;
14587
14642
  const rowYOffsets = [startY];
14588
14643
  for (let i = 0; i < gridRows - 1; i++) {
14589
- rowYOffsets.push(rowYOffsets[i] + rowHeights[i] + TAB_CONFIG.TAB_DEPTH);
14644
+ rowYOffsets.push(rowYOffsets[i] + rowHeights[i] + boardGap);
14590
14645
  }
14591
14646
  const colXOffsets = [startX];
14592
14647
  for (let i = 0; i < gridCols - 1; i++) {
14593
- colXOffsets.push(colXOffsets[i] + colWidths[i] + TAB_CONFIG.TAB_DEPTH);
14648
+ colXOffsets.push(colXOffsets[i] + colWidths[i] + boardGap);
14594
14649
  }
14595
14650
  unpositionedBoards.forEach((board, i) => {
14596
14651
  const col = i % gridCols;
@@ -14624,9 +14679,8 @@ var Panel = class extends Group6 {
14624
14679
  if (isFinite(minX)) {
14625
14680
  const boundsWidth = maxX - minX;
14626
14681
  const boundsHeight = maxY - minY;
14627
- const margin = TAB_CONFIG.TAB_DEPTH * 3;
14628
- const newPanelWidth = boundsWidth + 2 * margin;
14629
- const newPanelHeight = boundsHeight + 2 * margin;
14682
+ const newPanelWidth = boundsWidth + 2 * DEFAULT_PANEL_MARGIN;
14683
+ const newPanelHeight = boundsHeight + 2 * DEFAULT_PANEL_MARGIN;
14630
14684
  db.pcb_panel.update(this.pcb_panel_id, {
14631
14685
  width: newPanelWidth,
14632
14686
  height: newPanelHeight
@@ -14634,15 +14688,29 @@ var Panel = class extends Group6 {
14634
14688
  }
14635
14689
  }
14636
14690
  if (this._tabsAndMouseBitesGenerated) return;
14637
- const childBoardIds = childBoardInstances.map((c) => c.pcb_board_id).filter((id) => !!id);
14638
- const boardsInPanel = db.pcb_board.list().filter((b) => childBoardIds.includes(b.pcb_board_id));
14639
- if (boardsInPanel.length === 0) return;
14640
- const { tabCutouts, mouseBiteHoles } = generatePanelTabsAndMouseBites(boardsInPanel);
14641
- for (const tabCutout of tabCutouts) {
14642
- db.pcb_cutout.insert(tabCutout);
14643
- }
14644
- for (const mouseBiteHole of mouseBiteHoles) {
14645
- db.pcb_hole.insert(mouseBiteHole);
14691
+ const props = this._parsedProps;
14692
+ const panelizationMethod = props.panelizationMethod ?? "tab-routing";
14693
+ if (panelizationMethod !== "none") {
14694
+ const childBoardIds = childBoardInstances.map((c) => c.pcb_board_id).filter((id) => !!id);
14695
+ const boardsInPanel = db.pcb_board.list().filter((b) => childBoardIds.includes(b.pcb_board_id));
14696
+ if (boardsInPanel.length === 0) return;
14697
+ const tabWidth = props.tabWidth ?? DEFAULT_TAB_WIDTH;
14698
+ const boardGap = props.boardGap ?? tabWidth;
14699
+ const { tabCutouts, mouseBiteHoles } = generatePanelTabsAndMouseBites(
14700
+ boardsInPanel,
14701
+ {
14702
+ boardGap,
14703
+ tabWidth,
14704
+ tabLength: props.tabLength ?? DEFAULT_TAB_LENGTH,
14705
+ mouseBites: props.mouseBites ?? true
14706
+ }
14707
+ );
14708
+ for (const tabCutout of tabCutouts) {
14709
+ db.pcb_cutout.insert(tabCutout);
14710
+ }
14711
+ for (const mouseBiteHole of mouseBiteHoles) {
14712
+ db.pcb_hole.insert(mouseBiteHole);
14713
+ }
14646
14714
  }
14647
14715
  this._tabsAndMouseBitesGenerated = true;
14648
14716
  }
@@ -14658,8 +14726,8 @@ var Panel = class extends Group6 {
14658
14726
  const { db } = this.root;
14659
14727
  const props = this._parsedProps;
14660
14728
  const inserted = db.pcb_panel.insert({
14661
- width: distance7.parse(props.width),
14662
- height: distance7.parse(props.height),
14729
+ width: distance9.parse(props.width),
14730
+ height: distance9.parse(props.height),
14663
14731
  center: this._getGlobalPcbPositionBeforeLayout(),
14664
14732
  covered_with_solder_mask: !(props.noSolderMask ?? false)
14665
14733
  });
@@ -14671,8 +14739,8 @@ var Panel = class extends Group6 {
14671
14739
  const { db } = this.root;
14672
14740
  const props = this._parsedProps;
14673
14741
  db.pcb_panel.update(this.pcb_panel_id, {
14674
- width: distance7.parse(props.width),
14675
- height: distance7.parse(props.height),
14742
+ width: distance9.parse(props.width),
14743
+ height: distance9.parse(props.height),
14676
14744
  center: this._getGlobalPcbPositionBeforeLayout(),
14677
14745
  covered_with_solder_mask: !(props.noSolderMask ?? false)
14678
14746
  });
@@ -18460,7 +18528,7 @@ import { identity as identity6 } from "transformation-matrix";
18460
18528
  var package_default = {
18461
18529
  name: "@tscircuit/core",
18462
18530
  type: "module",
18463
- version: "0.0.870",
18531
+ version: "0.0.872",
18464
18532
  types: "dist/index.d.ts",
18465
18533
  main: "dist/index.js",
18466
18534
  module: "dist/index.js",
@@ -18504,7 +18572,7 @@ var package_default = {
18504
18572
  "@tscircuit/math-utils": "^0.0.29",
18505
18573
  "@tscircuit/miniflex": "^0.0.4",
18506
18574
  "@tscircuit/ngspice-spice-engine": "^0.0.3",
18507
- "@tscircuit/props": "^0.0.403",
18575
+ "@tscircuit/props": "^0.0.409",
18508
18576
  "@tscircuit/schematic-autolayout": "^0.0.6",
18509
18577
  "@tscircuit/schematic-match-adapt": "^0.0.16",
18510
18578
  "@tscircuit/schematic-trace-solver": "^v0.0.45",
@@ -18518,13 +18586,13 @@ var package_default = {
18518
18586
  "bun-match-svg": "0.0.12",
18519
18587
  "calculate-elbow": "^0.0.12",
18520
18588
  "chokidar-cli": "^3.0.0",
18521
- "circuit-json": "^0.0.317",
18589
+ "circuit-json": "^0.0.319",
18522
18590
  "circuit-json-to-bpc": "^0.0.13",
18523
18591
  "circuit-json-to-connectivity-map": "^0.0.22",
18524
18592
  "circuit-json-to-gltf": "^0.0.31",
18525
18593
  "circuit-json-to-simple-3d": "^0.0.9",
18526
18594
  "circuit-json-to-spice": "^0.0.24",
18527
- "circuit-to-svg": "^0.0.274",
18595
+ "circuit-to-svg": "^0.0.275",
18528
18596
  concurrently: "^9.1.2",
18529
18597
  "connectivity-map": "^1.0.0",
18530
18598
  debug: "^4.3.6",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.871",
4
+ "version": "0.0.873",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -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.3",
48
- "@tscircuit/props": "^0.0.403",
48
+ "@tscircuit/props": "^0.0.409",
49
49
  "@tscircuit/schematic-autolayout": "^0.0.6",
50
50
  "@tscircuit/schematic-match-adapt": "^0.0.16",
51
51
  "@tscircuit/schematic-trace-solver": "^v0.0.45",
@@ -59,13 +59,13 @@
59
59
  "bun-match-svg": "0.0.12",
60
60
  "calculate-elbow": "^0.0.12",
61
61
  "chokidar-cli": "^3.0.0",
62
- "circuit-json": "^0.0.317",
62
+ "circuit-json": "^0.0.319",
63
63
  "circuit-json-to-bpc": "^0.0.13",
64
64
  "circuit-json-to-connectivity-map": "^0.0.22",
65
65
  "circuit-json-to-gltf": "^0.0.31",
66
66
  "circuit-json-to-simple-3d": "^0.0.9",
67
67
  "circuit-json-to-spice": "^0.0.24",
68
- "circuit-to-svg": "^0.0.274",
68
+ "circuit-to-svg": "^0.0.275",
69
69
  "concurrently": "^9.1.2",
70
70
  "connectivity-map": "^1.0.0",
71
71
  "debug": "^4.3.6",