@tscircuit/pcb-viewer 1.11.413 → 1.11.414

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
@@ -948,9 +948,6 @@ import { createContext, useContext } from "react";
948
948
  var RenderingEngineContext = createContext(null);
949
949
  var useRenderingEngine = () => useContext(RenderingEngineContext);
950
950
 
951
- // src/PCBViewer.tsx
952
- import { applyEditEvents } from "@tscircuit/core";
953
-
954
951
  // node_modules/@tscircuit/circuit-json-util/dist/index.js
955
952
  import * as Soup from "circuit-json";
956
953
  import * as Soup2 from "circuit-json";
@@ -8993,6 +8990,158 @@ var cjuIndexed = (soup, options = {}) => {
8993
8990
  return suIndexed;
8994
8991
  };
8995
8992
  cjuIndexed.unparsed = cjuIndexed;
8993
+ var getQuarterTurns = (angleRadians) => Math.round(angleRadians / (Math.PI / 2));
8994
+ var insertionDirectionToVec = (direction) => {
8995
+ switch (direction) {
8996
+ case "from_left":
8997
+ return { x: -1, y: 0 };
8998
+ case "from_right":
8999
+ return { x: 1, y: 0 };
9000
+ case "from_top":
9001
+ return { x: 0, y: 1 };
9002
+ case "from_bottom":
9003
+ return { x: 0, y: -1 };
9004
+ }
9005
+ };
9006
+ var vecToInsertionDirection = ({
9007
+ x,
9008
+ y
9009
+ }) => {
9010
+ if (x > 0) return "from_right";
9011
+ if (x < 0) return "from_left";
9012
+ if (y > 0) return "from_top";
9013
+ return "from_bottom";
9014
+ };
9015
+ var transformInsertionDirection = (direction, opts) => {
9016
+ if (!direction) return direction;
9017
+ if (direction === "from_above" || direction === "from_below") {
9018
+ if (!opts.isFlipped) return direction;
9019
+ return direction === "from_above" ? "from_below" : "from_above";
9020
+ }
9021
+ let { x, y } = insertionDirectionToVec(direction);
9022
+ let quarterTurns = Math.round(opts.rotationDegrees / 90);
9023
+ while (quarterTurns > 0) {
9024
+ ;
9025
+ [x, y] = [-y, x];
9026
+ quarterTurns--;
9027
+ }
9028
+ while (quarterTurns < 0) {
9029
+ ;
9030
+ [x, y] = [y, -x];
9031
+ quarterTurns++;
9032
+ }
9033
+ if (opts.isFlipped) {
9034
+ y = -y;
9035
+ }
9036
+ return vecToInsertionDirection({ x, y });
9037
+ };
9038
+ var transformPCBElement = (elm, matrix2) => {
9039
+ const tsr = decomposeTSR(matrix2);
9040
+ const flipPadWidthHeight = Math.abs(getQuarterTurns(tsr.rotation.angle)) % 2 === 1;
9041
+ const rotationDegrees = tsr.rotation.angle / Math.PI * 180;
9042
+ const isFlipped = tsr.scale.sy < 0;
9043
+ if (elm.type === "pcb_plated_hole" || elm.type === "pcb_hole" || elm.type === "pcb_via" || elm.type === "pcb_smtpad" || elm.type === "pcb_solder_paste" || elm.type === "pcb_port") {
9044
+ const { x, y } = applyToPoint(matrix2, {
9045
+ x: Number(elm.x),
9046
+ y: Number(elm.y)
9047
+ });
9048
+ elm.x = x;
9049
+ elm.y = y;
9050
+ if (elm.type === "pcb_smtpad" && elm.shape === "polygon" && Array.isArray(elm.points)) {
9051
+ elm.points = elm.points.map((point2) => {
9052
+ const tp = applyToPoint(matrix2, { x: point2.x, y: point2.y });
9053
+ return {
9054
+ x: tp.x,
9055
+ y: tp.y
9056
+ };
9057
+ });
9058
+ }
9059
+ } else if (elm.type === "pcb_keepout" || elm.type === "pcb_board") {
9060
+ elm.center = applyToPoint(matrix2, elm.center);
9061
+ } else if (elm.type === "pcb_silkscreen_text" || elm.type === "pcb_fabrication_note_text" || elm.type === "pcb_note_text") {
9062
+ elm.anchor_position = applyToPoint(matrix2, elm.anchor_position);
9063
+ } else if (elm.type === "pcb_copper_text") {
9064
+ if (elm.anchor_position) {
9065
+ elm.anchor_position = applyToPoint(matrix2, elm.anchor_position);
9066
+ }
9067
+ } else if (elm.type === "pcb_courtyard_rect") {
9068
+ elm.center = applyToPoint(matrix2, elm.center);
9069
+ elm.ccw_rotation = ((elm.ccw_rotation ?? 0) + rotationDegrees) % 360;
9070
+ } else if (elm.type === "pcb_silkscreen_circle" || elm.type === "pcb_silkscreen_rect" || elm.type === "pcb_silkscreen_pill" || elm.type === "pcb_silkscreen_oval" || elm.type === "pcb_note_rect" || elm.type === "pcb_courtyard_circle") {
9071
+ elm.center = applyToPoint(matrix2, elm.center);
9072
+ } else if (elm.type === "pcb_component") {
9073
+ elm.center = applyToPoint(matrix2, elm.center);
9074
+ elm.rotation = elm.rotation + rotationDegrees;
9075
+ elm.rotation = elm.rotation % 360;
9076
+ if (elm.cable_insertion_center) {
9077
+ elm.cable_insertion_center = applyToPoint(
9078
+ matrix2,
9079
+ elm.cable_insertion_center
9080
+ );
9081
+ }
9082
+ elm.insertion_direction = transformInsertionDirection(
9083
+ elm.insertion_direction,
9084
+ {
9085
+ rotationDegrees,
9086
+ isFlipped
9087
+ }
9088
+ );
9089
+ if (flipPadWidthHeight) {
9090
+ ;
9091
+ [elm.width, elm.height] = [elm.height, elm.width];
9092
+ }
9093
+ } else if (elm.type === "pcb_courtyard_outline") {
9094
+ elm.outline = elm.outline.map((p) => {
9095
+ const tp = applyToPoint(matrix2, p);
9096
+ p.x = tp.x;
9097
+ p.y = tp.y;
9098
+ return p;
9099
+ });
9100
+ } else if (elm.type === "pcb_courtyard_polygon") {
9101
+ elm.points = elm.points.map((p) => {
9102
+ const tp = applyToPoint(matrix2, p);
9103
+ p.x = tp.x;
9104
+ p.y = tp.y;
9105
+ return p;
9106
+ });
9107
+ } else if (elm.type === "pcb_trace") {
9108
+ elm.route = elm.route.map((rp) => {
9109
+ if (!("x" in rp)) {
9110
+ rp.start = applyToPoint(matrix2, rp.start);
9111
+ rp.end = applyToPoint(matrix2, rp.end);
9112
+ return rp;
9113
+ }
9114
+ const tp = applyToPoint(matrix2, rp);
9115
+ rp.x = tp.x;
9116
+ rp.y = tp.y;
9117
+ return rp;
9118
+ });
9119
+ } else if (elm.type === "pcb_silkscreen_path" || elm.type === "pcb_trace_hint" || elm.type === "pcb_fabrication_note_path" || elm.type === "pcb_note_path") {
9120
+ elm.route = elm.route.map((rp) => {
9121
+ const tp = applyToPoint(matrix2, rp);
9122
+ rp.x = tp.x;
9123
+ rp.y = tp.y;
9124
+ return rp;
9125
+ });
9126
+ } else if (elm.type === "pcb_silkscreen_line" || elm.type === "pcb_note_line") {
9127
+ const p1 = { x: elm.x1, y: elm.y1 };
9128
+ const p2 = { x: elm.x2, y: elm.y2 };
9129
+ const p1t = applyToPoint(matrix2, p1);
9130
+ const p2t = applyToPoint(matrix2, p2);
9131
+ elm.x1 = p1t.x;
9132
+ elm.y1 = p1t.y;
9133
+ elm.x2 = p2t.x;
9134
+ elm.y2 = p2t.y;
9135
+ } else if (elm.type === "cad_component") {
9136
+ const newPos = applyToPoint(matrix2, {
9137
+ x: elm.position.x,
9138
+ y: elm.position.y
9139
+ });
9140
+ elm.position.x = newPos.x;
9141
+ elm.position.y = newPos.y;
9142
+ }
9143
+ return elm;
9144
+ };
8996
9145
  var getElementId = (elm) => {
8997
9146
  const type = elm.type;
8998
9147
  const id = elm[`${type}_id`];
@@ -9806,7 +9955,7 @@ var useMeasure_default = isBrowser && typeof window.ResizeObserver !== "undefine
9806
9955
  };
9807
9956
 
9808
9957
  // src/PCBViewer.tsx
9809
- import { compose as compose9, scale as scale6, translate as translate13 } from "transformation-matrix";
9958
+ import { compose as compose9, scale as scale6, translate as translate14 } from "transformation-matrix";
9810
9959
 
9811
9960
  // node_modules/use-mouse-matrix-transform/dist/chunk-TGYMZPTI.js
9812
9961
  import { compose as compose2, translate as translate6, scale } from "transformation-matrix";
@@ -18369,7 +18518,7 @@ import { css as css3 } from "@emotion/css";
18369
18518
  // package.json
18370
18519
  var package_default = {
18371
18520
  name: "@tscircuit/pcb-viewer",
18372
- version: "1.11.412",
18521
+ version: "1.11.413",
18373
18522
  main: "dist/index.js",
18374
18523
  type: "module",
18375
18524
  repository: {
@@ -18401,6 +18550,7 @@ var package_default = {
18401
18550
  "@swc/core": "^1.4.12",
18402
18551
  "@tscircuit/circuit-json-util": "^0.0.116",
18403
18552
  "@tscircuit/circuit-json-webgpu": "github:tscircuit/circuit-json-webgpu#6c1414c7464a743190747c99bb8ec504f2ecf646",
18553
+ "@tscircuit/core": "^0.0.1701",
18404
18554
  "@tscircuit/eagle-xml-converter": "^1.0.0",
18405
18555
  "@types/bun": "latest",
18406
18556
  "@types/color": "^3.0.6",
@@ -18427,8 +18577,7 @@ var package_default = {
18427
18577
  },
18428
18578
  peerDependencies: {
18429
18579
  react: "*",
18430
- "react-dom": "*",
18431
- tscircuit: "*"
18580
+ "react-dom": "*"
18432
18581
  },
18433
18582
  dependencies: {
18434
18583
  "@emotion/css": "^11.11.2",
@@ -20647,9 +20796,65 @@ var calculateBoardSizeKey = (circuitJson) => {
20647
20796
  return `${round(board.width)}_${round(board.height)}`;
20648
20797
  };
20649
20798
 
20799
+ // src/lib/apply-edit-events.ts
20800
+ import { translate as translate13 } from "transformation-matrix";
20801
+ function applyEditEvents({
20802
+ circuitJson,
20803
+ editEvents
20804
+ }) {
20805
+ let editedCircuitJson = structuredClone(circuitJson);
20806
+ for (const editEvent of editEvents) {
20807
+ if (editEvent.edit_event_type === "edit_pcb_component_location") {
20808
+ const pcbComponent = su(editedCircuitJson).pcb_component.get(
20809
+ editEvent.pcb_component_id
20810
+ );
20811
+ const isAlreadyAtEditedCenter = pcbComponent?.center.x === editEvent.new_center.x && pcbComponent.center.y === editEvent.new_center.y;
20812
+ if (isAlreadyAtEditedCenter) continue;
20813
+ const pcbToEditedPcbTransform = translate13(
20814
+ editEvent.new_center.x - editEvent.original_center.x,
20815
+ editEvent.new_center.y - editEvent.original_center.y
20816
+ );
20817
+ editedCircuitJson = editedCircuitJson.map(
20818
+ (element) => "pcb_component_id" in element && element.pcb_component_id === editEvent.pcb_component_id ? transformPCBElement(element, pcbToEditedPcbTransform) : element
20819
+ );
20820
+ continue;
20821
+ }
20822
+ if (editEvent.edit_event_type === "edit_schematic_component_location") {
20823
+ editedCircuitJson = editedCircuitJson.map(
20824
+ (element) => element.type === "schematic_component" && element.schematic_component_id === editEvent.schematic_component_id ? { ...element, center: editEvent.new_center } : element
20825
+ );
20826
+ continue;
20827
+ }
20828
+ if (editEvent.edit_event_type !== "edit_pcb_trace_hint") continue;
20829
+ if (!editEvent.pcb_trace_hint_id) continue;
20830
+ const pcbTraceHint = su(editedCircuitJson).pcb_trace_hint.get(
20831
+ editEvent.pcb_trace_hint_id
20832
+ );
20833
+ if (pcbTraceHint) {
20834
+ editedCircuitJson = editedCircuitJson.map(
20835
+ (element) => element.type === "pcb_trace_hint" && element.pcb_trace_hint_id === editEvent.pcb_trace_hint_id ? { ...element, route: editEvent.route } : element
20836
+ );
20837
+ continue;
20838
+ }
20839
+ const pcbPort = su(editedCircuitJson).pcb_port.get(editEvent.pcb_port_id);
20840
+ if (!pcbPort?.pcb_component_id) continue;
20841
+ const newPcbTraceHint = {
20842
+ type: "pcb_trace_hint",
20843
+ pcb_trace_hint_id: editEvent.pcb_trace_hint_id,
20844
+ route: editEvent.route,
20845
+ pcb_port_id: editEvent.pcb_port_id,
20846
+ pcb_component_id: pcbPort.pcb_component_id
20847
+ };
20848
+ editedCircuitJson = editedCircuitJson.filter(
20849
+ (element) => element.type !== "pcb_trace_hint" || element.pcb_port_id !== editEvent.pcb_port_id
20850
+ ).concat(newPcbTraceHint);
20851
+ }
20852
+ return editedCircuitJson;
20853
+ }
20854
+
20650
20855
  // src/PCBViewer.tsx
20651
20856
  import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
20652
- var defaultTransform = compose9(translate13(400, 300), scale6(40, -40));
20857
+ var defaultTransform = compose9(translate14(400, 300), scale6(40, -40));
20653
20858
  var PCBViewer = ({
20654
20859
  circuitJson,
20655
20860
  debugGraphics,
@@ -20729,9 +20934,9 @@ var PCBViewer = ({
20729
20934
  100
20730
20935
  ) * 0.75;
20731
20936
  const targetTransform = compose9(
20732
- translate13((elmBounds.width ?? 0) / 2, (elmBounds.height ?? 0) / 2),
20937
+ translate14((elmBounds.width ?? 0) / 2, (elmBounds.height ?? 0) / 2),
20733
20938
  scale6(scaleFactor, -scaleFactor, 0, 0),
20734
- translate13(-center.x, -center.y)
20939
+ translate14(-center.x, -center.y)
20735
20940
  );
20736
20941
  setTransform(targetTransform);
20737
20942
  return;