@tscircuit/3d-viewer 0.0.421 → 0.0.423

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.
Files changed (2) hide show
  1. package/dist/index.js +323 -187
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1712,7 +1712,7 @@ var require_toString2 = __commonJS({
1712
1712
  var require_translate = __commonJS({
1713
1713
  "node_modules/@jscad/modeling/src/maths/mat4/translate.js"(exports, module) {
1714
1714
  "use strict";
1715
- var translate6 = (out, matrix, offsets) => {
1715
+ var translate7 = (out, matrix, offsets) => {
1716
1716
  const x = offsets[0];
1717
1717
  const y = offsets[1];
1718
1718
  const z126 = offsets[2];
@@ -1765,7 +1765,7 @@ var require_translate = __commonJS({
1765
1765
  }
1766
1766
  return out;
1767
1767
  };
1768
- module.exports = translate6;
1768
+ module.exports = translate7;
1769
1769
  }
1770
1770
  });
1771
1771
 
@@ -5426,7 +5426,7 @@ var require_colorize = __commonJS({
5426
5426
  newpoly.color = color;
5427
5427
  return newpoly;
5428
5428
  };
5429
- var colorize5 = (color, ...objects) => {
5429
+ var colorize6 = (color, ...objects) => {
5430
5430
  if (!Array.isArray(color)) throw new Error("color must be an array");
5431
5431
  if (color.length < 3) throw new Error("color must contain R, G and B values");
5432
5432
  if (color.length === 3) color = [color[0], color[1], color[2], 1];
@@ -5442,7 +5442,7 @@ var require_colorize = __commonJS({
5442
5442
  });
5443
5443
  return results.length === 1 ? results[0] : results;
5444
5444
  };
5445
- module.exports = colorize5;
5445
+ module.exports = colorize6;
5446
5446
  }
5447
5447
  });
5448
5448
 
@@ -6267,11 +6267,11 @@ var require_clone9 = __commonJS({
6267
6267
  "node_modules/@jscad/modeling/src/maths/line2/clone.js"(exports, module) {
6268
6268
  "use strict";
6269
6269
  var create = require_create11();
6270
- var clone = (line3) => {
6270
+ var clone = (line4) => {
6271
6271
  const out = create();
6272
- out[0] = line3[0];
6273
- out[1] = line3[1];
6274
- out[2] = line3[2];
6272
+ out[0] = line4[0];
6273
+ out[1] = line4[1];
6274
+ out[2] = line4[2];
6275
6275
  return out;
6276
6276
  };
6277
6277
  module.exports = clone;
@@ -6283,8 +6283,8 @@ var require_direction = __commonJS({
6283
6283
  "node_modules/@jscad/modeling/src/maths/line2/direction.js"(exports, module) {
6284
6284
  "use strict";
6285
6285
  var vec2 = require_vec2();
6286
- var direction = (line3) => {
6287
- const vector = vec2.normal(vec2.create(), line3);
6286
+ var direction = (line4) => {
6287
+ const vector = vec2.normal(vec2.create(), line4);
6288
6288
  vec2.negate(vector, vector);
6289
6289
  return vector;
6290
6290
  };
@@ -6297,7 +6297,7 @@ var require_origin = __commonJS({
6297
6297
  "node_modules/@jscad/modeling/src/maths/line2/origin.js"(exports, module) {
6298
6298
  "use strict";
6299
6299
  var vec2 = require_vec2();
6300
- var origin = (line3) => vec2.scale(vec2.create(), line3, line3[2]);
6300
+ var origin = (line4) => vec2.scale(vec2.create(), line4, line4[2]);
6301
6301
  module.exports = origin;
6302
6302
  }
6303
6303
  });
@@ -6309,9 +6309,9 @@ var require_closestPoint = __commonJS({
6309
6309
  var vec2 = require_vec2();
6310
6310
  var direction = require_direction();
6311
6311
  var origin = require_origin();
6312
- var closestPoint = (line3, point2) => {
6313
- const orig = origin(line3);
6314
- const dir = direction(line3);
6312
+ var closestPoint = (line4, point2) => {
6313
+ const orig = origin(line4);
6314
+ const dir = direction(line4);
6315
6315
  const v = vec2.subtract(vec2.create(), point2, orig);
6316
6316
  const dist = vec2.dot(v, dir);
6317
6317
  vec2.scale(v, dir, dist);
@@ -6326,10 +6326,10 @@ var require_closestPoint = __commonJS({
6326
6326
  var require_copy5 = __commonJS({
6327
6327
  "node_modules/@jscad/modeling/src/maths/line2/copy.js"(exports, module) {
6328
6328
  "use strict";
6329
- var copy = (out, line3) => {
6330
- out[0] = line3[0];
6331
- out[1] = line3[1];
6332
- out[2] = line3[2];
6329
+ var copy = (out, line4) => {
6330
+ out[0] = line4[0];
6331
+ out[1] = line4[1];
6332
+ out[2] = line4[2];
6333
6333
  return out;
6334
6334
  };
6335
6335
  module.exports = copy;
@@ -6341,9 +6341,9 @@ var require_distanceToPoint = __commonJS({
6341
6341
  "node_modules/@jscad/modeling/src/maths/line2/distanceToPoint.js"(exports, module) {
6342
6342
  "use strict";
6343
6343
  var vec2 = require_vec2();
6344
- var distanceToPoint = (line3, point2) => {
6345
- let distance2 = vec2.dot(point2, line3);
6346
- distance2 = Math.abs(distance2 - line3[2]);
6344
+ var distanceToPoint = (line4, point2) => {
6345
+ let distance2 = vec2.dot(point2, line4);
6346
+ distance2 = Math.abs(distance2 - line4[2]);
6347
6347
  return distance2;
6348
6348
  };
6349
6349
  module.exports = distanceToPoint;
@@ -6511,9 +6511,9 @@ var require_reverse3 = __commonJS({
6511
6511
  var vec2 = require_vec2();
6512
6512
  var copy = require_copy5();
6513
6513
  var fromValues = require_fromValues5();
6514
- var reverse = (out, line3) => {
6515
- const normal = vec2.negate(vec2.create(), line3);
6516
- const distance2 = -line3[2];
6514
+ var reverse = (out, line4) => {
6515
+ const normal = vec2.negate(vec2.create(), line4);
6516
+ const distance2 = -line4[2];
6517
6517
  return copy(out, fromValues(normal[0], normal[1], distance2));
6518
6518
  };
6519
6519
  module.exports = reverse;
@@ -6524,7 +6524,7 @@ var require_reverse3 = __commonJS({
6524
6524
  var require_toString9 = __commonJS({
6525
6525
  "node_modules/@jscad/modeling/src/maths/line2/toString.js"(exports, module) {
6526
6526
  "use strict";
6527
- var toString = (line3) => `line2: (${line3[0].toFixed(7)}, ${line3[1].toFixed(7)}, ${line3[2].toFixed(7)})`;
6527
+ var toString = (line4) => `line2: (${line4[0].toFixed(7)}, ${line4[1].toFixed(7)}, ${line4[2].toFixed(7)})`;
6528
6528
  module.exports = toString;
6529
6529
  }
6530
6530
  });
@@ -6537,9 +6537,9 @@ var require_transform9 = __commonJS({
6537
6537
  var fromPoints = require_fromPoints6();
6538
6538
  var origin = require_origin();
6539
6539
  var direction = require_direction();
6540
- var transform2 = (out, line3, matrix) => {
6541
- const org = origin(line3);
6542
- const dir = direction(line3);
6540
+ var transform2 = (out, line4, matrix) => {
6541
+ const org = origin(line4);
6542
+ const dir = direction(line4);
6543
6543
  vec2.transform(org, org, matrix);
6544
6544
  vec2.transform(dir, dir, matrix);
6545
6545
  return fromPoints(out, org, dir);
@@ -6553,10 +6553,10 @@ var require_xAtY = __commonJS({
6553
6553
  "node_modules/@jscad/modeling/src/maths/line2/xAtY.js"(exports, module) {
6554
6554
  "use strict";
6555
6555
  var origin = require_origin();
6556
- var xAtY = (line3, y) => {
6557
- let x = (line3[2] - line3[1] * y) / line3[0];
6556
+ var xAtY = (line4, y) => {
6557
+ let x = (line4[2] - line4[1] * y) / line4[0];
6558
6558
  if (Number.isNaN(x)) {
6559
- const org = origin(line3);
6559
+ const org = origin(line4);
6560
6560
  x = org[0];
6561
6561
  }
6562
6562
  return x;
@@ -6610,10 +6610,10 @@ var require_clone10 = __commonJS({
6610
6610
  "use strict";
6611
6611
  var vec3 = require_vec3();
6612
6612
  var create = require_create12();
6613
- var clone = (line3) => {
6613
+ var clone = (line4) => {
6614
6614
  const out = create();
6615
- vec3.copy(out[0], line3[0]);
6616
- vec3.copy(out[1], line3[1]);
6615
+ vec3.copy(out[0], line4[0]);
6616
+ vec3.copy(out[1], line4[1]);
6617
6617
  return out;
6618
6618
  };
6619
6619
  module.exports = clone;
@@ -6625,9 +6625,9 @@ var require_closestPoint2 = __commonJS({
6625
6625
  "node_modules/@jscad/modeling/src/maths/line3/closestPoint.js"(exports, module) {
6626
6626
  "use strict";
6627
6627
  var vec3 = require_vec3();
6628
- var closestPoint = (line3, point2) => {
6629
- const lpoint = line3[0];
6630
- const ldirection = line3[1];
6628
+ var closestPoint = (line4, point2) => {
6629
+ const lpoint = line4[0];
6630
+ const ldirection = line4[1];
6631
6631
  const a = vec3.dot(vec3.subtract(vec3.create(), point2, lpoint), ldirection);
6632
6632
  const b = vec3.dot(ldirection, ldirection);
6633
6633
  const t = a / b;
@@ -6644,9 +6644,9 @@ var require_copy6 = __commonJS({
6644
6644
  "node_modules/@jscad/modeling/src/maths/line3/copy.js"(exports, module) {
6645
6645
  "use strict";
6646
6646
  var vec3 = require_vec3();
6647
- var copy = (out, line3) => {
6648
- vec3.copy(out[0], line3[0]);
6649
- vec3.copy(out[1], line3[1]);
6647
+ var copy = (out, line4) => {
6648
+ vec3.copy(out[0], line4[0]);
6649
+ vec3.copy(out[1], line4[1]);
6650
6650
  return out;
6651
6651
  };
6652
6652
  module.exports = copy;
@@ -6657,7 +6657,7 @@ var require_copy6 = __commonJS({
6657
6657
  var require_direction2 = __commonJS({
6658
6658
  "node_modules/@jscad/modeling/src/maths/line3/direction.js"(exports, module) {
6659
6659
  "use strict";
6660
- var direction = (line3) => line3[1];
6660
+ var direction = (line4) => line4[1];
6661
6661
  module.exports = direction;
6662
6662
  }
6663
6663
  });
@@ -6668,8 +6668,8 @@ var require_distanceToPoint2 = __commonJS({
6668
6668
  "use strict";
6669
6669
  var vec3 = require_vec3();
6670
6670
  var closestPoint = require_closestPoint2();
6671
- var distanceToPoint = (line3, point2) => {
6672
- const closest = closestPoint(line3, point2);
6671
+ var distanceToPoint = (line4, point2) => {
6672
+ const closest = closestPoint(line4, point2);
6673
6673
  const distancevector = vec3.subtract(vec3.create(), point2, closest);
6674
6674
  return vec3.length(distancevector);
6675
6675
  };
@@ -6762,11 +6762,11 @@ var require_intersectPointOfLineAndPlane = __commonJS({
6762
6762
  "node_modules/@jscad/modeling/src/maths/line3/intersectPointOfLineAndPlane.js"(exports, module) {
6763
6763
  "use strict";
6764
6764
  var vec3 = require_vec3();
6765
- var intersectToPlane = (line3, plane) => {
6765
+ var intersectToPlane = (line4, plane) => {
6766
6766
  const pnormal = plane;
6767
6767
  const pw = plane[3];
6768
- const lpoint = line3[0];
6769
- const ldirection = line3[1];
6768
+ const lpoint = line4[0];
6769
+ const ldirection = line4[1];
6770
6770
  const labda = (pw - vec3.dot(pnormal, lpoint)) / vec3.dot(pnormal, ldirection);
6771
6771
  const point2 = vec3.add(vec3.create(), lpoint, vec3.scale(vec3.create(), ldirection, labda));
6772
6772
  return point2;
@@ -6779,7 +6779,7 @@ var require_intersectPointOfLineAndPlane = __commonJS({
6779
6779
  var require_origin2 = __commonJS({
6780
6780
  "node_modules/@jscad/modeling/src/maths/line3/origin.js"(exports, module) {
6781
6781
  "use strict";
6782
- var origin = (line3) => line3[0];
6782
+ var origin = (line4) => line4[0];
6783
6783
  module.exports = origin;
6784
6784
  }
6785
6785
  });
@@ -6790,9 +6790,9 @@ var require_reverse4 = __commonJS({
6790
6790
  "use strict";
6791
6791
  var vec3 = require_vec3();
6792
6792
  var fromPointAndDirection = require_fromPointAndDirection();
6793
- var reverse = (out, line3) => {
6794
- const point2 = vec3.clone(line3[0]);
6795
- const direction = vec3.negate(vec3.create(), line3[1]);
6793
+ var reverse = (out, line4) => {
6794
+ const point2 = vec3.clone(line4[0]);
6795
+ const direction = vec3.negate(vec3.create(), line4[1]);
6796
6796
  return fromPointAndDirection(out, point2, direction);
6797
6797
  };
6798
6798
  module.exports = reverse;
@@ -6803,9 +6803,9 @@ var require_reverse4 = __commonJS({
6803
6803
  var require_toString10 = __commonJS({
6804
6804
  "node_modules/@jscad/modeling/src/maths/line3/toString.js"(exports, module) {
6805
6805
  "use strict";
6806
- var toString = (line3) => {
6807
- const point2 = line3[0];
6808
- const direction = line3[1];
6806
+ var toString = (line4) => {
6807
+ const point2 = line4[0];
6808
+ const direction = line4[1];
6809
6809
  return `line3: point: (${point2[0].toFixed(7)}, ${point2[1].toFixed(7)}, ${point2[2].toFixed(7)}) direction: (${direction[0].toFixed(7)}, ${direction[1].toFixed(7)}, ${direction[2].toFixed(7)})`;
6810
6810
  };
6811
6811
  module.exports = toString;
@@ -6818,9 +6818,9 @@ var require_transform10 = __commonJS({
6818
6818
  "use strict";
6819
6819
  var vec3 = require_vec3();
6820
6820
  var fromPointAndDirection = require_fromPointAndDirection();
6821
- var transform2 = (out, line3, matrix) => {
6822
- const point2 = line3[0];
6823
- const direction = line3[1];
6821
+ var transform2 = (out, line4, matrix) => {
6822
+ const point2 = line4[0];
6823
+ const direction = line4[1];
6824
6824
  const pointPlusDirection = vec3.add(vec3.create(), point2, direction);
6825
6825
  const newpoint = vec3.transform(vec3.create(), point2, matrix);
6826
6826
  const newPointPlusDirection = vec3.transform(pointPlusDirection, pointPlusDirection, matrix);
@@ -8033,11 +8033,11 @@ var require_line = __commonJS({
8033
8033
  "node_modules/@jscad/modeling/src/primitives/line.js"(exports, module) {
8034
8034
  "use strict";
8035
8035
  var path2 = require_path2();
8036
- var line3 = (points) => {
8036
+ var line4 = (points) => {
8037
8037
  if (!Array.isArray(points)) throw new Error("points must be an array");
8038
8038
  return path2.fromPoints({}, points);
8039
8039
  };
8040
- module.exports = line3;
8040
+ module.exports = line4;
8041
8041
  }
8042
8042
  });
8043
8043
 
@@ -9746,7 +9746,7 @@ var require_translate2 = __commonJS({
9746
9746
  var geom2 = require_geom2();
9747
9747
  var geom3 = require_geom3();
9748
9748
  var path2 = require_path2();
9749
- var translate6 = (offset4, ...objects) => {
9749
+ var translate7 = (offset4, ...objects) => {
9750
9750
  if (!Array.isArray(offset4)) throw new Error("offset must be an array");
9751
9751
  objects = flatten(objects);
9752
9752
  if (objects.length === 0) throw new Error("wrong number of arguments");
@@ -9761,11 +9761,11 @@ var require_translate2 = __commonJS({
9761
9761
  });
9762
9762
  return results.length === 1 ? results[0] : results;
9763
9763
  };
9764
- var translateX = (offset4, ...objects) => translate6([offset4, 0, 0], objects);
9765
- var translateY = (offset4, ...objects) => translate6([0, offset4, 0], objects);
9766
- var translateZ = (offset4, ...objects) => translate6([0, 0, offset4], objects);
9764
+ var translateX = (offset4, ...objects) => translate7([offset4, 0, 0], objects);
9765
+ var translateY = (offset4, ...objects) => translate7([0, offset4, 0], objects);
9766
+ var translateZ = (offset4, ...objects) => translate7([0, 0, offset4], objects);
9767
9767
  module.exports = {
9768
- translate: translate6,
9768
+ translate: translate7,
9769
9769
  translateX,
9770
9770
  translateY,
9771
9771
  translateZ
@@ -9780,7 +9780,7 @@ var require_torus = __commonJS({
9780
9780
  var { TAU } = require_constants();
9781
9781
  var extrudeRotate = require_extrudeRotate();
9782
9782
  var { rotate: rotate2 } = require_rotate3();
9783
- var { translate: translate6 } = require_translate2();
9783
+ var { translate: translate7 } = require_translate2();
9784
9784
  var circle = require_circle();
9785
9785
  var { isGT, isGTE } = require_commonChecks();
9786
9786
  var torus = (options) => {
@@ -9805,7 +9805,7 @@ var require_torus = __commonJS({
9805
9805
  if (innerRotation !== 0) {
9806
9806
  innerCircle = rotate2([0, 0, innerRotation], innerCircle);
9807
9807
  }
9808
- innerCircle = translate6([outerRadius, 0], innerCircle);
9808
+ innerCircle = translate7([outerRadius, 0], innerCircle);
9809
9809
  const extrudeOptions = {
9810
9810
  startAngle,
9811
9811
  angle: outerRotation,
@@ -10148,9 +10148,9 @@ var require_vectorText = __commonJS({
10148
10148
  "use strict";
10149
10149
  var vectorChar = require_vectorChar();
10150
10150
  var vectorParams = require_vectorParams();
10151
- var translateLine = (options, line3) => {
10151
+ var translateLine = (options, line4) => {
10152
10152
  const { x, y } = Object.assign({ x: 0, y: 0 }, options || {});
10153
- const segments = line3.segments;
10153
+ const segments = line4.segments;
10154
10154
  let segment = null;
10155
10155
  let point2 = null;
10156
10156
  for (let i = 0, il = segments.length; i < il; i++) {
@@ -10160,7 +10160,7 @@ var require_vectorText = __commonJS({
10160
10160
  segment[j] = [point2[0] + x, point2[1] + y];
10161
10161
  }
10162
10162
  }
10163
- return line3;
10163
+ return line4;
10164
10164
  };
10165
10165
  var vectorText3 = (options, text) => {
10166
10166
  const {
@@ -10176,15 +10176,15 @@ var require_vectorText = __commonJS({
10176
10176
  } = vectorParams(options, text);
10177
10177
  let [x, y] = [xOffset, yOffset];
10178
10178
  let i, il, char, vect, width10, diff;
10179
- let line3 = { width: 0, segments: [] };
10179
+ let line4 = { width: 0, segments: [] };
10180
10180
  const lines = [];
10181
10181
  let output = [];
10182
10182
  let maxWidth = 0;
10183
10183
  const lineStart = x;
10184
10184
  const pushLine = () => {
10185
- lines.push(line3);
10186
- maxWidth = Math.max(maxWidth, line3.width);
10187
- line3 = { width: 0, segments: [] };
10185
+ lines.push(line4);
10186
+ maxWidth = Math.max(maxWidth, line4.width);
10187
+ line4 = { width: 0, segments: [] };
10188
10188
  };
10189
10189
  for (i = 0, il = input.length; i < il; i++) {
10190
10190
  char = input[i];
@@ -10196,26 +10196,26 @@ var require_vectorText = __commonJS({
10196
10196
  continue;
10197
10197
  }
10198
10198
  width10 = vect.width * letterSpacing;
10199
- line3.width += width10;
10199
+ line4.width += width10;
10200
10200
  x += width10;
10201
10201
  if (char !== " ") {
10202
- line3.segments = line3.segments.concat(vect.segments);
10202
+ line4.segments = line4.segments.concat(vect.segments);
10203
10203
  }
10204
10204
  }
10205
- if (line3.segments.length) {
10205
+ if (line4.segments.length) {
10206
10206
  pushLine();
10207
10207
  }
10208
10208
  for (i = 0, il = lines.length; i < il; i++) {
10209
- line3 = lines[i];
10210
- if (maxWidth > line3.width) {
10211
- diff = maxWidth - line3.width;
10209
+ line4 = lines[i];
10210
+ if (maxWidth > line4.width) {
10211
+ diff = maxWidth - line4.width;
10212
10212
  if (align === "right") {
10213
- line3 = translateLine({ x: diff }, line3);
10213
+ line4 = translateLine({ x: diff }, line4);
10214
10214
  } else if (align === "center") {
10215
- line3 = translateLine({ x: diff / 2 }, line3);
10215
+ line4 = translateLine({ x: diff / 2 }, line4);
10216
10216
  }
10217
10217
  }
10218
- output = output.concat(line3.segments);
10218
+ output = output.concat(line4.segments);
10219
10219
  }
10220
10220
  return output;
10221
10221
  };
@@ -12269,7 +12269,7 @@ var require_expand = __commonJS({
12269
12269
  var expandGeom2 = require_expandGeom2();
12270
12270
  var expandGeom3 = require_expandGeom3();
12271
12271
  var expandPath2 = require_expandPath2();
12272
- var expand4 = (options, ...objects) => {
12272
+ var expand5 = (options, ...objects) => {
12273
12273
  objects = flatten(objects);
12274
12274
  if (objects.length === 0) throw new Error("wrong number of arguments");
12275
12275
  const results = objects.map((object) => {
@@ -12280,7 +12280,7 @@ var require_expand = __commonJS({
12280
12280
  });
12281
12281
  return results.length === 1 ? results[0] : results;
12282
12282
  };
12283
- module.exports = expand4;
12283
+ module.exports = expand5;
12284
12284
  }
12285
12285
  });
12286
12286
 
@@ -12451,7 +12451,7 @@ var require_extrudeLinear = __commonJS({
12451
12451
  var path2 = require_path2();
12452
12452
  var extrudeLinearGeom2 = require_extrudeLinearGeom2();
12453
12453
  var extrudeLinearPath2 = require_extrudeLinearPath2();
12454
- var extrudeLinear5 = (options, ...objects) => {
12454
+ var extrudeLinear6 = (options, ...objects) => {
12455
12455
  const defaults = {
12456
12456
  height: 1,
12457
12457
  twistAngle: 0,
@@ -12469,7 +12469,7 @@ var require_extrudeLinear = __commonJS({
12469
12469
  });
12470
12470
  return results.length === 1 ? results[0] : results;
12471
12471
  };
12472
- module.exports = extrudeLinear5;
12472
+ module.exports = extrudeLinear6;
12473
12473
  }
12474
12474
  });
12475
12475
 
@@ -12478,7 +12478,7 @@ var require_extrudeRectangularPath2 = __commonJS({
12478
12478
  "node_modules/@jscad/modeling/src/operations/extrusions/extrudeRectangularPath2.js"(exports, module) {
12479
12479
  "use strict";
12480
12480
  var path2 = require_path2();
12481
- var expand4 = require_expand();
12481
+ var expand5 = require_expand();
12482
12482
  var extrudeLinearGeom2 = require_extrudeLinearGeom2();
12483
12483
  var extrudeRectangularPath2 = (options, geometry) => {
12484
12484
  const defaults = {
@@ -12490,7 +12490,7 @@ var require_extrudeRectangularPath2 = __commonJS({
12490
12490
  options.offset = [0, 0, height10];
12491
12491
  const points = path2.toPoints(geometry);
12492
12492
  if (points.length === 0) throw new Error("the given geometry cannot be empty");
12493
- const newgeometry = expand4(options, geometry);
12493
+ const newgeometry = expand5(options, geometry);
12494
12494
  return extrudeLinearGeom2(options, newgeometry);
12495
12495
  };
12496
12496
  module.exports = extrudeRectangularPath2;
@@ -12504,7 +12504,7 @@ var require_extrudeRectangularGeom2 = __commonJS({
12504
12504
  var { area } = require_utils();
12505
12505
  var geom2 = require_geom2();
12506
12506
  var path2 = require_path2();
12507
- var expand4 = require_expand();
12507
+ var expand5 = require_expand();
12508
12508
  var extrudeLinearGeom2 = require_extrudeLinearGeom2();
12509
12509
  var extrudeRectangularGeom2 = (options, geometry) => {
12510
12510
  const defaults = {
@@ -12518,7 +12518,7 @@ var require_extrudeRectangularGeom2 = __commonJS({
12518
12518
  if (outlines.length === 0) throw new Error("the given geometry cannot be empty");
12519
12519
  const newparts = outlines.map((outline) => {
12520
12520
  if (area(outline) < 0) outline.reverse();
12521
- return expand4(options, path2.fromPoints({ closed: true }, outline));
12521
+ return expand5(options, path2.fromPoints({ closed: true }, outline));
12522
12522
  });
12523
12523
  const allsides = newparts.reduce((sides2, part) => sides2.concat(geom2.toSides(part)), []);
12524
12524
  const newgeometry = geom2.create(allsides);
@@ -13528,7 +13528,7 @@ var require_align = __commonJS({
13528
13528
  var flatten = require_flatten();
13529
13529
  var padArrayToLength = require_padArrayToLength();
13530
13530
  var measureAggregateBoundingBox = require_measureAggregateBoundingBox();
13531
- var { translate: translate6 } = require_translate2();
13531
+ var { translate: translate7 } = require_translate2();
13532
13532
  var validateOptions = (options) => {
13533
13533
  if (!Array.isArray(options.modes) || options.modes.length > 3) throw new Error("align(): modes must be an array of length <= 3");
13534
13534
  options.modes = padArrayToLength(options.modes, "none", 3);
@@ -13565,7 +13565,7 @@ var require_align = __commonJS({
13565
13565
  translation[i] = relativeTo[i] - bounds[0][i];
13566
13566
  }
13567
13567
  }
13568
- return translate6(translation, geometry);
13568
+ return translate7(translation, geometry);
13569
13569
  };
13570
13570
  var align = (options, ...geometries) => {
13571
13571
  const defaults = {
@@ -13602,7 +13602,7 @@ var require_center = __commonJS({
13602
13602
  var geom3 = require_geom3();
13603
13603
  var path2 = require_path2();
13604
13604
  var measureBoundingBox = require_measureBoundingBox2();
13605
- var { translate: translate6 } = require_translate2();
13605
+ var { translate: translate7 } = require_translate2();
13606
13606
  var centerGeometry = (options, object) => {
13607
13607
  const defaults = {
13608
13608
  axes: [true, true, true],
@@ -13614,7 +13614,7 @@ var require_center = __commonJS({
13614
13614
  if (axes[0]) offset4[0] = relativeTo[0] - (bounds[0][0] + (bounds[1][0] - bounds[0][0]) / 2);
13615
13615
  if (axes[1]) offset4[1] = relativeTo[1] - (bounds[0][1] + (bounds[1][1] - bounds[0][1]) / 2);
13616
13616
  if (axes[2]) offset4[2] = relativeTo[2] - (bounds[0][2] + (bounds[1][2] - bounds[0][2]) / 2);
13617
- return translate6(offset4, object);
13617
+ return translate7(offset4, object);
13618
13618
  };
13619
13619
  var center = (options, ...objects) => {
13620
13620
  const defaults = {
@@ -24177,7 +24177,7 @@ var m2host = (raw_params) => {
24177
24177
  }
24178
24178
  const centerX = (minX + maxX) / 2;
24179
24179
  const centerY = (minY + maxY) / 2;
24180
- const translate6 = (el) => {
24180
+ const translate7 = (el) => {
24181
24181
  if (typeof el.x === "number") el.x -= centerX;
24182
24182
  if (typeof el.y === "number") el.y -= centerY;
24183
24183
  if (el.center) {
@@ -24191,9 +24191,9 @@ var m2host = (raw_params) => {
24191
24191
  }));
24192
24192
  }
24193
24193
  };
24194
- for (const pad2 of pads) translate6(pad2);
24195
- translate6(cutout);
24196
- translate6(pin1Marker);
24194
+ for (const pad2 of pads) translate7(pad2);
24195
+ translate7(cutout);
24196
+ translate7(pin1Marker);
24197
24197
  return {
24198
24198
  circuitJson: [
24199
24199
  ...pads,
@@ -26647,7 +26647,7 @@ import * as THREE14 from "three";
26647
26647
  // package.json
26648
26648
  var package_default = {
26649
26649
  name: "@tscircuit/3d-viewer",
26650
- version: "0.0.420",
26650
+ version: "0.0.422",
26651
26651
  main: "./dist/index.js",
26652
26652
  module: "./dist/index.js",
26653
26653
  type: "module",
@@ -26718,7 +26718,7 @@ var package_default = {
26718
26718
  "react-use-gesture": "^9.1.3",
26719
26719
  semver: "^7.7.0",
26720
26720
  "strip-ansi": "^7.1.0",
26721
- tscircuit: "^0.0.746",
26721
+ tscircuit: "^0.0.834",
26722
26722
  tsup: "^8.3.6",
26723
26723
  typescript: "^5.7.3",
26724
26724
  vite: "^7.1.5",
@@ -27810,9 +27810,9 @@ var createBoardGeomFromCircuitJson = (circuitJson, opts = {}) => {
27810
27810
  };
27811
27811
 
27812
27812
  // src/BoardGeomBuilder.ts
27813
- var import_transforms4 = __toESM(require_transforms(), 1);
27814
- var import_primitives6 = __toESM(require_primitives(), 1);
27815
- var import_colors4 = __toESM(require_colors(), 1);
27813
+ var import_transforms5 = __toESM(require_transforms(), 1);
27814
+ var import_primitives7 = __toESM(require_primitives(), 1);
27815
+ var import_colors5 = __toESM(require_colors(), 1);
27816
27816
  var import_booleans3 = __toESM(require_booleans(), 1);
27817
27817
  import { su as su3 } from "@tscircuit/circuit-json-util";
27818
27818
 
@@ -28196,8 +28196,8 @@ var platedHole = (plated_hole, ctx, options = {}) => {
28196
28196
  };
28197
28197
 
28198
28198
  // src/BoardGeomBuilder.ts
28199
- var import_extrusions4 = __toESM(require_extrusions(), 1);
28200
- var import_expansions3 = __toESM(require_expansions(), 1);
28199
+ var import_extrusions5 = __toESM(require_extrusions(), 1);
28200
+ var import_expansions4 = __toESM(require_expansions(), 1);
28201
28201
 
28202
28202
  // src/geoms/create-geoms-for-silkscreen-text.ts
28203
28203
  var import_text = __toESM(require_text(), 1);
@@ -28333,10 +28333,10 @@ peg$SyntaxError.prototype.format = function(sources) {
28333
28333
  if (src) {
28334
28334
  var e = this.location.end;
28335
28335
  var filler = peg$padEnd("", offset_s.line.toString().length, " ");
28336
- var line3 = src[s.line - 1];
28337
- var last = s.line === e.line ? e.column : line3.length + 1;
28336
+ var line4 = src[s.line - 1];
28337
+ var last = s.line === e.line ? e.column : line4.length + 1;
28338
28338
  var hatLen = last - s.column || 1;
28339
- str += "\n --> " + loc + "\n" + filler + " |\n" + offset_s.line + " | " + line3 + "\n" + filler + " | " + peg$padEnd("", s.column - 1, " ") + peg$padEnd("", hatLen, "^");
28339
+ str += "\n --> " + loc + "\n" + filler + " |\n" + offset_s.line + " | " + line4 + "\n" + filler + " | " + peg$padEnd("", s.column - 1, " ") + peg$padEnd("", hatLen, "^");
28340
28340
  } else {
28341
28341
  str += "\n at " + loc;
28342
28342
  }
@@ -28506,11 +28506,61 @@ var import_expansions2 = __toESM(require_expansions(), 1);
28506
28506
  var import_extrusions3 = __toESM(require_extrusions(), 1);
28507
28507
  var import_transforms3 = __toESM(require_transforms(), 1);
28508
28508
  var import_colors3 = __toESM(require_colors(), 1);
28509
+
28510
+ // src/utils/units.ts
28511
+ var MM_PER_INCH = 25.4;
28512
+ var MM_PER_MIL = MM_PER_INCH / 1e3;
28513
+ var dimensionRegex = /^\s*(-?\d*(?:\.\d+)?)(?:\s*(mm|mil|inch|in|"))?\s*$/i;
28514
+ function normalizeUnit(unit) {
28515
+ if (!unit) return void 0;
28516
+ const normalized = unit.trim().toLowerCase();
28517
+ if (normalized === '"') return "in";
28518
+ if (normalized === "inch") return "in";
28519
+ return normalized;
28520
+ }
28521
+ function parseDimensionToMm(value) {
28522
+ if (value === null || value === void 0) return void 0;
28523
+ if (typeof value === "number") {
28524
+ return Number.isFinite(value) ? value : void 0;
28525
+ }
28526
+ if (typeof value !== "string") return void 0;
28527
+ const trimmed = value.trim();
28528
+ if (trimmed.length === 0) return void 0;
28529
+ const match = trimmed.match(dimensionRegex);
28530
+ if (!match) {
28531
+ const numeric = Number.parseFloat(trimmed);
28532
+ return Number.isFinite(numeric) ? numeric : void 0;
28533
+ }
28534
+ const [, magnitudeRaw, unitRaw] = match;
28535
+ const magnitude = Number.parseFloat(magnitudeRaw || "0");
28536
+ if (!Number.isFinite(magnitude)) return void 0;
28537
+ const unit = normalizeUnit(unitRaw);
28538
+ switch (unit) {
28539
+ case "mil":
28540
+ return magnitude * MM_PER_MIL;
28541
+ case "in":
28542
+ return magnitude * MM_PER_INCH;
28543
+ case "mm":
28544
+ case void 0:
28545
+ return magnitude;
28546
+ default:
28547
+ return magnitude;
28548
+ }
28549
+ }
28550
+ function coerceDimensionToMm(value, fallback) {
28551
+ const parsed = parseDimensionToMm(value);
28552
+ return parsed === void 0 ? fallback : parsed;
28553
+ }
28554
+
28555
+ // src/geoms/create-geoms-for-silkscreen-path.ts
28509
28556
  function createSilkscreenPathGeom(sp, ctx) {
28510
28557
  if (sp.route.length < 2) return void 0;
28511
- const routePoints = sp.route.map((p) => [p.x, p.y]);
28558
+ const routePoints = sp.route.map((p) => [
28559
+ parseDimensionToMm(p.x) ?? 0,
28560
+ parseDimensionToMm(p.y) ?? 0
28561
+ ]);
28512
28562
  const pathLine = (0, import_primitives4.line)(routePoints);
28513
- const strokeWidth = sp.stroke_width || 0.1;
28563
+ const strokeWidth = coerceDimensionToMm(sp.stroke_width, 0.1);
28514
28564
  const expandedPath = (0, import_expansions2.expand)(
28515
28565
  { delta: strokeWidth / 2, corners: "round" },
28516
28566
  pathLine
@@ -28526,8 +28576,40 @@ function createSilkscreenPathGeom(sp, ctx) {
28526
28576
  return pathGeom;
28527
28577
  }
28528
28578
 
28529
- // src/geoms/brep-converter.ts
28579
+ // src/geoms/create-geoms-for-silkscreen-line.ts
28530
28580
  var import_primitives5 = __toESM(require_primitives(), 1);
28581
+ var import_expansions3 = __toESM(require_expansions(), 1);
28582
+ var import_extrusions4 = __toESM(require_extrusions(), 1);
28583
+ var import_transforms4 = __toESM(require_transforms(), 1);
28584
+ var import_colors4 = __toESM(require_colors(), 1);
28585
+ function createSilkscreenLineGeom(sl, ctx) {
28586
+ const x1 = parseDimensionToMm(sl.x1) ?? 0;
28587
+ const y1 = parseDimensionToMm(sl.y1) ?? 0;
28588
+ const x2 = parseDimensionToMm(sl.x2) ?? 0;
28589
+ const y2 = parseDimensionToMm(sl.y2) ?? 0;
28590
+ if (x1 === x2 && y1 === y2) return void 0;
28591
+ const routePoints = [
28592
+ [x1, y1],
28593
+ [x2, y2]
28594
+ ];
28595
+ const baseLine = (0, import_primitives5.line)(routePoints);
28596
+ const strokeWidth = coerceDimensionToMm(sl.stroke_width, 0.1);
28597
+ const expandedLine = (0, import_expansions3.expand)(
28598
+ { delta: strokeWidth / 2, corners: "round" },
28599
+ baseLine
28600
+ );
28601
+ const layerSign = sl.layer === "bottom" ? -1 : 1;
28602
+ const zPos = layerSign * ctx.pcbThickness / 2 + layerSign * M * 1.5;
28603
+ let lineGeom = (0, import_transforms4.translate)(
28604
+ [0, 0, zPos],
28605
+ (0, import_extrusions4.extrudeLinear)({ height: 0.012 }, expandedLine)
28606
+ );
28607
+ lineGeom = (0, import_colors4.colorize)([1, 1, 1], lineGeom);
28608
+ return lineGeom;
28609
+ }
28610
+
28611
+ // src/geoms/brep-converter.ts
28612
+ var import_primitives6 = __toESM(require_primitives(), 1);
28531
28613
  var import_booleans2 = __toESM(require_booleans(), 1);
28532
28614
  function segmentToPoints(p1, p2, bulge, arcSegments) {
28533
28615
  if (!bulge || Math.abs(bulge) < 1e-9) {
@@ -28596,7 +28678,7 @@ function createGeom2FromBRep(brep, arcSegments = 16) {
28596
28678
  if (arePointsClockwise2(outerPoints)) {
28597
28679
  outerPoints.reverse();
28598
28680
  }
28599
- const outerGeom = (0, import_primitives5.polygon)({ points: outerPoints });
28681
+ const outerGeom = (0, import_primitives6.polygon)({ points: outerPoints });
28600
28682
  if (!brep.inner_rings || brep.inner_rings.length === 0) {
28601
28683
  return outerGeom;
28602
28684
  }
@@ -28605,7 +28687,7 @@ function createGeom2FromBRep(brep, arcSegments = 16) {
28605
28687
  if (arePointsClockwise2(innerPoints)) {
28606
28688
  innerPoints.reverse();
28607
28689
  }
28608
- return (0, import_primitives5.polygon)({ points: innerPoints });
28690
+ return (0, import_primitives6.polygon)({ points: innerPoints });
28609
28691
  });
28610
28692
  if (innerGeoms.length === 0) return outerGeom;
28611
28693
  return (0, import_booleans2.subtract)(outerGeom, innerGeoms);
@@ -28618,15 +28700,15 @@ var BOARD_CLIP_XY_OUTSET = 0.05;
28618
28700
  var createCenteredRectPadGeom = (width10, height10, thickness, rectBorderRadius) => {
28619
28701
  const clampedRadius = clampRectBorderRadius(width10, height10, rectBorderRadius);
28620
28702
  if (clampedRadius <= 0) {
28621
- return (0, import_primitives6.cuboid)({ center: [0, 0, 0], size: [width10, height10, thickness] });
28703
+ return (0, import_primitives7.cuboid)({ center: [0, 0, 0], size: [width10, height10, thickness] });
28622
28704
  }
28623
- const rect2d = (0, import_primitives6.roundedRectangle)({
28705
+ const rect2d = (0, import_primitives7.roundedRectangle)({
28624
28706
  size: [width10, height10],
28625
28707
  roundRadius: clampedRadius,
28626
28708
  segments: PAD_ROUNDED_SEGMENTS
28627
28709
  });
28628
- const extruded = (0, import_extrusions4.extrudeLinear)({ height: thickness }, rect2d);
28629
- return (0, import_transforms4.translate)([0, 0, -thickness / 2], extruded);
28710
+ const extruded = (0, import_extrusions5.extrudeLinear)({ height: thickness }, rect2d);
28711
+ return (0, import_transforms5.translate)([0, 0, -thickness / 2], extruded);
28630
28712
  };
28631
28713
  var buildStateOrder = [
28632
28714
  "initializing",
@@ -28638,6 +28720,7 @@ var buildStateOrder = [
28638
28720
  "processing_traces",
28639
28721
  "processing_vias",
28640
28722
  "processing_silkscreen_text",
28723
+ "processing_silkscreen_lines",
28641
28724
  "processing_silkscreen_paths",
28642
28725
  "finalizing",
28643
28726
  "done"
@@ -28652,6 +28735,7 @@ var BoardGeomBuilder = class {
28652
28735
  pcb_vias;
28653
28736
  silkscreenTexts;
28654
28737
  silkscreenPaths;
28738
+ silkscreenLines;
28655
28739
  pcb_cutouts;
28656
28740
  pcb_copper_pours;
28657
28741
  boardGeom = null;
@@ -28664,6 +28748,7 @@ var BoardGeomBuilder = class {
28664
28748
  // Combined with platedHoleGeoms
28665
28749
  silkscreenTextGeoms = [];
28666
28750
  silkscreenPathGeoms = [];
28751
+ silkscreenLineGeoms = [];
28667
28752
  copperPourGeoms = [];
28668
28753
  boardClipGeom = null;
28669
28754
  state = "initializing";
@@ -28697,6 +28782,7 @@ var BoardGeomBuilder = class {
28697
28782
  this.pcb_vias = su3(circuitJson).pcb_via.list();
28698
28783
  this.silkscreenTexts = su3(circuitJson).pcb_silkscreen_text.list();
28699
28784
  this.silkscreenPaths = su3(circuitJson).pcb_silkscreen_path.list();
28785
+ this.silkscreenLines = su3(circuitJson).pcb_silkscreen_line.list();
28700
28786
  this.pcb_cutouts = su3(circuitJson).pcb_cutout.list();
28701
28787
  this.pcb_copper_pours = circuitJson.filter(
28702
28788
  (e) => e.type === "pcb_copper_pour"
@@ -28721,11 +28807,11 @@ var BoardGeomBuilder = class {
28721
28807
  { xyOutset: BOARD_CLIP_XY_OUTSET }
28722
28808
  );
28723
28809
  } else {
28724
- this.boardGeom = (0, import_primitives6.cuboid)({
28810
+ this.boardGeom = (0, import_primitives7.cuboid)({
28725
28811
  size: [this.board.width, this.board.height, this.ctx.pcbThickness],
28726
28812
  center: [this.board.center.x, this.board.center.y, 0]
28727
28813
  });
28728
- this.boardClipGeom = (0, import_primitives6.cuboid)({
28814
+ this.boardClipGeom = (0, import_primitives7.cuboid)({
28729
28815
  size: [
28730
28816
  this.board.width + 2 * BOARD_CLIP_XY_OUTSET,
28731
28817
  this.board.height + 2 * BOARD_CLIP_XY_OUTSET,
@@ -28797,6 +28883,14 @@ var BoardGeomBuilder = class {
28797
28883
  this.goToNextState();
28798
28884
  }
28799
28885
  break;
28886
+ case "processing_silkscreen_lines":
28887
+ if (this.currentIndex < this.silkscreenLines.length) {
28888
+ this.processSilkscreenLine(this.silkscreenLines[this.currentIndex]);
28889
+ this.currentIndex++;
28890
+ } else {
28891
+ this.goToNextState();
28892
+ }
28893
+ break;
28800
28894
  case "processing_silkscreen_paths":
28801
28895
  if (this.currentIndex < this.silkscreenPaths.length) {
28802
28896
  this.processSilkscreenPath(this.silkscreenPaths[this.currentIndex]);
@@ -28835,17 +28929,17 @@ var BoardGeomBuilder = class {
28835
28929
  const cutoutHeight = this.ctx.pcbThickness * 1.5;
28836
28930
  switch (cutout.shape) {
28837
28931
  case "rect":
28838
- cutoutGeom = (0, import_primitives6.cuboid)({
28932
+ cutoutGeom = (0, import_primitives7.cuboid)({
28839
28933
  center: [cutout.center.x, cutout.center.y, 0],
28840
28934
  size: [cutout.width, cutout.height, cutoutHeight]
28841
28935
  });
28842
28936
  if (cutout.rotation) {
28843
28937
  const rotationRadians = cutout.rotation * Math.PI / 180;
28844
- cutoutGeom = (0, import_transforms4.rotateZ)(rotationRadians, cutoutGeom);
28938
+ cutoutGeom = (0, import_transforms5.rotateZ)(rotationRadians, cutoutGeom);
28845
28939
  }
28846
28940
  break;
28847
28941
  case "circle":
28848
- cutoutGeom = (0, import_primitives6.cylinder)({
28942
+ cutoutGeom = (0, import_primitives7.cylinder)({
28849
28943
  center: [cutout.center.x, cutout.center.y, 0],
28850
28944
  radius: cutout.radius,
28851
28945
  height: cutoutHeight
@@ -28862,9 +28956,9 @@ var BoardGeomBuilder = class {
28862
28956
  if (arePointsClockwise(pointsVec2)) {
28863
28957
  pointsVec2 = pointsVec2.reverse();
28864
28958
  }
28865
- const polygon2d = (0, import_primitives6.polygon)({ points: pointsVec2 });
28866
- cutoutGeom = (0, import_extrusions4.extrudeLinear)({ height: cutoutHeight }, polygon2d);
28867
- cutoutGeom = (0, import_transforms4.translate)([0, 0, -cutoutHeight / 2], cutoutGeom);
28959
+ const polygon2d = (0, import_primitives7.polygon)({ points: pointsVec2 });
28960
+ cutoutGeom = (0, import_extrusions5.extrudeLinear)({ height: cutoutHeight }, polygon2d);
28961
+ cutoutGeom = (0, import_transforms5.translate)([0, 0, -cutoutHeight / 2], cutoutGeom);
28868
28962
  break;
28869
28963
  }
28870
28964
  if (cutoutGeom) {
@@ -28876,22 +28970,22 @@ var BoardGeomBuilder = class {
28876
28970
  const zPos = layerSign * this.ctx.pcbThickness / 2 + layerSign * BOARD_SURFACE_OFFSET.copper;
28877
28971
  let pourGeom = null;
28878
28972
  if (pour.shape === "rect") {
28879
- let baseGeom = (0, import_primitives6.cuboid)({
28973
+ let baseGeom = (0, import_primitives7.cuboid)({
28880
28974
  center: [0, 0, 0],
28881
28975
  // Create at origin for rotation
28882
28976
  size: [pour.width, pour.height, M]
28883
28977
  });
28884
28978
  if ("rotation" in pour && pour.rotation) {
28885
28979
  const rotationRadians = pour.rotation * Math.PI / 180;
28886
- baseGeom = (0, import_transforms4.rotateZ)(rotationRadians, baseGeom);
28980
+ baseGeom = (0, import_transforms5.rotateZ)(rotationRadians, baseGeom);
28887
28981
  }
28888
- pourGeom = (0, import_transforms4.translate)([pour.center.x, pour.center.y, zPos], baseGeom);
28982
+ pourGeom = (0, import_transforms5.translate)([pour.center.x, pour.center.y, zPos], baseGeom);
28889
28983
  } else if (pour.shape === "brep") {
28890
28984
  const brepShape = pour.brep_shape;
28891
28985
  if (brepShape && brepShape.outer_ring) {
28892
28986
  const pourGeom2 = createGeom2FromBRep(brepShape);
28893
- pourGeom = (0, import_extrusions4.extrudeLinear)({ height: M }, pourGeom2);
28894
- pourGeom = (0, import_transforms4.translate)([0, 0, zPos], pourGeom);
28987
+ pourGeom = (0, import_extrusions5.extrudeLinear)({ height: M }, pourGeom2);
28988
+ pourGeom = (0, import_transforms5.translate)([0, 0, zPos], pourGeom);
28895
28989
  }
28896
28990
  } else if (pour.shape === "polygon") {
28897
28991
  let pointsVec2 = pour.points.map((p) => [p.x, p.y]);
@@ -28904,15 +28998,15 @@ var BoardGeomBuilder = class {
28904
28998
  if (arePointsClockwise(pointsVec2)) {
28905
28999
  pointsVec2 = pointsVec2.reverse();
28906
29000
  }
28907
- const polygon2d = (0, import_primitives6.polygon)({ points: pointsVec2 });
28908
- pourGeom = (0, import_extrusions4.extrudeLinear)({ height: M }, polygon2d);
28909
- pourGeom = (0, import_transforms4.translate)([0, 0, zPos], pourGeom);
29001
+ const polygon2d = (0, import_primitives7.polygon)({ points: pointsVec2 });
29002
+ pourGeom = (0, import_extrusions5.extrudeLinear)({ height: M }, polygon2d);
29003
+ pourGeom = (0, import_transforms5.translate)([0, 0, zPos], pourGeom);
28910
29004
  }
28911
29005
  if (pourGeom) {
28912
29006
  if (this.boardClipGeom) {
28913
29007
  pourGeom = (0, import_booleans3.intersect)(this.boardClipGeom, pourGeom);
28914
29008
  }
28915
- const coloredPourGeom = (0, import_colors4.colorize)(colors.copper, pourGeom);
29009
+ const coloredPourGeom = (0, import_colors5.colorize)(colors.copper, pourGeom);
28916
29010
  this.copperPourGeoms.push(coloredPourGeom);
28917
29011
  }
28918
29012
  }
@@ -28921,7 +29015,7 @@ var BoardGeomBuilder = class {
28921
29015
  if (ph.shape === "circle" || ph.shape === "circular_hole_with_rect_pad") {
28922
29016
  let cyGeom = null;
28923
29017
  if (ph.shape === "circular_hole_with_rect_pad") {
28924
- cyGeom = (0, import_primitives6.cylinder)({
29018
+ cyGeom = (0, import_primitives7.cylinder)({
28925
29019
  center: [
28926
29020
  ph.x + (ph.hole_offset_x || 0),
28927
29021
  ph.y + (ph.hole_offset_y || 0),
@@ -28933,7 +29027,7 @@ var BoardGeomBuilder = class {
28933
29027
  // Ensure it cuts through
28934
29028
  });
28935
29029
  } else {
28936
- cyGeom = (0, import_primitives6.cylinder)({
29030
+ cyGeom = (0, import_primitives7.cylinder)({
28937
29031
  center: [ph.x, ph.y, 0],
28938
29032
  radius: ph.hole_diameter / 2 + M,
28939
29033
  // Add margin for subtraction
@@ -28945,7 +29039,7 @@ var BoardGeomBuilder = class {
28945
29039
  this.boardGeom = (0, import_booleans3.subtract)(this.boardGeom, cyGeom);
28946
29040
  }
28947
29041
  this.padGeoms = this.padGeoms.map(
28948
- (pg) => (0, import_colors4.colorize)(colors.copper, (0, import_booleans3.subtract)(pg, cyGeom))
29042
+ (pg) => (0, import_colors5.colorize)(colors.copper, (0, import_booleans3.subtract)(pg, cyGeom))
28949
29043
  );
28950
29044
  const platedHoleGeom = platedHole(ph, this.ctx, {
28951
29045
  clipGeom: this.boardClipGeom
@@ -28960,7 +29054,7 @@ var BoardGeomBuilder = class {
28960
29054
  let pillHole;
28961
29055
  if (ph.shape === "pill_hole_with_rect_pad") {
28962
29056
  pillHole = (0, import_booleans3.union)(
28963
- (0, import_primitives6.cuboid)({
29057
+ (0, import_primitives7.cuboid)({
28964
29058
  center: [
28965
29059
  ph.x + (ph.hole_offset_x || 0),
28966
29060
  ph.y + (ph.hole_offset_y || 0),
@@ -28968,7 +29062,7 @@ var BoardGeomBuilder = class {
28968
29062
  ],
28969
29063
  size: shouldRotate ? [holeHeight, rectLength, this.ctx.pcbThickness * 1.5] : [rectLength, holeHeight, this.ctx.pcbThickness * 1.5]
28970
29064
  }),
28971
- (0, import_primitives6.cylinder)({
29065
+ (0, import_primitives7.cylinder)({
28972
29066
  center: shouldRotate ? [
28973
29067
  ph.x + (ph.hole_offset_x || 0),
28974
29068
  ph.y + (ph.hole_offset_y || 0) - rectLength / 2,
@@ -28981,7 +29075,7 @@ var BoardGeomBuilder = class {
28981
29075
  radius: holeRadius,
28982
29076
  height: this.ctx.pcbThickness * 1.5
28983
29077
  }),
28984
- (0, import_primitives6.cylinder)({
29078
+ (0, import_primitives7.cylinder)({
28985
29079
  center: shouldRotate ? [
28986
29080
  ph.x + (ph.hole_offset_x || 0),
28987
29081
  ph.y + (ph.hole_offset_y || 0) + rectLength / 2,
@@ -28997,16 +29091,16 @@ var BoardGeomBuilder = class {
28997
29091
  );
28998
29092
  } else {
28999
29093
  pillHole = (0, import_booleans3.union)(
29000
- (0, import_primitives6.cuboid)({
29094
+ (0, import_primitives7.cuboid)({
29001
29095
  center: [ph.x, ph.y, 0],
29002
29096
  size: shouldRotate ? [holeHeight, rectLength, this.ctx.pcbThickness * 1.5] : [rectLength, holeHeight, this.ctx.pcbThickness * 1.5]
29003
29097
  }),
29004
- (0, import_primitives6.cylinder)({
29098
+ (0, import_primitives7.cylinder)({
29005
29099
  center: shouldRotate ? [ph.x, ph.y - rectLength / 2, 0] : [ph.x - rectLength / 2, ph.y, 0],
29006
29100
  radius: holeRadius,
29007
29101
  height: this.ctx.pcbThickness * 1.5
29008
29102
  }),
29009
- (0, import_primitives6.cylinder)({
29103
+ (0, import_primitives7.cylinder)({
29010
29104
  center: shouldRotate ? [ph.x, ph.y + rectLength / 2, 0] : [ph.x + rectLength / 2, ph.y, 0],
29011
29105
  radius: holeRadius,
29012
29106
  height: this.ctx.pcbThickness * 1.5
@@ -29017,7 +29111,7 @@ var BoardGeomBuilder = class {
29017
29111
  this.boardGeom = (0, import_booleans3.subtract)(this.boardGeom, pillHole);
29018
29112
  }
29019
29113
  this.padGeoms = this.padGeoms.map(
29020
- (pg) => (0, import_colors4.colorize)(colors.copper, (0, import_booleans3.subtract)(pg, pillHole))
29114
+ (pg) => (0, import_colors5.colorize)(colors.copper, (0, import_booleans3.subtract)(pg, pillHole))
29021
29115
  );
29022
29116
  const platedHoleGeom = platedHole(ph, this.ctx, {
29023
29117
  clipGeom: this.boardClipGeom
@@ -29030,22 +29124,22 @@ var BoardGeomBuilder = class {
29030
29124
  const holeDepth = this.ctx.pcbThickness * 1.5;
29031
29125
  const copperInset = 0.02;
29032
29126
  if (hole.hole_shape === "round" || hole.hole_shape === "circle") {
29033
- const cyGeom = (0, import_primitives6.cylinder)({
29127
+ const cyGeom = (0, import_primitives7.cylinder)({
29034
29128
  center: [hole.x, hole.y, 0],
29035
29129
  radius: hole.hole_diameter / 2 + M,
29036
29130
  height: holeDepth
29037
29131
  });
29038
29132
  this.boardGeom = (0, import_booleans3.subtract)(this.boardGeom, cyGeom);
29039
29133
  this.padGeoms = this.padGeoms.map(
29040
- (pg) => (0, import_colors4.colorize)(colors.copper, (0, import_booleans3.subtract)(pg, cyGeom))
29134
+ (pg) => (0, import_colors5.colorize)(colors.copper, (0, import_booleans3.subtract)(pg, cyGeom))
29041
29135
  );
29042
- const copperCut = (0, import_primitives6.cylinder)({
29136
+ const copperCut = (0, import_primitives7.cylinder)({
29043
29137
  center: [hole.x, hole.y, 0],
29044
29138
  radius: hole.hole_diameter / 2 + M / 2,
29045
29139
  height: holeDepth
29046
29140
  });
29047
29141
  this.platedHoleGeoms = this.platedHoleGeoms.map(
29048
- (phg) => (0, import_colors4.colorize)(colors.copper, (0, import_booleans3.subtract)(phg, copperCut))
29142
+ (phg) => (0, import_colors5.colorize)(colors.copper, (0, import_booleans3.subtract)(phg, copperCut))
29049
29143
  );
29050
29144
  } else if (hole.hole_shape === "pill" || hole.hole_shape === "rotated_pill") {
29051
29145
  const holeWidth = hole.hole_width;
@@ -29056,16 +29150,16 @@ var BoardGeomBuilder = class {
29056
29150
  let pillHole;
29057
29151
  if (holeWidth > holeHeight) {
29058
29152
  pillHole = (0, import_booleans3.union)(
29059
- (0, import_primitives6.cuboid)({
29153
+ (0, import_primitives7.cuboid)({
29060
29154
  center: [hole.x, hole.y, 0],
29061
29155
  size: [rectLength, holeHeight, holeDepth]
29062
29156
  }),
29063
- (0, import_primitives6.cylinder)({
29157
+ (0, import_primitives7.cylinder)({
29064
29158
  center: [hole.x - rectLength / 2, hole.y, 0],
29065
29159
  radius: holeRadius,
29066
29160
  height: holeDepth
29067
29161
  }),
29068
- (0, import_primitives6.cylinder)({
29162
+ (0, import_primitives7.cylinder)({
29069
29163
  center: [hole.x + rectLength / 2, hole.y, 0],
29070
29164
  radius: holeRadius,
29071
29165
  height: holeDepth
@@ -29073,16 +29167,16 @@ var BoardGeomBuilder = class {
29073
29167
  );
29074
29168
  } else {
29075
29169
  pillHole = (0, import_booleans3.union)(
29076
- (0, import_primitives6.cuboid)({
29170
+ (0, import_primitives7.cuboid)({
29077
29171
  center: [hole.x, hole.y, 0],
29078
29172
  size: [holeWidth, rectLength, holeDepth]
29079
29173
  }),
29080
- (0, import_primitives6.cylinder)({
29174
+ (0, import_primitives7.cylinder)({
29081
29175
  center: [hole.x, hole.y - rectLength / 2, 0],
29082
29176
  radius: holeRadius,
29083
29177
  height: holeDepth
29084
29178
  }),
29085
- (0, import_primitives6.cylinder)({
29179
+ (0, import_primitives7.cylinder)({
29086
29180
  center: [hole.x, hole.y + rectLength / 2, 0],
29087
29181
  radius: holeRadius,
29088
29182
  height: holeDepth
@@ -29091,15 +29185,15 @@ var BoardGeomBuilder = class {
29091
29185
  }
29092
29186
  if (isRotated) {
29093
29187
  const rotationRadians = hole.ccw_rotation * Math.PI / 180;
29094
- pillHole = (0, import_transforms4.rotateZ)(rotationRadians, pillHole);
29188
+ pillHole = (0, import_transforms5.rotateZ)(rotationRadians, pillHole);
29095
29189
  }
29096
29190
  this.boardGeom = (0, import_booleans3.subtract)(this.boardGeom, pillHole);
29097
29191
  this.padGeoms = this.padGeoms.map(
29098
- (pg) => (0, import_colors4.colorize)(colors.copper, (0, import_booleans3.subtract)(pg, pillHole))
29192
+ (pg) => (0, import_colors5.colorize)(colors.copper, (0, import_booleans3.subtract)(pg, pillHole))
29099
29193
  );
29100
- const copperPill = (0, import_expansions3.expand)({ delta: -copperInset }, pillHole);
29194
+ const copperPill = (0, import_expansions4.expand)({ delta: -copperInset }, pillHole);
29101
29195
  this.platedHoleGeoms = this.platedHoleGeoms.map(
29102
- (phg) => (0, import_colors4.colorize)(colors.copper, (0, import_booleans3.subtract)(phg, copperPill))
29196
+ (phg) => (0, import_colors5.colorize)(colors.copper, (0, import_booleans3.subtract)(phg, copperPill))
29103
29197
  );
29104
29198
  }
29105
29199
  }
@@ -29114,12 +29208,12 @@ var BoardGeomBuilder = class {
29114
29208
  M,
29115
29209
  rectBorderRadius
29116
29210
  );
29117
- const positionedPadGeom = (0, import_transforms4.translate)([pad2.x, pad2.y, zPos], basePadGeom);
29211
+ const positionedPadGeom = (0, import_transforms5.translate)([pad2.x, pad2.y, zPos], basePadGeom);
29118
29212
  let finalPadGeom = positionedPadGeom;
29119
29213
  if (this.boardClipGeom) {
29120
29214
  finalPadGeom = (0, import_booleans3.intersect)(this.boardClipGeom, finalPadGeom);
29121
29215
  }
29122
- finalPadGeom = (0, import_colors4.colorize)(colors.copper, finalPadGeom);
29216
+ finalPadGeom = (0, import_colors5.colorize)(colors.copper, finalPadGeom);
29123
29217
  this.padGeoms.push(finalPadGeom);
29124
29218
  } else if (pad2.shape === "rotated_rect") {
29125
29219
  let basePadGeom = createCenteredRectPadGeom(
@@ -29129,16 +29223,16 @@ var BoardGeomBuilder = class {
29129
29223
  rectBorderRadius
29130
29224
  );
29131
29225
  const rotationRadians = pad2.ccw_rotation * Math.PI / 180;
29132
- basePadGeom = (0, import_transforms4.rotateZ)(rotationRadians, basePadGeom);
29133
- const positionedPadGeom = (0, import_transforms4.translate)([pad2.x, pad2.y, zPos], basePadGeom);
29226
+ basePadGeom = (0, import_transforms5.rotateZ)(rotationRadians, basePadGeom);
29227
+ const positionedPadGeom = (0, import_transforms5.translate)([pad2.x, pad2.y, zPos], basePadGeom);
29134
29228
  let finalPadGeom = positionedPadGeom;
29135
29229
  if (this.boardClipGeom) {
29136
29230
  finalPadGeom = (0, import_booleans3.intersect)(this.boardClipGeom, finalPadGeom);
29137
29231
  }
29138
- finalPadGeom = (0, import_colors4.colorize)(colors.copper, finalPadGeom);
29232
+ finalPadGeom = (0, import_colors5.colorize)(colors.copper, finalPadGeom);
29139
29233
  this.padGeoms.push(finalPadGeom);
29140
29234
  } else if (pad2.shape === "circle") {
29141
- let padGeom = (0, import_primitives6.cylinder)({
29235
+ let padGeom = (0, import_primitives7.cylinder)({
29142
29236
  center: [pad2.x, pad2.y, zPos],
29143
29237
  radius: pad2.radius,
29144
29238
  height: M
@@ -29146,7 +29240,7 @@ var BoardGeomBuilder = class {
29146
29240
  if (this.boardClipGeom) {
29147
29241
  padGeom = (0, import_booleans3.intersect)(this.boardClipGeom, padGeom);
29148
29242
  }
29149
- padGeom = (0, import_colors4.colorize)(colors.copper, padGeom);
29243
+ padGeom = (0, import_colors5.colorize)(colors.copper, padGeom);
29150
29244
  this.padGeoms.push(padGeom);
29151
29245
  }
29152
29246
  }
@@ -29160,14 +29254,14 @@ var BoardGeomBuilder = class {
29160
29254
  if (currentSegmentPoints.length >= 2 && currentLayer) {
29161
29255
  const layerSign = currentLayer === "bottom" ? -1 : 1;
29162
29256
  const zCenter = layerSign * this.ctx.pcbThickness / 2 + layerSign * BOARD_SURFACE_OFFSET.traces;
29163
- const linePath = (0, import_primitives6.line)(currentSegmentPoints);
29164
- const expandedPath = (0, import_expansions3.expand)(
29257
+ const linePath = (0, import_primitives7.line)(currentSegmentPoints);
29258
+ const expandedPath = (0, import_expansions4.expand)(
29165
29259
  { delta: currentWidth / 2, corners: "round" },
29166
29260
  linePath
29167
29261
  );
29168
- let traceGeom = (0, import_transforms4.translate)(
29262
+ let traceGeom = (0, import_transforms5.translate)(
29169
29263
  [0, 0, zCenter - M / 2],
29170
- (0, import_extrusions4.extrudeLinear)({ height: M }, expandedPath)
29264
+ (0, import_extrusions5.extrudeLinear)({ height: M }, expandedPath)
29171
29265
  );
29172
29266
  const startPointCoords = currentSegmentPoints[0];
29173
29267
  const endPointCoords = currentSegmentPoints[currentSegmentPoints.length - 1];
@@ -29176,7 +29270,7 @@ var BoardGeomBuilder = class {
29176
29270
  startPointCoords[1]
29177
29271
  );
29178
29272
  if (startHole) {
29179
- const cuttingCylinder = (0, import_primitives6.cylinder)({
29273
+ const cuttingCylinder = (0, import_primitives7.cylinder)({
29180
29274
  center: [startPointCoords[0], startPointCoords[1], zCenter],
29181
29275
  radius: startHole.diameter / 2 + M,
29182
29276
  height: M
@@ -29185,7 +29279,7 @@ var BoardGeomBuilder = class {
29185
29279
  }
29186
29280
  const endHole = this.getHoleToCut(endPointCoords[0], endPointCoords[1]);
29187
29281
  if (endHole) {
29188
- const cuttingCylinder = (0, import_primitives6.cylinder)({
29282
+ const cuttingCylinder = (0, import_primitives7.cylinder)({
29189
29283
  center: [endPointCoords[0], endPointCoords[1], zCenter],
29190
29284
  radius: endHole.diameter / 2 + M,
29191
29285
  height: M
@@ -29196,7 +29290,7 @@ var BoardGeomBuilder = class {
29196
29290
  if (this.boardClipGeom) {
29197
29291
  traceGeom = (0, import_booleans3.intersect)(this.boardClipGeom, traceGeom);
29198
29292
  }
29199
- traceGeom = (0, import_colors4.colorize)(tracesMaterialColor, traceGeom);
29293
+ traceGeom = (0, import_colors5.colorize)(tracesMaterialColor, traceGeom);
29200
29294
  this.traceGeoms.push(traceGeom);
29201
29295
  }
29202
29296
  currentSegmentPoints = [];
@@ -29263,31 +29357,31 @@ var BoardGeomBuilder = class {
29263
29357
  point2[0] + xOffset + st.anchor_position.x,
29264
29358
  point2[1] + yOffset + st.anchor_position.y
29265
29359
  ]);
29266
- const textPath = (0, import_primitives6.line)(alignedOutline);
29360
+ const textPath = (0, import_primitives7.line)(alignedOutline);
29267
29361
  const fontSize = st.font_size || 0.25;
29268
29362
  const expansionDelta = Math.min(
29269
29363
  Math.max(0.01, fontSize * 0.1),
29270
29364
  fontSize * 0.05
29271
29365
  );
29272
- const expandedPath = (0, import_expansions3.expand)(
29366
+ const expandedPath = (0, import_expansions4.expand)(
29273
29367
  { delta: expansionDelta, corners: "round" },
29274
29368
  textPath
29275
29369
  );
29276
29370
  let textGeom;
29277
29371
  if (st.layer === "bottom") {
29278
- textGeom = (0, import_transforms4.translate)(
29372
+ textGeom = (0, import_transforms5.translate)(
29279
29373
  [0, 0, -this.ctx.pcbThickness / 2 - M],
29280
29374
  // Position above board
29281
- (0, import_extrusions4.extrudeLinear)({ height: 0.012 }, expandedPath)
29375
+ (0, import_extrusions5.extrudeLinear)({ height: 0.012 }, expandedPath)
29282
29376
  );
29283
29377
  } else {
29284
- textGeom = (0, import_transforms4.translate)(
29378
+ textGeom = (0, import_transforms5.translate)(
29285
29379
  [0, 0, this.ctx.pcbThickness / 2 + M],
29286
29380
  // Position above board
29287
- (0, import_extrusions4.extrudeLinear)({ height: 0.012 }, expandedPath)
29381
+ (0, import_extrusions5.extrudeLinear)({ height: 0.012 }, expandedPath)
29288
29382
  );
29289
29383
  }
29290
- textGeom = (0, import_colors4.colorize)([1, 1, 1], textGeom);
29384
+ textGeom = (0, import_colors5.colorize)([1, 1, 1], textGeom);
29291
29385
  this.silkscreenTextGeoms.push(textGeom);
29292
29386
  }
29293
29387
  }
@@ -29297,10 +29391,16 @@ var BoardGeomBuilder = class {
29297
29391
  this.silkscreenPathGeoms.push(pathGeom);
29298
29392
  }
29299
29393
  }
29394
+ processSilkscreenLine(sl) {
29395
+ const lineGeom = createSilkscreenLineGeom(sl, this.ctx);
29396
+ if (lineGeom) {
29397
+ this.silkscreenLineGeoms.push(lineGeom);
29398
+ }
29399
+ }
29300
29400
  finalize() {
29301
29401
  if (!this.boardGeom) return;
29302
29402
  const boardMaterialColor = boardMaterialColors[this.board.material] ?? colors.fr4Green;
29303
- this.boardGeom = (0, import_colors4.colorize)(boardMaterialColor, this.boardGeom);
29403
+ this.boardGeom = (0, import_colors5.colorize)(boardMaterialColor, this.boardGeom);
29304
29404
  this.finalGeoms = [
29305
29405
  this.boardGeom,
29306
29406
  ...this.platedHoleGeoms,
@@ -29309,6 +29409,7 @@ var BoardGeomBuilder = class {
29309
29409
  ...this.viaGeoms,
29310
29410
  ...this.copperPourGeoms,
29311
29411
  ...this.silkscreenTextGeoms,
29412
+ ...this.silkscreenLineGeoms,
29312
29413
  ...this.silkscreenPathGeoms
29313
29414
  ];
29314
29415
  if (this.onCompleteCallback) {
@@ -29825,9 +29926,13 @@ function createSilkscreenTextureForLayer({
29825
29926
  }) {
29826
29927
  const pcbSilkscreenTexts = su6(circuitJson).pcb_silkscreen_text.list();
29827
29928
  const pcbSilkscreenPaths = su6(circuitJson).pcb_silkscreen_path.list();
29929
+ const pcbSilkscreenLines = su6(circuitJson).pcb_silkscreen_line.list();
29828
29930
  const textsOnLayer = pcbSilkscreenTexts.filter((t) => t.layer === layer);
29829
29931
  const pathsOnLayer = pcbSilkscreenPaths.filter((p) => p.layer === layer);
29830
- if (textsOnLayer.length === 0 && pathsOnLayer.length === 0) return null;
29932
+ const linesOnLayer = pcbSilkscreenLines.filter((l) => l.layer === layer);
29933
+ if (textsOnLayer.length === 0 && pathsOnLayer.length === 0 && linesOnLayer.length === 0) {
29934
+ return null;
29935
+ }
29831
29936
  const canvas = document.createElement("canvas");
29832
29937
  const canvasWidth = Math.floor(boardData.width * traceTextureResolution);
29833
29938
  const canvasHeight = Math.floor(boardData.height * traceTextureResolution);
@@ -29841,15 +29946,30 @@ function createSilkscreenTextureForLayer({
29841
29946
  }
29842
29947
  ctx.strokeStyle = silkscreenColor;
29843
29948
  ctx.fillStyle = silkscreenColor;
29949
+ const canvasXFromPcb = (pcbX) => (pcbX - boardData.center.x + boardData.width / 2) * traceTextureResolution;
29950
+ const canvasYFromPcb = (pcbY) => (-(pcbY - boardData.center.y) + boardData.height / 2) * traceTextureResolution;
29951
+ linesOnLayer.forEach((lineEl) => {
29952
+ const startXmm = parseDimensionToMm(lineEl.x1) ?? 0;
29953
+ const startYmm = parseDimensionToMm(lineEl.y1) ?? 0;
29954
+ const endXmm = parseDimensionToMm(lineEl.x2) ?? 0;
29955
+ const endYmm = parseDimensionToMm(lineEl.y2) ?? 0;
29956
+ if (startXmm === endXmm && startYmm === endYmm) return;
29957
+ ctx.beginPath();
29958
+ ctx.lineWidth = coerceDimensionToMm(lineEl.stroke_width, 0.1) * traceTextureResolution;
29959
+ ctx.lineCap = "round";
29960
+ ctx.moveTo(canvasXFromPcb(startXmm), canvasYFromPcb(startYmm));
29961
+ ctx.lineTo(canvasXFromPcb(endXmm), canvasYFromPcb(endYmm));
29962
+ ctx.stroke();
29963
+ });
29844
29964
  pathsOnLayer.forEach((path) => {
29845
29965
  if (path.route.length < 2) return;
29846
29966
  ctx.beginPath();
29847
- ctx.lineWidth = (path.stroke_width || 0.1) * traceTextureResolution;
29967
+ ctx.lineWidth = coerceDimensionToMm(path.stroke_width, 0.1) * traceTextureResolution;
29848
29968
  ctx.lineCap = "round";
29849
29969
  ctx.lineJoin = "round";
29850
29970
  path.route.forEach((point2, index2) => {
29851
- const canvasX = (point2.x - boardData.center.x + boardData.width / 2) * traceTextureResolution;
29852
- const canvasY = (-(point2.y - boardData.center.y) + boardData.height / 2) * traceTextureResolution;
29971
+ const canvasX = canvasXFromPcb(parseDimensionToMm(point2.x) ?? 0);
29972
+ const canvasY = canvasYFromPcb(parseDimensionToMm(point2.y) ?? 0);
29853
29973
  if (index2 === 0) ctx.moveTo(canvasX, canvasY);
29854
29974
  else ctx.lineTo(canvasX, canvasY);
29855
29975
  });
@@ -29935,8 +30055,8 @@ function createSilkscreenTextureForLayer({
29935
30055
  }
29936
30056
  const pcbX = transformedP.x + xOff + textS.anchor_position.x;
29937
30057
  const pcbY = transformedP.y + yOff + textS.anchor_position.y;
29938
- const canvasX = (pcbX - boardData.center.x + boardData.width / 2) * traceTextureResolution;
29939
- const canvasY = (-(pcbY - boardData.center.y) + boardData.height / 2) * traceTextureResolution;
30058
+ const canvasX = canvasXFromPcb(pcbX);
30059
+ const canvasY = canvasYFromPcb(pcbY);
29940
30060
  if (index2 === 0) ctx.moveTo(canvasX, canvasY);
29941
30061
  else ctx.lineTo(canvasX, canvasY);
29942
30062
  });
@@ -37513,6 +37633,7 @@ var ContextMenu = ({
37513
37633
  {
37514
37634
  style: {
37515
37635
  ...itemStyles2,
37636
+ ...itemPaddingStyles2,
37516
37637
  backgroundColor: hoveredItem === "autorotate" ? "#404040" : "transparent"
37517
37638
  },
37518
37639
  onSelect: (e) => e.preventDefault(),
@@ -37623,8 +37744,14 @@ import { jsx as jsx34, jsxs as jsxs10 } from "react/jsx-runtime";
37623
37744
  var CadViewerInner = (props) => {
37624
37745
  const [engine, setEngine] = useState33("manifold");
37625
37746
  const containerRef = useRef22(null);
37626
- const [autoRotate, setAutoRotate] = useState33(true);
37627
- const [autoRotateUserToggled, setAutoRotateUserToggled] = useState33(false);
37747
+ const [autoRotate, setAutoRotate] = useState33(() => {
37748
+ const stored = window.localStorage.getItem("cadViewerAutoRotate");
37749
+ return stored === "false" ? false : true;
37750
+ });
37751
+ const [autoRotateUserToggled, setAutoRotateUserToggled] = useState33(() => {
37752
+ const stored = window.localStorage.getItem("cadViewerAutoRotateUserToggled");
37753
+ return stored === "true";
37754
+ });
37628
37755
  const [cameraPreset, setCameraPreset] = useState33("Custom");
37629
37756
  const { visibility, toggleLayer } = useLayerVisibility();
37630
37757
  const cameraControllerRef = useRef22(null);
@@ -37680,6 +37807,15 @@ var CadViewerInner = (props) => {
37680
37807
  useEffect39(() => {
37681
37808
  window.localStorage.setItem("cadViewerEngine", engine);
37682
37809
  }, [engine]);
37810
+ useEffect39(() => {
37811
+ window.localStorage.setItem("cadViewerAutoRotate", String(autoRotate));
37812
+ }, [autoRotate]);
37813
+ useEffect39(() => {
37814
+ window.localStorage.setItem(
37815
+ "cadViewerAutoRotateUserToggled",
37816
+ String(autoRotateUserToggled)
37817
+ );
37818
+ }, [autoRotateUserToggled]);
37683
37819
  const viewerKey = props.circuitJson ? JSON.stringify(props.circuitJson) : void 0;
37684
37820
  return /* @__PURE__ */ jsxs10(
37685
37821
  "div",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/3d-viewer",
3
- "version": "0.0.421",
3
+ "version": "0.0.423",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "type": "module",
@@ -71,7 +71,7 @@
71
71
  "react-use-gesture": "^9.1.3",
72
72
  "semver": "^7.7.0",
73
73
  "strip-ansi": "^7.1.0",
74
- "tscircuit": "^0.0.746",
74
+ "tscircuit": "^0.0.834",
75
75
  "tsup": "^8.3.6",
76
76
  "typescript": "^5.7.3",
77
77
  "vite": "^7.1.5",