@tscircuit/pcb-viewer 1.11.278 → 1.11.280

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
@@ -7074,7 +7074,7 @@ function getExpandedStroke(strokeInput, defaultWidth) {
7074
7074
  }
7075
7075
 
7076
7076
  // src/lib/convert-element-to-primitive.ts
7077
- import { distance } from "circuit-json";
7077
+ import { distance as distance2 } from "circuit-json";
7078
7078
 
7079
7079
  // src/lib/element-to-primitive-converters/convert-smtpad-rect.ts
7080
7080
  var convertSmtpadRect = (element, metadata) => {
@@ -7196,6 +7196,43 @@ var convertSmtpadPolygon = (element, metadata) => {
7196
7196
  // src/lib/element-to-primitive-converters/convert-smtpad-pill.ts
7197
7197
  var convertSmtpadPill = (element, metadata) => {
7198
7198
  const { x, y, width, height, layer } = element;
7199
+ const primitives = [
7200
+ {
7201
+ _pcb_drawing_object_id: getNewPcbDrawingObjectId("pill"),
7202
+ pcb_drawing_type: "pill",
7203
+ x,
7204
+ y,
7205
+ w: width,
7206
+ h: height,
7207
+ layer: layer || "top",
7208
+ _element: element,
7209
+ _parent_pcb_component: metadata._parent_pcb_component,
7210
+ _parent_source_component: metadata._parent_source_component,
7211
+ _source_port: metadata._source_port
7212
+ }
7213
+ ];
7214
+ if (element.is_covered_with_solder_mask) {
7215
+ const maskLayer = layer === "bottom" ? "soldermask_with_copper_bottom" : "soldermask_with_copper_top";
7216
+ const maskPrimitive = {
7217
+ _pcb_drawing_object_id: getNewPcbDrawingObjectId("pill"),
7218
+ pcb_drawing_type: "pill",
7219
+ x,
7220
+ y,
7221
+ w: width,
7222
+ h: height,
7223
+ layer: maskLayer,
7224
+ _element: element,
7225
+ _parent_pcb_component: metadata._parent_pcb_component,
7226
+ _parent_source_component: metadata._parent_source_component,
7227
+ _source_port: metadata._source_port,
7228
+ ..."solder_mask_color" in element && element.solder_mask_color ? { color: element.solder_mask_color } : {}
7229
+ };
7230
+ primitives.push(maskPrimitive);
7231
+ }
7232
+ return primitives;
7233
+ };
7234
+ var convertSmtpadRotatedPill = (element, metadata) => {
7235
+ const { x, y, width, height, layer, ccw_rotation } = element;
7199
7236
  const primitives = [
7200
7237
  {
7201
7238
  _pcb_drawing_object_id: getNewPcbDrawingObjectId("pill"),
@@ -7209,7 +7246,7 @@ var convertSmtpadPill = (element, metadata) => {
7209
7246
  _parent_pcb_component: metadata._parent_pcb_component,
7210
7247
  _parent_source_component: metadata._parent_source_component,
7211
7248
  _source_port: metadata._source_port,
7212
- ...element.shape === "rotated_pill" && element.ccw_rotation !== void 0 ? { ccw_rotation: element.ccw_rotation } : {}
7249
+ ccw_rotation
7213
7250
  }
7214
7251
  ];
7215
7252
  if (element.is_covered_with_solder_mask) {
@@ -7226,7 +7263,7 @@ var convertSmtpadPill = (element, metadata) => {
7226
7263
  _parent_pcb_component: metadata._parent_pcb_component,
7227
7264
  _parent_source_component: metadata._parent_source_component,
7228
7265
  _source_port: metadata._source_port,
7229
- ...element.shape === "rotated_pill" && element.ccw_rotation !== void 0 ? { ccw_rotation: element.ccw_rotation } : {},
7266
+ ccw_rotation,
7230
7267
  ..."solder_mask_color" in element && element.solder_mask_color ? { color: element.solder_mask_color } : {}
7231
7268
  };
7232
7269
  primitives.push(maskPrimitive);
@@ -7234,12 +7271,49 @@ var convertSmtpadPill = (element, metadata) => {
7234
7271
  return primitives;
7235
7272
  };
7236
7273
 
7274
+ // src/lib/element-to-primitive/convert-pcb-copper-text-to-primitive.ts
7275
+ import { distance } from "circuit-json";
7276
+ var convertPcbCopperTextToPrimitive = (element, metadata) => {
7277
+ const { _parent_pcb_component, _parent_source_component } = metadata;
7278
+ const copperText = element;
7279
+ const fontSize = typeof copperText.font_size === "string" ? distance.parse(copperText.font_size) : copperText.font_size ?? 0.2;
7280
+ let knockoutPadding;
7281
+ if (copperText.knockout_padding) {
7282
+ knockoutPadding = {
7283
+ left: typeof copperText.knockout_padding.left === "string" ? distance.parse(copperText.knockout_padding.left) : copperText.knockout_padding.left,
7284
+ top: typeof copperText.knockout_padding.top === "string" ? distance.parse(copperText.knockout_padding.top) : copperText.knockout_padding.top,
7285
+ bottom: typeof copperText.knockout_padding.bottom === "string" ? distance.parse(copperText.knockout_padding.bottom) : copperText.knockout_padding.bottom,
7286
+ right: typeof copperText.knockout_padding.right === "string" ? distance.parse(copperText.knockout_padding.right) : copperText.knockout_padding.right
7287
+ };
7288
+ }
7289
+ return [
7290
+ {
7291
+ _pcb_drawing_object_id: getNewPcbDrawingObjectId("text"),
7292
+ pcb_drawing_type: "text",
7293
+ x: copperText.anchor_position.x,
7294
+ y: copperText.anchor_position.y,
7295
+ layer: copperText.layer,
7296
+ // "top", "bottom", or inner layers
7297
+ align: copperText.anchor_alignment ?? "center",
7298
+ text: copperText.text,
7299
+ size: fontSize,
7300
+ ccw_rotation: copperText.ccw_rotation,
7301
+ is_mirrored: copperText.is_mirrored,
7302
+ is_knockout: copperText.is_knockout,
7303
+ knockout_padding: knockoutPadding,
7304
+ _element: element,
7305
+ _parent_pcb_component,
7306
+ _parent_source_component
7307
+ }
7308
+ ];
7309
+ };
7310
+
7237
7311
  // src/lib/convert-element-to-primitive.ts
7238
7312
  var globalPcbDrawingObjectCount = 0;
7239
7313
  var getNewPcbDrawingObjectId = (prefix) => `${prefix}_${globalPcbDrawingObjectCount++}`;
7240
7314
  var normalizePolygonPoints = (points) => (points ?? []).map((point) => ({
7241
- x: distance.parse(point.x),
7242
- y: distance.parse(point.y)
7315
+ x: distance2.parse(point.x),
7316
+ y: distance2.parse(point.y)
7243
7317
  }));
7244
7318
  var convertElementToPrimitives = (element, allElements) => {
7245
7319
  const _parent_pcb_component = "pcb_component_id" in element ? allElements.find(
@@ -7438,8 +7512,10 @@ var convertElementToPrimitives = (element, allElements) => {
7438
7512
  return convertSmtpadCircle(element, metadata);
7439
7513
  } else if (element.shape === "polygon") {
7440
7514
  return convertSmtpadPolygon(element, metadata);
7441
- } else if (element.shape === "pill" || element.shape === "rotated_pill") {
7515
+ } else if (element.shape === "pill") {
7442
7516
  return convertSmtpadPill(element, metadata);
7517
+ } else if (element.shape === "rotated_pill") {
7518
+ return convertSmtpadRotatedPill(element, metadata);
7443
7519
  }
7444
7520
  return [];
7445
7521
  }
@@ -7764,10 +7840,10 @@ var convertElementToPrimitives = (element, allElements) => {
7764
7840
  hole_height,
7765
7841
  layers
7766
7842
  } = element;
7767
- const hole_offset_x = distance.parse(
7843
+ const hole_offset_x = distance2.parse(
7768
7844
  element.hole_offset_x ?? 0
7769
7845
  );
7770
- const hole_offset_y = distance.parse(
7846
+ const hole_offset_y = distance2.parse(
7771
7847
  element.hole_offset_y ?? 0
7772
7848
  );
7773
7849
  const pcb_outline = pad_outline;
@@ -8150,6 +8226,12 @@ var convertElementToPrimitives = (element, allElements) => {
8150
8226
  }
8151
8227
  ];
8152
8228
  }
8229
+ case "pcb_copper_text": {
8230
+ return convertPcbCopperTextToPrimitive(element, {
8231
+ _parent_pcb_component,
8232
+ _parent_source_component
8233
+ });
8234
+ }
8153
8235
  case "pcb_copper_pour": {
8154
8236
  const pour = element;
8155
8237
  switch (pour.shape) {
@@ -9441,6 +9523,7 @@ var getTextGeometry = (text) => {
9441
9523
  return {
9442
9524
  text_lines,
9443
9525
  line_count,
9526
+ line_widths,
9444
9527
  target_height,
9445
9528
  target_width_char,
9446
9529
  space_between_chars,
@@ -9463,17 +9546,21 @@ var convertTextToLines = (text) => {
9463
9546
  const {
9464
9547
  text_lines,
9465
9548
  line_count,
9549
+ line_widths,
9466
9550
  target_height,
9467
9551
  target_width_char,
9468
9552
  space_between_chars,
9469
- space_between_lines
9553
+ space_between_lines,
9554
+ width: maxWidth
9470
9555
  } = getTextGeometry(text);
9471
9556
  if (target_height <= 0 || line_count === 0) return [];
9472
9557
  const strokeWidth = target_height / 12;
9473
9558
  const lines = [];
9474
9559
  for (let lineIndex = 0; lineIndex < line_count; lineIndex++) {
9475
- const lineYOffset = lineIndex * (target_height + space_between_lines);
9476
- let current_x_origin_for_char_box = text.x;
9560
+ const lineYOffset = -lineIndex * (target_height + space_between_lines);
9561
+ const lineWidth = line_widths[lineIndex];
9562
+ const lineXOffset = (maxWidth - lineWidth) / 2;
9563
+ let current_x_origin_for_char_box = text.x + lineXOffset;
9477
9564
  for (let letterIndex = 0; letterIndex < text_lines[lineIndex].length; letterIndex++) {
9478
9565
  const letter = text_lines[lineIndex][letterIndex];
9479
9566
  const letterLines = lineAlphabet[letter] ?? lineAlphabet[letter.toUpperCase()];
@@ -9533,56 +9620,44 @@ var drawLine = (drawer, line) => {
9533
9620
  drawer.moveTo(line.x1, line.y1);
9534
9621
  drawer.lineTo(line.x2, line.y2);
9535
9622
  };
9536
- var drawText = (drawer, text) => {
9537
- drawer.equip({
9538
- fontSize: text.size,
9539
- color: getColor(text),
9540
- layer: text.layer
9541
- });
9542
- let alignOffset = { x: 0, y: 0 };
9543
- const { width: textWidth, height: textHeight } = getTextMetrics(text);
9544
- switch (text.align) {
9623
+ var getAlignOffset = (textWidth, textHeight, align) => {
9624
+ switch (align) {
9545
9625
  case "top_left":
9546
- alignOffset.x = 0;
9547
- alignOffset.y = -textHeight;
9548
- break;
9626
+ return { x: 0, y: -textHeight };
9549
9627
  case "top_center":
9550
- alignOffset.x = -textWidth / 2;
9551
- alignOffset.y = -textHeight;
9552
- break;
9628
+ return { x: -textWidth / 2, y: -textHeight };
9553
9629
  case "top_right":
9554
- alignOffset.x = -textWidth;
9555
- alignOffset.y = -textHeight;
9556
- break;
9630
+ return { x: -textWidth, y: -textHeight };
9557
9631
  case "center_left":
9558
- alignOffset.x = 0;
9559
- alignOffset.y = -textHeight / 2;
9560
- break;
9632
+ return { x: 0, y: -textHeight / 2 };
9561
9633
  case "center":
9562
- alignOffset.x = -textWidth / 2;
9563
- alignOffset.y = -textHeight / 2;
9564
- break;
9634
+ return { x: -textWidth / 2, y: -textHeight / 2 };
9565
9635
  case "center_right":
9566
- alignOffset.x = -textWidth;
9567
- alignOffset.y = -textHeight / 2;
9568
- break;
9636
+ return { x: -textWidth, y: -textHeight / 2 };
9569
9637
  case "bottom_left":
9570
- alignOffset.x = 0;
9571
- alignOffset.y = 0;
9572
- break;
9638
+ return { x: 0, y: 0 };
9573
9639
  case "bottom_center":
9574
- alignOffset.x = -textWidth / 2;
9575
- alignOffset.y = 0;
9576
- break;
9640
+ return { x: -textWidth / 2, y: 0 };
9577
9641
  case "bottom_right":
9578
- alignOffset.x = -textWidth;
9579
- alignOffset.y = 0;
9580
- break;
9642
+ return { x: -textWidth, y: 0 };
9581
9643
  default:
9582
- alignOffset.x = 0;
9583
- alignOffset.y = 0;
9584
- break;
9644
+ return { x: 0, y: 0 };
9645
+ }
9646
+ };
9647
+ var shouldMirrorText = (text) => {
9648
+ if (text.layer === "bottom_silkscreen" || text.layer === "bottom") {
9649
+ return text.is_mirrored !== false;
9585
9650
  }
9651
+ return text.is_mirrored === true;
9652
+ };
9653
+ var drawText = (drawer, text) => {
9654
+ drawer.equip({
9655
+ fontSize: text.size,
9656
+ color: getColor(text),
9657
+ layer: text.layer
9658
+ });
9659
+ const { width: textWidth, height: textHeight } = getTextMetrics(text);
9660
+ const alignOffset = getAlignOffset(textWidth, textHeight, text.align);
9586
9661
  text.x ??= 0;
9587
9662
  text.y ??= 0;
9588
9663
  const rotationAnchor = {
@@ -9594,7 +9669,7 @@ var drawText = (drawer, text) => {
9594
9669
  x: text.x + alignOffset.x,
9595
9670
  y: text.y + alignOffset.y
9596
9671
  });
9597
- if (text.layer === "bottom_silkscreen") {
9672
+ if (shouldMirrorText(text)) {
9598
9673
  text_lines = text_lines.map((line) => ({
9599
9674
  ...line,
9600
9675
  x1: 2 * text.x - line.x1,
@@ -9613,6 +9688,80 @@ var drawText = (drawer, text) => {
9613
9688
  drawLine(drawer, line);
9614
9689
  }
9615
9690
  };
9691
+ var drawKnockoutText = (drawer, text) => {
9692
+ const {
9693
+ width: textWidth,
9694
+ height: textHeight,
9695
+ lineHeight
9696
+ } = getTextMetrics(text);
9697
+ text.x ??= 0;
9698
+ text.y ??= 0;
9699
+ const padding = text.knockout_padding ?? {
9700
+ left: text.size * 0.5,
9701
+ right: text.size * 0.5,
9702
+ top: text.size * 0.3,
9703
+ bottom: text.size * 0.3
9704
+ };
9705
+ const rectWidth = textWidth + padding.left + padding.right;
9706
+ const rectHeight = textHeight + padding.top + padding.bottom;
9707
+ const textCenterXAtOrigin = textWidth / 2;
9708
+ const textCenterYAtOrigin = lineHeight - textHeight / 2;
9709
+ const textDrawX = text.x - textCenterXAtOrigin;
9710
+ const textDrawY = text.y - textCenterYAtOrigin;
9711
+ const rotationAnchor = {
9712
+ x: text.x,
9713
+ y: text.y
9714
+ };
9715
+ const rect = {
9716
+ _pcb_drawing_object_id: `knockout_rect_${text._pcb_drawing_object_id}`,
9717
+ pcb_drawing_type: "rect",
9718
+ x: text.x,
9719
+ y: text.y,
9720
+ w: rectWidth,
9721
+ h: rectHeight,
9722
+ layer: text.layer,
9723
+ ccw_rotation: text.ccw_rotation
9724
+ };
9725
+ if (text.ccw_rotation) {
9726
+ drawRotatedRect(drawer, rect);
9727
+ } else {
9728
+ drawRect(drawer, rect);
9729
+ }
9730
+ let text_lines = convertTextToLines({
9731
+ ...text,
9732
+ x: textDrawX,
9733
+ y: textDrawY
9734
+ });
9735
+ if (shouldMirrorText(text)) {
9736
+ text_lines = text_lines.map((line) => ({
9737
+ ...line,
9738
+ x1: 2 * text.x - line.x1,
9739
+ x2: 2 * text.x - line.x2
9740
+ }));
9741
+ }
9742
+ if (text.ccw_rotation) {
9743
+ const rotateTextParams = {
9744
+ lines: text_lines,
9745
+ anchorPoint: rotationAnchor,
9746
+ ccwRotation: text.ccw_rotation
9747
+ };
9748
+ text_lines = rotateText(rotateTextParams);
9749
+ }
9750
+ for (const line of text_lines) {
9751
+ drawer.equip({
9752
+ size: line.width,
9753
+ shape: "circle",
9754
+ color: "black",
9755
+ layer: text.layer,
9756
+ mode: "subtract"
9757
+ });
9758
+ drawer.moveTo(line.x1, line.y1);
9759
+ drawer.lineTo(line.x2, line.y2);
9760
+ }
9761
+ drawer.equip({
9762
+ mode: "add"
9763
+ });
9764
+ };
9616
9765
  var drawRect = (drawer, rect) => {
9617
9766
  drawer.equip({
9618
9767
  color: getColor(rect),
@@ -9694,6 +9843,9 @@ var drawPrimitive = (drawer, primitive) => {
9694
9843
  case "line":
9695
9844
  return drawLine(drawer, primitive);
9696
9845
  case "text":
9846
+ if (primitive.is_knockout) {
9847
+ return drawKnockoutText(drawer, primitive);
9848
+ }
9697
9849
  return drawText(drawer, primitive);
9698
9850
  case "rect": {
9699
9851
  if (primitive.ccw_rotation) {
@@ -10453,7 +10605,7 @@ function calculateDiagonalLabel(params) {
10453
10605
  } = params;
10454
10606
  const deltaX = dimensionEnd.x - dimensionStart.x;
10455
10607
  const deltaY = dimensionEnd.y - dimensionStart.y;
10456
- const distance3 = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
10608
+ const distance4 = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
10457
10609
  const screenDeltaX = screenDimensionEnd.x - screenDimensionStart.x;
10458
10610
  const screenDeltaY = screenDimensionEnd.y - screenDimensionStart.y;
10459
10611
  const screenDistance = Math.sqrt(
@@ -10495,11 +10647,11 @@ function calculateDiagonalLabel(params) {
10495
10647
  const x = midX + offsetX;
10496
10648
  const y = midY + offsetY;
10497
10649
  return {
10498
- distance: distance3,
10650
+ distance: distance4,
10499
10651
  screenDistance,
10500
10652
  x,
10501
10653
  y,
10502
- show: distance3 > 0.01 && screenDistance > 30 && isDiagonal
10654
+ show: distance4 > 0.01 && screenDistance > 30 && isDiagonal
10503
10655
  };
10504
10656
  }
10505
10657
 
@@ -10793,11 +10945,11 @@ var DimensionOverlay = ({
10793
10945
  for (const snap of snappingPointsWithScreen) {
10794
10946
  const dx = snap.screenPoint.x - screenPoint.x;
10795
10947
  const dy = snap.screenPoint.y - screenPoint.y;
10796
- const distance3 = Math.hypot(dx, dy);
10797
- if (distance3 > SNAP_THRESHOLD_PX) continue;
10798
- if (!bestMatch || distance3 < bestMatch.distance) {
10948
+ const distance4 = Math.hypot(dx, dy);
10949
+ if (distance4 > SNAP_THRESHOLD_PX) continue;
10950
+ if (!bestMatch || distance4 < bestMatch.distance) {
10799
10951
  bestMatch = {
10800
- distance: distance3,
10952
+ distance: distance4,
10801
10953
  id: snap.id,
10802
10954
  point: snap.point
10803
10955
  };
@@ -11396,10 +11548,10 @@ var isInsideOfSmtpad = (elm, point, padding = 0) => {
11396
11548
  };
11397
11549
  var isInsideOfPlatedHole = (hole, point, padding = 0) => {
11398
11550
  if (hole.shape === "circle") {
11399
- const distance3 = Math.sqrt(
11551
+ const distance4 = Math.sqrt(
11400
11552
  (point.x - hole.x) ** 2 + (point.y - hole.y) ** 2
11401
11553
  );
11402
- return distance3 <= hole.outer_diameter / 2 + padding;
11554
+ return distance4 <= hole.outer_diameter / 2 + padding;
11403
11555
  } else if (hole.shape === "circular_hole_with_rect_pad") {
11404
11556
  const dx = Math.abs(point.x - hole.x);
11405
11557
  const dy = Math.abs(point.y - hole.y);
@@ -12227,7 +12379,7 @@ var ErrorOverlay = ({
12227
12379
 
12228
12380
  // src/components/MouseElementTracker.tsx
12229
12381
  import { pointToSegmentDistance } from "@tscircuit/math-utils";
12230
- import { distance as distance2 } from "circuit-json";
12382
+ import { distance as distance3 } from "circuit-json";
12231
12383
 
12232
12384
  // src/lib/util/if-sets-match-exactly.ts
12233
12385
  function ifSetsMatchExactly(set1, set2) {
@@ -12777,22 +12929,22 @@ var getPrimitivesUnderPoint = (primitives, rwPoint, transform) => {
12777
12929
  for (const primitive of primitives) {
12778
12930
  if (!primitive._element) continue;
12779
12931
  if ("x1" in primitive && primitive._element?.type === "pcb_trace") {
12780
- const distance3 = pointToSegmentDistance(
12932
+ const distance4 = pointToSegmentDistance(
12781
12933
  { x: rwPoint.x, y: rwPoint.y },
12782
12934
  { x: primitive.x1, y: primitive.y1 },
12783
12935
  { x: primitive.x2, y: primitive.y2 }
12784
12936
  );
12785
12937
  const lineWidth = primitive.width || 0.5;
12786
12938
  const detectionThreshold = Math.max(lineWidth * 25, 2) / transform.a;
12787
- if (distance3 < detectionThreshold) {
12939
+ if (distance4 < detectionThreshold) {
12788
12940
  newMousedPrimitives.push(primitive);
12789
12941
  }
12790
12942
  continue;
12791
12943
  }
12792
12944
  if (primitive.pcb_drawing_type === "polygon") {
12793
12945
  const points = primitive.points.map((point) => ({
12794
- x: distance2.parse(point.x),
12795
- y: distance2.parse(point.y)
12946
+ x: distance3.parse(point.x),
12947
+ y: distance3.parse(point.y)
12796
12948
  }));
12797
12949
  const boundingBox = getPolygonBoundingBox(points);
12798
12950
  if (!boundingBox) continue;
@@ -12806,8 +12958,8 @@ var getPrimitivesUnderPoint = (primitives, rwPoint, transform) => {
12806
12958
  }
12807
12959
  if (primitive.pcb_drawing_type === "polygon_with_arcs") {
12808
12960
  const points = primitive.brep_shape.outer_ring.vertices.map((v) => ({
12809
- x: distance2.parse(v.x),
12810
- y: distance2.parse(v.y)
12961
+ x: distance3.parse(v.x),
12962
+ y: distance3.parse(v.y)
12811
12963
  }));
12812
12964
  const boundingBox = getPolygonBoundingBox(points);
12813
12965
  if (!boundingBox) continue;
@@ -13249,11 +13401,11 @@ var RatsNestOverlay = ({ transform, soup, children }) => {
13249
13401
  connectedIds.forEach((id) => {
13250
13402
  const pos = getElementPosition(id);
13251
13403
  if (pos) {
13252
- const distance3 = Math.sqrt(
13404
+ const distance4 = Math.sqrt(
13253
13405
  (sourcePoint.x - pos.x) ** 2 + (sourcePoint.y - pos.y) ** 2
13254
13406
  );
13255
- if (distance3 < minDistance && distance3 > 0) {
13256
- minDistance = distance3;
13407
+ if (distance4 < minDistance && distance4 > 0) {
13408
+ minDistance = distance4;
13257
13409
  nearestPoint = pos;
13258
13410
  }
13259
13411
  }
@@ -13333,7 +13485,7 @@ import { css as css3 } from "@emotion/css";
13333
13485
  // package.json
13334
13486
  var package_default = {
13335
13487
  name: "@tscircuit/pcb-viewer",
13336
- version: "1.11.277",
13488
+ version: "1.11.279",
13337
13489
  main: "dist/index.js",
13338
13490
  type: "module",
13339
13491
  repository: "tscircuit/pcb-viewer",