@tscircuit/pcb-viewer 1.11.351 → 1.11.353

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -18,6 +18,7 @@ interface State {
18
18
  is_showing_multiple_traces_length: boolean;
19
19
  is_showing_rats_nest: boolean;
20
20
  is_showing_copper_pours: boolean;
21
+ is_showing_courtyards: boolean;
21
22
  is_showing_pcb_groups: boolean;
22
23
  is_showing_group_anchor_offsets: boolean;
23
24
  is_showing_solder_mask: boolean;
@@ -34,6 +35,7 @@ interface State {
34
35
  setIsShowingMultipleTracesLength: (is_showing: boolean) => void;
35
36
  setIsShowingDrcErrors: (is_showing: boolean) => void;
36
37
  setIsShowingCopperPours: (is_showing: boolean) => void;
38
+ setIsShowingCourtyards: (is_showing: boolean) => void;
37
39
  setIsShowingPcbGroups: (is_showing: boolean) => void;
38
40
  setIsShowingGroupAnchorOffsets: (is_showing: boolean) => void;
39
41
  setIsShowingSolderMask: (is_showing: boolean) => void;
package/dist/index.js CHANGED
@@ -5572,6 +5572,34 @@ var cju = (circuitJsonInput, options = {}) => {
5572
5572
  if (prop === "subtree") {
5573
5573
  return (opts) => cju(buildSubtree(circuitJson, opts), options);
5574
5574
  }
5575
+ if (prop === "insert") {
5576
+ return (elm) => {
5577
+ const component_type2 = elm.type;
5578
+ if (!component_type2) {
5579
+ throw new Error("insert requires an element with a type");
5580
+ }
5581
+ internalStore.counts[component_type2] ??= -1;
5582
+ internalStore.counts[component_type2]++;
5583
+ const index = internalStore.counts[component_type2];
5584
+ const newElm = {
5585
+ ...elm,
5586
+ type: component_type2,
5587
+ [`${component_type2}_id`]: `${component_type2}_${index}`
5588
+ };
5589
+ if (options.validateInserts) {
5590
+ const parser = Soup[component_type2] ?? Soup.any_soup_element;
5591
+ parser.parse(newElm);
5592
+ }
5593
+ circuitJson.push(newElm);
5594
+ internalStore.editCount++;
5595
+ return newElm;
5596
+ };
5597
+ }
5598
+ if (prop === "insertAll") {
5599
+ return (elms) => {
5600
+ return elms.map((elm) => su2.insert(elm));
5601
+ };
5602
+ }
5575
5603
  const component_type = prop;
5576
5604
  return {
5577
5605
  get: (id) => circuitJson.find(
@@ -6199,6 +6227,43 @@ var getElementId = (elm) => {
6199
6227
  const id = elm[`${type}_id`];
6200
6228
  return id;
6201
6229
  };
6230
+ var mergeBounds = (currentBounds, nextBounds) => ({
6231
+ minX: Math.min(currentBounds.minX, nextBounds.minX),
6232
+ minY: Math.min(currentBounds.minY, nextBounds.minY),
6233
+ maxX: Math.max(currentBounds.maxX, nextBounds.maxX),
6234
+ maxY: Math.max(currentBounds.maxY, nextBounds.maxY)
6235
+ });
6236
+ var getCircleBounds = (x, y, diameter) => {
6237
+ const radius = diameter / 2;
6238
+ return {
6239
+ minX: x - radius,
6240
+ minY: y - radius,
6241
+ maxX: x + radius,
6242
+ maxY: y + radius
6243
+ };
6244
+ };
6245
+ var getRotatedRectBounds = (x, y, width, height, rotationDegrees) => {
6246
+ const halfWidth = width / 2;
6247
+ const halfHeight = height / 2;
6248
+ const theta = rotationDegrees * Math.PI / 180;
6249
+ const cosTheta = Math.cos(theta);
6250
+ const sinTheta = Math.sin(theta);
6251
+ const corners = [
6252
+ { x: -halfWidth, y: -halfHeight },
6253
+ { x: halfWidth, y: -halfHeight },
6254
+ { x: halfWidth, y: halfHeight },
6255
+ { x: -halfWidth, y: halfHeight }
6256
+ ].map((corner) => ({
6257
+ x: x + corner.x * cosTheta - corner.y * sinTheta,
6258
+ y: y + corner.x * sinTheta + corner.y * cosTheta
6259
+ }));
6260
+ return {
6261
+ minX: Math.min(...corners.map((corner) => corner.x)),
6262
+ minY: Math.min(...corners.map((corner) => corner.y)),
6263
+ maxX: Math.max(...corners.map((corner) => corner.x)),
6264
+ maxY: Math.max(...corners.map((corner) => corner.y))
6265
+ };
6266
+ };
6202
6267
  var getBoundsOfPcbElements = (elements) => {
6203
6268
  let minX = Number.POSITIVE_INFINITY;
6204
6269
  let minY = Number.POSITIVE_INFINITY;
@@ -6215,6 +6280,47 @@ var getBoundsOfPcbElements = (elements) => {
6215
6280
  }
6216
6281
  continue;
6217
6282
  }
6283
+ if (elm.type === "pcb_hole" && elm.hole_shape === "circle") {
6284
+ const holeBounds = getCircleBounds(elm.x, elm.y, elm.hole_diameter);
6285
+ minX = Math.min(minX, holeBounds.minX);
6286
+ minY = Math.min(minY, holeBounds.minY);
6287
+ maxX = Math.max(maxX, holeBounds.maxX);
6288
+ maxY = Math.max(maxY, holeBounds.maxY);
6289
+ continue;
6290
+ }
6291
+ if (elm.type === "pcb_plated_hole") {
6292
+ let platedHoleBounds;
6293
+ if ("outer_diameter" in elm && typeof elm.outer_diameter === "number") {
6294
+ platedHoleBounds = getCircleBounds(elm.x, elm.y, elm.outer_diameter);
6295
+ } else if ("hole_diameter" in elm && typeof elm.hole_diameter === "number") {
6296
+ platedHoleBounds = getCircleBounds(elm.x, elm.y, elm.hole_diameter);
6297
+ }
6298
+ if ("rect_pad_width" in elm && typeof elm.rect_pad_width === "number" && "rect_pad_height" in elm && typeof elm.rect_pad_height === "number") {
6299
+ const rectBounds = getRotatedRectBounds(
6300
+ elm.x,
6301
+ elm.y,
6302
+ elm.rect_pad_width,
6303
+ elm.rect_pad_height,
6304
+ "rect_ccw_rotation" in elm ? elm.rect_ccw_rotation ?? 0 : 0
6305
+ );
6306
+ platedHoleBounds = platedHoleBounds ? mergeBounds(platedHoleBounds, rectBounds) : rectBounds;
6307
+ }
6308
+ if ("hole_diameter" in elm && typeof elm.hole_diameter === "number") {
6309
+ const drillBounds = getCircleBounds(
6310
+ elm.x + ("hole_offset_x" in elm ? elm.hole_offset_x ?? 0 : 0),
6311
+ elm.y + ("hole_offset_y" in elm ? elm.hole_offset_y ?? 0 : 0),
6312
+ elm.hole_diameter
6313
+ );
6314
+ platedHoleBounds = platedHoleBounds ? mergeBounds(platedHoleBounds, drillBounds) : drillBounds;
6315
+ }
6316
+ if (platedHoleBounds) {
6317
+ minX = Math.min(minX, platedHoleBounds.minX);
6318
+ minY = Math.min(minY, platedHoleBounds.minY);
6319
+ maxX = Math.max(maxX, platedHoleBounds.maxX);
6320
+ maxY = Math.max(maxY, platedHoleBounds.maxY);
6321
+ continue;
6322
+ }
6323
+ }
6218
6324
  let centerX;
6219
6325
  let centerY;
6220
6326
  let width;
@@ -6261,6 +6367,20 @@ var getBoundsOfPcbElements = (elements) => {
6261
6367
  maxX = Math.max(maxX, point.x);
6262
6368
  maxY = Math.max(maxY, point.y);
6263
6369
  }
6370
+ } else if (elm.type === "pcb_courtyard_outline") {
6371
+ for (const point of elm.outline) {
6372
+ minX = Math.min(minX, point.x);
6373
+ minY = Math.min(minY, point.y);
6374
+ maxX = Math.max(maxX, point.x);
6375
+ maxY = Math.max(maxY, point.y);
6376
+ }
6377
+ } else if (elm.type === "pcb_courtyard_polygon") {
6378
+ for (const point of elm.points) {
6379
+ minX = Math.min(minX, point.x);
6380
+ minY = Math.min(minY, point.y);
6381
+ maxX = Math.max(maxX, point.x);
6382
+ maxY = Math.max(maxY, point.y);
6383
+ }
6264
6384
  }
6265
6385
  }
6266
6386
  return { minX, minY, maxX, maxY };
@@ -6474,6 +6594,7 @@ var STORAGE_KEYS = {
6474
6594
  IS_SHOWING_PCB_GROUPS: "pcb_viewer_is_showing_pcb_groups",
6475
6595
  PCB_GROUP_VIEW_MODE: "pcb_viewer_group_view_mode",
6476
6596
  IS_SHOWING_COPPER_POURS: "pcb_viewer_is_showing_copper_pours",
6597
+ IS_SHOWING_COURTYARDS: "pcb_viewer_is_showing_courtyards",
6477
6598
  IS_SHOWING_GROUP_ANCHOR_OFFSETS: "pcb_viewer_is_showing_group_anchor_offsets",
6478
6599
  IS_SHOWING_SOLDER_MASK: "pcb_viewer_is_showing_solder_mask",
6479
6600
  IS_SHOWING_FABRICATION_NOTES: "pcb_viewer_is_showing_fabrication_notes"
@@ -6531,6 +6652,10 @@ var createStore = (initialState = {}, disablePcbGroups = false) => createZustand
6531
6652
  STORAGE_KEYS.IS_SHOWING_COPPER_POURS,
6532
6653
  true
6533
6654
  ),
6655
+ is_showing_courtyards: getStoredBoolean(
6656
+ STORAGE_KEYS.IS_SHOWING_COURTYARDS,
6657
+ true
6658
+ ),
6534
6659
  is_showing_pcb_groups: disablePcbGroups ? false : getStoredBoolean(STORAGE_KEYS.IS_SHOWING_PCB_GROUPS, true),
6535
6660
  is_showing_group_anchor_offsets: getStoredBoolean(
6536
6661
  STORAGE_KEYS.IS_SHOWING_GROUP_ANCHOR_OFFSETS,
@@ -6569,6 +6694,10 @@ var createStore = (initialState = {}, disablePcbGroups = false) => createZustand
6569
6694
  setStoredBoolean(STORAGE_KEYS.IS_SHOWING_COPPER_POURS, is_showing);
6570
6695
  set({ is_showing_copper_pours: is_showing });
6571
6696
  },
6697
+ setIsShowingCourtyards: (is_showing) => {
6698
+ setStoredBoolean(STORAGE_KEYS.IS_SHOWING_COURTYARDS, is_showing);
6699
+ set({ is_showing_courtyards: is_showing });
6700
+ },
6572
6701
  setIsShowingPcbGroups: (is_showing) => {
6573
6702
  if (disablePcbGroups) return;
6574
6703
  setStoredBoolean(STORAGE_KEYS.IS_SHOWING_PCB_GROUPS, is_showing);
@@ -9897,6 +10026,9 @@ var CanvasPrimitiveRenderer = ({
9897
10026
  const isShowingFabricationNotes = useGlobalStore(
9898
10027
  (s) => s.is_showing_fabrication_notes
9899
10028
  );
10029
+ const isShowingCourtyards = useGlobalStore(
10030
+ (s) => s.is_showing_courtyards
10031
+ );
9900
10032
  useEffect5(() => {
9901
10033
  if (!canvasRefs.current) return;
9902
10034
  if (Object.keys(canvasRefs.current).length === 0) return;
@@ -10121,23 +10253,25 @@ var CanvasPrimitiveRenderer = ({
10121
10253
  realToCanvasMat: transform
10122
10254
  });
10123
10255
  }
10124
- const topCourtyardCanvas = canvasRefs.current.top_courtyard;
10125
- if (topCourtyardCanvas) {
10126
- drawCourtyardElementsForLayer({
10127
- canvas: topCourtyardCanvas,
10128
- elements,
10129
- layers: ["top_courtyard"],
10130
- realToCanvasMat: transform
10131
- });
10132
- }
10133
- const bottomCourtyardCanvas = canvasRefs.current.bottom_courtyard;
10134
- if (bottomCourtyardCanvas) {
10135
- drawCourtyardElementsForLayer({
10136
- canvas: bottomCourtyardCanvas,
10137
- elements,
10138
- layers: ["bottom_courtyard"],
10139
- realToCanvasMat: transform
10140
- });
10256
+ if (isShowingCourtyards) {
10257
+ const topCourtyardCanvas = canvasRefs.current.top_courtyard;
10258
+ if (topCourtyardCanvas) {
10259
+ drawCourtyardElementsForLayer({
10260
+ canvas: topCourtyardCanvas,
10261
+ elements,
10262
+ layers: ["top_courtyard"],
10263
+ realToCanvasMat: transform
10264
+ });
10265
+ }
10266
+ const bottomCourtyardCanvas = canvasRefs.current.bottom_courtyard;
10267
+ if (bottomCourtyardCanvas) {
10268
+ drawCourtyardElementsForLayer({
10269
+ canvas: bottomCourtyardCanvas,
10270
+ elements,
10271
+ layers: ["bottom_courtyard"],
10272
+ realToCanvasMat: transform
10273
+ });
10274
+ }
10141
10275
  }
10142
10276
  const boardCanvas = canvasRefs.current.board;
10143
10277
  if (boardCanvas) {
@@ -10186,7 +10320,8 @@ var CanvasPrimitiveRenderer = ({
10186
10320
  transform,
10187
10321
  selectedLayer,
10188
10322
  isShowingSolderMask,
10189
- isShowingFabricationNotes
10323
+ isShowingFabricationNotes,
10324
+ isShowingCourtyards
10190
10325
  ]);
10191
10326
  return /* @__PURE__ */ jsxs(
10192
10327
  "div",
@@ -14226,7 +14361,7 @@ import { css as css3 } from "@emotion/css";
14226
14361
  // package.json
14227
14362
  var package_default = {
14228
14363
  name: "@tscircuit/pcb-viewer",
14229
- version: "1.11.350",
14364
+ version: "1.11.352",
14230
14365
  main: "dist/index.js",
14231
14366
  type: "module",
14232
14367
  repository: "tscircuit/pcb-viewer",
@@ -14250,7 +14385,7 @@ var package_default = {
14250
14385
  "@semantic-release/npm": "^9.0.1",
14251
14386
  "@semantic-release/release-notes-generator": "^10.0.3",
14252
14387
  "@swc/core": "^1.4.12",
14253
- "@tscircuit/circuit-json-util": "^0.0.78",
14388
+ "@tscircuit/circuit-json-util": "^0.0.90",
14254
14389
  "@tscircuit/eagle-xml-converter": "^1.0.0",
14255
14390
  "@types/bun": "latest",
14256
14391
  "@types/color": "^3.0.6",
@@ -14263,7 +14398,7 @@ var package_default = {
14263
14398
  "react-cosmos-plugin-vite": "7.0.0-beta.0",
14264
14399
  "react-dom": "19.1.0",
14265
14400
  "react-use": "^17.4.0",
14266
- tscircuit: "^0.0.1421",
14401
+ tscircuit: "^0.0.1517",
14267
14402
  tsup: "^8.0.2",
14268
14403
  "type-fest": "^3.0.0",
14269
14404
  typescript: "^5.4.4",
@@ -14279,9 +14414,9 @@ var package_default = {
14279
14414
  "@tscircuit/alphabet": "^0.0.22",
14280
14415
  "@tscircuit/math-utils": "^0.0.29",
14281
14416
  "@vitejs/plugin-react": "^5.0.2",
14282
- "circuit-json": "^0.0.387",
14283
- "circuit-to-canvas": "^0.0.92",
14284
- "circuit-to-svg": "^0.0.323",
14417
+ "circuit-json": "^0.0.403",
14418
+ "circuit-to-canvas": "^0.0.93",
14419
+ "circuit-to-svg": "^0.0.337",
14285
14420
  color: "^4.2.3",
14286
14421
  "react-supergrid": "^1.0.10",
14287
14422
  "react-toastify": "^10.0.5",
@@ -14560,6 +14695,7 @@ var ToolbarOverlay = ({ children, elements }) => {
14560
14695
  setIsShowingAutorouting,
14561
14696
  setIsShowingDrcErrors,
14562
14697
  setIsShowingCopperPours,
14698
+ setIsShowingCourtyards,
14563
14699
  setIsShowingPcbGroups,
14564
14700
  setIsShowingGroupAnchorOffsets,
14565
14701
  setIsShowingSolderMask,
@@ -14581,6 +14717,7 @@ var ToolbarOverlay = ({ children, elements }) => {
14581
14717
  is_showing_autorouting: s.is_showing_autorouting,
14582
14718
  is_showing_drc_errors: s.is_showing_drc_errors,
14583
14719
  is_showing_copper_pours: s.is_showing_copper_pours,
14720
+ is_showing_courtyards: s.is_showing_courtyards,
14584
14721
  is_showing_pcb_groups: s.is_showing_pcb_groups,
14585
14722
  is_showing_group_anchor_offsets: s.is_showing_group_anchor_offsets,
14586
14723
  is_showing_solder_mask: s.is_showing_solder_mask,
@@ -14593,6 +14730,7 @@ var ToolbarOverlay = ({ children, elements }) => {
14593
14730
  setIsShowingAutorouting: s.setIsShowingAutorouting,
14594
14731
  setIsShowingDrcErrors: s.setIsShowingDrcErrors,
14595
14732
  setIsShowingCopperPours: s.setIsShowingCopperPours,
14733
+ setIsShowingCourtyards: s.setIsShowingCourtyards,
14596
14734
  setIsShowingPcbGroups: s.setIsShowingPcbGroups,
14597
14735
  setIsShowingGroupAnchorOffsets: s.setIsShowingGroupAnchorOffsets,
14598
14736
  setIsShowingSolderMask: s.setIsShowingSolderMask,
@@ -15140,6 +15278,16 @@ var ToolbarOverlay = ({ children, elements }) => {
15140
15278
  }
15141
15279
  }
15142
15280
  ),
15281
+ /* @__PURE__ */ jsx20(
15282
+ CheckboxMenuItem,
15283
+ {
15284
+ label: "Show Courtyards",
15285
+ checked: viewSettings.is_showing_courtyards,
15286
+ onClick: () => {
15287
+ setIsShowingCourtyards(!viewSettings.is_showing_courtyards);
15288
+ }
15289
+ }
15290
+ ),
15143
15291
  /* @__PURE__ */ jsx20(
15144
15292
  CheckboxMenuItem,
15145
15293
  {