@tscircuit/pcb-viewer 1.11.97 → 1.11.99

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
@@ -29,23 +29,19 @@ type StateProps = {
29
29
  [key in keyof State]: State[key] extends boolean ? boolean : never;
30
30
  };
31
31
 
32
- type EditEvent = ManualEditEvent;
33
-
34
32
  type Props = {
35
33
  circuitJson?: AnyCircuitElement[];
36
34
  height?: number;
37
35
  allowEditing?: boolean;
38
- editEvents?: EditEvent[];
36
+ editEvents?: ManualEditEvent[];
39
37
  initialState?: Partial<StateProps>;
40
- onEditEventsChanged?: (editEvents: EditEvent[]) => void;
38
+ onEditEventsChanged?: (editEvents: ManualEditEvent[]) => void;
41
39
  focusOnHover?: boolean;
42
40
  clickToInteractEnabled?: boolean;
43
41
  debugGraphics?: GraphicsObject | null;
44
42
  };
45
43
  declare const PCBViewer: ({ circuitJson, debugGraphics, height, initialState, allowEditing, editEvents: editEventsProp, onEditEventsChanged, focusOnHover, clickToInteractEnabled, }: Props) => react_jsx_runtime.JSX.Element;
46
44
 
47
- declare const applyEditEvents: (soup: AnyCircuitElement[], edit_events: EditEvent[]) => AnyCircuitElement[];
48
-
49
45
  type GridConfig = {
50
46
  spacing: number;
51
47
  view_window: {
@@ -66,9 +62,9 @@ interface CanvasElementsRendererProps {
66
62
  allowEditing: boolean;
67
63
  focusOnHover?: boolean;
68
64
  cancelPanDrag: () => void;
69
- onCreateEditEvent: (event: EditEvent) => void;
70
- onModifyEditEvent: (event: Partial<EditEvent>) => void;
65
+ onCreateEditEvent: (event: ManualEditEvent) => void;
66
+ onModifyEditEvent: (event: Partial<ManualEditEvent>) => void;
71
67
  }
72
68
  declare const CanvasElementsRenderer: (props: CanvasElementsRendererProps) => react_jsx_runtime.JSX.Element;
73
69
 
74
- export { CanvasElementsRenderer, type EditEvent, PCBViewer, applyEditEvents };
70
+ export { CanvasElementsRenderer, PCBViewer };
package/dist/index.js CHANGED
@@ -4,6 +4,9 @@ var __export = (target, all) => {
4
4
  __defProp(target, name, { get: all[name], enumerable: true });
5
5
  };
6
6
 
7
+ // src/PCBViewer.tsx
8
+ import { applyEditEvents } from "@tscircuit/core";
9
+
7
10
  // node_modules/circuit-json/dist/index.mjs
8
11
  var dist_exports = {};
9
12
  __export(dist_exports, {
@@ -5578,43 +5581,6 @@ var su = (soup, options = {}) => {
5578
5581
  };
5579
5582
  su.unparsed = su;
5580
5583
  var su_default = su;
5581
- var transformPCBElement = (elm, matrix) => {
5582
- if (elm.type === "pcb_plated_hole" || elm.type === "pcb_hole" || elm.type === "pcb_via" || elm.type === "pcb_smtpad" || elm.type === "pcb_port") {
5583
- const { x, y } = applyToPoint(matrix, { x: elm.x, y: elm.y });
5584
- elm.x = x;
5585
- elm.y = y;
5586
- } else if (elm.type === "pcb_keepout" || elm.type === "pcb_board") {
5587
- elm.center = applyToPoint(matrix, elm.center);
5588
- } else if (elm.type === "pcb_silkscreen_text" || elm.type === "pcb_fabrication_note_text") {
5589
- elm.anchor_position = applyToPoint(matrix, elm.anchor_position);
5590
- } else if (elm.type === "pcb_silkscreen_circle" || elm.type === "pcb_silkscreen_rect" || elm.type === "pcb_component") {
5591
- elm.center = applyToPoint(matrix, elm.center);
5592
- } else if (elm.type === "pcb_silkscreen_path" || elm.type === "pcb_trace" || elm.type === "pcb_fabrication_note_path") {
5593
- elm.route = elm.route.map((rp) => {
5594
- const tp = applyToPoint(matrix, rp);
5595
- rp.x = tp.x;
5596
- rp.y = tp.y;
5597
- return rp;
5598
- });
5599
- } else if (elm.type === "pcb_silkscreen_line") {
5600
- const p1 = { x: elm.x1, y: elm.y1 };
5601
- const p2 = { x: elm.x2, y: elm.y2 };
5602
- const p1t = applyToPoint(matrix, p1);
5603
- const p2t = applyToPoint(matrix, p2);
5604
- elm.x1 = p1t.x;
5605
- elm.y1 = p1t.y;
5606
- elm.x2 = p2t.x;
5607
- elm.y2 = p2t.y;
5608
- } else if (elm.type === "cad_component") {
5609
- const newPos = applyToPoint(matrix, {
5610
- x: elm.position.x,
5611
- y: elm.position.y
5612
- });
5613
- elm.position.x = newPos.x;
5614
- elm.position.y = newPos.y;
5615
- }
5616
- return elm;
5617
- };
5618
5584
  function stringHash(str) {
5619
5585
  let hash = 0;
5620
5586
  if (str.length == 0)
@@ -5849,57 +5815,6 @@ var ContextProviders = ({
5849
5815
  return /* @__PURE__ */ jsx(StoreContext.Provider, { value: store, children });
5850
5816
  };
5851
5817
 
5852
- // src/lib/apply-edit-events.ts
5853
- import { translate } from "transformation-matrix";
5854
-
5855
- // src/lib/apply-edit-events/apply-edit-trace-hint-event.ts
5856
- var applyTraceHintEditEvent = (soup, edit_event) => {
5857
- const existing_trace_hint = soup.find(
5858
- (th) => th.type === "pcb_trace_hint" && th.pcb_trace_hint_id === edit_event.pcb_trace_hint_id
5859
- );
5860
- if (existing_trace_hint) {
5861
- soup = soup.map(
5862
- (e) => e.pcb_trace_hint_id === edit_event.pcb_trace_hint_id ? {
5863
- ...e,
5864
- route: edit_event.route
5865
- } : e
5866
- );
5867
- } else {
5868
- const pcb_port2 = su_default(soup).pcb_port.get(edit_event.pcb_port_id);
5869
- soup = soup.filter(
5870
- (e) => !(e.type === "pcb_trace_hint" && e.pcb_port_id === edit_event.pcb_port_id)
5871
- ).concat([
5872
- {
5873
- type: "pcb_trace_hint",
5874
- pcb_trace_hint_id: edit_event.pcb_trace_hint_id,
5875
- route: edit_event.route,
5876
- pcb_port_id: edit_event.pcb_port_id,
5877
- pcb_component_id: pcb_port2?.pcb_component_id
5878
- }
5879
- ]);
5880
- }
5881
- return soup;
5882
- };
5883
-
5884
- // src/lib/apply-edit-events.ts
5885
- var applyEditEvents = (soup, edit_events) => {
5886
- soup = JSON.parse(JSON.stringify(soup));
5887
- for (const edit_event of edit_events) {
5888
- if (edit_event.edit_event_type === "edit_pcb_component_location") {
5889
- const mat = translate(
5890
- edit_event.new_center.x - edit_event.original_center.x,
5891
- edit_event.new_center.y - edit_event.original_center.y
5892
- );
5893
- soup = soup.map(
5894
- (e) => e.pcb_component_id !== edit_event.pcb_component_id ? e : transformPCBElement(e, mat)
5895
- );
5896
- } else if (edit_event.edit_event_type === "edit_pcb_trace_hint") {
5897
- soup = applyTraceHintEditEvent(soup, edit_event);
5898
- }
5899
- }
5900
- return soup;
5901
- };
5902
-
5903
5818
  // src/lib/toast.tsx
5904
5819
  import { useEffect } from "react";
5905
5820
  import {
@@ -5980,13 +5895,13 @@ var useMeasure_default = isBrowser && typeof window.ResizeObserver !== "undefine
5980
5895
  };
5981
5896
 
5982
5897
  // src/PCBViewer.tsx
5983
- import { compose as compose4, scale as scale2, translate as translate5 } from "transformation-matrix";
5898
+ import { compose as compose4, scale as scale2, translate as translate4 } from "transformation-matrix";
5984
5899
 
5985
- // node_modules/use-mouse-matrix-transform/dist/chunk-5TGSLHOO.js
5900
+ // node_modules/use-mouse-matrix-transform/dist/chunk-A3SUJQLF.js
5986
5901
  import {
5987
5902
  identity,
5988
5903
  scale,
5989
- translate as translate2,
5904
+ translate,
5990
5905
  compose,
5991
5906
  applyToPoint as applyToPoint2
5992
5907
  } from "transformation-matrix";
@@ -6022,6 +5937,9 @@ var useMouseMatrixTransform = (props = {}) => {
6022
5937
  const cancelDrag = useCallback(() => {
6023
5938
  setLastDragCancelTime(Date.now());
6024
5939
  }, []);
5940
+ const gestureModeRef = useRef("none");
5941
+ const lastTouchRef = useRef(null);
5942
+ const pinchDataRef = useRef(null);
6025
5943
  useEffect3(() => {
6026
5944
  const canvasElm = props.canvasElm ?? extRef.current;
6027
5945
  if (canvasElm && !outerCanvasElm) {
@@ -6059,7 +5977,7 @@ var useMouseMatrixTransform = (props = {}) => {
6059
5977
  if (props.shouldDrag && !props.shouldDrag(e))
6060
5978
  return;
6061
5979
  m1 = getMousePos(e);
6062
- const new_tf = compose(translate2(m1.x - m0.x, m1.y - m0.y), init_tf);
5980
+ const new_tf = compose(translate(m1.x - m0.x, m1.y - m0.y), init_tf);
6063
5981
  setTransform(new_tf);
6064
5982
  init_tf = new_tf;
6065
5983
  md = false;
@@ -6071,7 +5989,7 @@ var useMouseMatrixTransform = (props = {}) => {
6071
5989
  if (props.shouldDrag && !props.shouldDrag(e))
6072
5990
  return;
6073
5991
  m1 = getMousePos(e);
6074
- setTransform(compose(translate2(m1.x - m0.x, m1.y - m0.y), init_tf));
5992
+ setTransform(compose(translate(m1.x - m0.x, m1.y - m0.y), init_tf));
6075
5993
  }
6076
5994
  function handleMouseWheel(e) {
6077
5995
  if (props.enabled === false)
@@ -6080,9 +5998,9 @@ var useMouseMatrixTransform = (props = {}) => {
6080
5998
  return;
6081
5999
  const center = getMousePos(e);
6082
6000
  const new_tf = compose(
6083
- translate2(center.x, center.y),
6001
+ translate(center.x, center.y),
6084
6002
  scale(1 - e.deltaY / 1e3, 1 - e.deltaY / 1e3),
6085
- translate2(-center.x, -center.y),
6003
+ translate(-center.x, -center.y),
6086
6004
  init_tf
6087
6005
  );
6088
6006
  setTransform(new_tf);
@@ -6102,23 +6020,101 @@ var useMouseMatrixTransform = (props = {}) => {
6102
6020
  }
6103
6021
  md = false;
6104
6022
  m1 = getMousePos(e);
6105
- const new_tf = compose(translate2(m1.x - m0.x, m1.y - m0.y), init_tf);
6023
+ const new_tf = compose(translate(m1.x - m0.x, m1.y - m0.y), init_tf);
6106
6024
  setTransform(new_tf);
6107
6025
  init_tf = new_tf;
6108
6026
  }
6027
+ function handleTouchStart(e) {
6028
+ e.preventDefault();
6029
+ if (props.enabled === false)
6030
+ return;
6031
+ if (e.touches.length === 1) {
6032
+ gestureModeRef.current = "drag";
6033
+ const touch = e.touches[0];
6034
+ lastTouchRef.current = { x: touch.clientX, y: touch.clientY };
6035
+ } else if (e.touches.length === 2) {
6036
+ gestureModeRef.current = "pinch";
6037
+ const touch1 = e.touches[0];
6038
+ const touch2 = e.touches[1];
6039
+ const dx = touch2.clientX - touch1.clientX;
6040
+ const dy = touch2.clientY - touch1.clientY;
6041
+ const distance2 = Math.hypot(dx, dy);
6042
+ const midpoint = {
6043
+ x: (touch1.clientX + touch2.clientX) / 2,
6044
+ y: (touch1.clientY + touch2.clientY) / 2
6045
+ };
6046
+ pinchDataRef.current = {
6047
+ initialDistance: distance2,
6048
+ initialMidpoint: midpoint
6049
+ };
6050
+ }
6051
+ }
6052
+ function handleTouchMove(e) {
6053
+ e.preventDefault();
6054
+ if (props.enabled === false)
6055
+ return;
6056
+ if (gestureModeRef.current === "drag" && e.touches.length === 1 && lastTouchRef.current) {
6057
+ const touch = e.touches[0];
6058
+ const deltaX = touch.clientX - lastTouchRef.current.x;
6059
+ const deltaY = touch.clientY - lastTouchRef.current.y;
6060
+ const new_tf = { ...init_tf, e: init_tf.e + deltaX, f: init_tf.f + deltaY };
6061
+ setTransform(new_tf);
6062
+ init_tf = new_tf;
6063
+ lastTouchRef.current = { x: touch.clientX, y: touch.clientY };
6064
+ } else if (gestureModeRef.current === "pinch" && e.touches.length === 2 && pinchDataRef.current) {
6065
+ const touch1 = e.touches[0];
6066
+ const touch2 = e.touches[1];
6067
+ const dx = touch2.clientX - touch1.clientX;
6068
+ const dy = touch2.clientY - touch1.clientY;
6069
+ const newDistance = Math.hypot(dx, dy);
6070
+ const { initialDistance, initialMidpoint } = pinchDataRef.current;
6071
+ const scaleFactor = 1 + (newDistance / initialDistance - 1) * 0.07;
6072
+ const new_tf = compose(
6073
+ translate(initialMidpoint.x, initialMidpoint.y),
6074
+ scale(scaleFactor, scaleFactor),
6075
+ translate(-initialMidpoint.x, -initialMidpoint.y),
6076
+ init_tf
6077
+ );
6078
+ setTransform(new_tf);
6079
+ init_tf = new_tf;
6080
+ }
6081
+ }
6082
+ function handleTouchEnd(e) {
6083
+ e.preventDefault();
6084
+ if (e.touches.length === 0) {
6085
+ gestureModeRef.current = "none";
6086
+ lastTouchRef.current = null;
6087
+ pinchDataRef.current = null;
6088
+ }
6089
+ }
6109
6090
  canvasElm.addEventListener("mousedown", handleMouseDown);
6110
6091
  canvasElm.addEventListener("mouseup", handleMouseUp);
6111
6092
  window.addEventListener("mousemove", handleMouseMove);
6112
6093
  canvasElm.addEventListener("mouseout", handleMouseOut);
6113
6094
  canvasElm.addEventListener("wheel", handleMouseWheel);
6095
+ canvasElm.addEventListener("touchstart", handleTouchStart, { passive: false });
6096
+ canvasElm.addEventListener("touchmove", handleTouchMove, { passive: false });
6097
+ canvasElm.addEventListener("touchend", handleTouchEnd, { passive: false });
6098
+ canvasElm.addEventListener("touchcancel", handleTouchEnd, { passive: false });
6114
6099
  return () => {
6115
6100
  canvasElm.removeEventListener("mousedown", handleMouseDown);
6116
6101
  canvasElm.removeEventListener("mouseup", handleMouseUp);
6117
6102
  window.removeEventListener("mousemove", handleMouseMove);
6118
6103
  canvasElm.removeEventListener("mouseout", handleMouseOut);
6119
6104
  canvasElm.removeEventListener("wheel", handleMouseWheel);
6105
+ canvasElm.removeEventListener("touchstart", handleTouchStart);
6106
+ canvasElm.removeEventListener("touchmove", handleTouchMove);
6107
+ canvasElm.removeEventListener("touchend", handleTouchEnd);
6108
+ canvasElm.removeEventListener("touchcancel", handleTouchEnd);
6120
6109
  };
6121
- }, [outerCanvasElm, waitCounter, extChangeCounter, lastDragCancelTime, props.enabled, props.shouldDrag]);
6110
+ }, [
6111
+ outerCanvasElm,
6112
+ waitCounter,
6113
+ extChangeCounter,
6114
+ lastDragCancelTime,
6115
+ props.enabled,
6116
+ props.shouldDrag
6117
+ ]);
6122
6118
  const applyTransformToPoint = useCallback(
6123
6119
  (obj) => applyToPoint2(transform, obj),
6124
6120
  [transform]
@@ -6766,7 +6762,7 @@ import {
6766
6762
  compose as compose2,
6767
6763
  identity as identity2,
6768
6764
  inverse,
6769
- translate as translate3
6765
+ translate as translate2
6770
6766
  } from "transformation-matrix";
6771
6767
 
6772
6768
  // src/lib/colors.ts
@@ -7079,7 +7075,7 @@ var Drawer = class {
7079
7075
  );
7080
7076
  this.transform = identity2();
7081
7077
  this.transform.d *= -1;
7082
- this.transform = compose2(this.transform, translate3(0, -500));
7078
+ this.transform = compose2(this.transform, translate2(0, -500));
7083
7079
  this.lastPoint = { x: 0, y: 0 };
7084
7080
  this.equip({});
7085
7081
  }
@@ -7336,16 +7332,16 @@ var Drawer = class {
7336
7332
  };
7337
7333
 
7338
7334
  // src/lib/util/rotate-text.ts
7339
- import { compose as compose3, translate as translate4, rotate, applyToPoint as applyToPoint4 } from "transformation-matrix";
7335
+ import { compose as compose3, translate as translate3, rotate, applyToPoint as applyToPoint4 } from "transformation-matrix";
7340
7336
  function rotateText(rotateTextParams) {
7341
7337
  const { lines, anchorPoint, ccwRotation } = rotateTextParams;
7342
7338
  if (!ccwRotation) return lines;
7343
7339
  const rad = ccwRotation * Math.PI / 180;
7344
7340
  const rotationMatrix = rotate(rad);
7345
7341
  const transform = compose3(
7346
- translate4(anchorPoint.x, anchorPoint.y),
7342
+ translate3(anchorPoint.x, anchorPoint.y),
7347
7343
  rotationMatrix,
7348
- translate4(-anchorPoint.x, -anchorPoint.y)
7344
+ translate3(-anchorPoint.x, -anchorPoint.y)
7349
7345
  );
7350
7346
  applyToPoint4(transform, anchorPoint);
7351
7347
  return lines.map((line) => ({
@@ -8042,7 +8038,7 @@ var EditPlacementOverlay = ({
8042
8038
  const rect = e.currentTarget.getBoundingClientRect();
8043
8039
  const x = e.clientX - rect.left;
8044
8040
  const y = e.clientY - rect.top;
8045
- if (isNaN(x) || isNaN(y)) return;
8041
+ if (Number.isNaN(x) || Number.isNaN(y)) return;
8046
8042
  const rwMousePoint = applyToPoint6(inverse3(transform), { x, y });
8047
8043
  let foundActiveComponent = false;
8048
8044
  for (const e2 of soup) {
@@ -8084,7 +8080,7 @@ var EditPlacementOverlay = ({
8084
8080
  const rect = e.currentTarget.getBoundingClientRect();
8085
8081
  const x = e.clientX - rect.left;
8086
8082
  const y = e.clientY - rect.top;
8087
- if (isNaN(x) || isNaN(y)) return;
8083
+ if (Number.isNaN(x) || Number.isNaN(y)) return;
8088
8084
  const rwMousePoint = applyToPoint6(inverse3(transform), { x, y });
8089
8085
  setDragState({
8090
8086
  ...dragState,
@@ -9184,7 +9180,7 @@ import { css as css3 } from "@emotion/css";
9184
9180
  // package.json
9185
9181
  var package_default = {
9186
9182
  name: "@tscircuit/pcb-viewer",
9187
- version: "1.11.96",
9183
+ version: "1.11.98",
9188
9184
  main: "dist/index.js",
9189
9185
  type: "module",
9190
9186
  repository: "tscircuit/pcb-viewer",
@@ -9210,7 +9206,7 @@ var package_default = {
9210
9206
  "@storybook/nextjs": "^8.0.6",
9211
9207
  "@storybook/react": "^8.0.6",
9212
9208
  "@swc/core": "^1.4.12",
9213
- "@tscircuit/core": "0.0.367",
9209
+ "@tscircuit/core": "0.0.370",
9214
9210
  "@tscircuit/eagle-xml-converter": "^1.0.0",
9215
9211
  "@tscircuit/props": "^0.0.171",
9216
9212
  "@tscircuit/soup-util": "^0.0.41",
@@ -9733,7 +9729,7 @@ var CanvasElementsRenderer = (props) => {
9733
9729
 
9734
9730
  // src/PCBViewer.tsx
9735
9731
  import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
9736
- var defaultTransform = compose4(translate5(400, 300), scale2(40, -40));
9732
+ var defaultTransform = compose4(translate4(400, 300), scale2(40, -40));
9737
9733
  var PCBViewer = ({
9738
9734
  circuitJson,
9739
9735
  debugGraphics,
@@ -9776,9 +9772,9 @@ var PCBViewer = ({
9776
9772
  100
9777
9773
  ) * 0.75;
9778
9774
  const targetTransform = compose4(
9779
- translate5((elmBounds.width ?? 0) / 2, (elmBounds.height ?? 0) / 2),
9775
+ translate4((elmBounds.width ?? 0) / 2, (elmBounds.height ?? 0) / 2),
9780
9776
  scale2(scaleFactor, -scaleFactor, 0, 0),
9781
- translate5(-center.x, -center.y)
9777
+ translate4(-center.x, -center.y)
9782
9778
  );
9783
9779
  setTransform(targetTransform);
9784
9780
  return;
@@ -9798,7 +9794,10 @@ var PCBViewer = ({
9798
9794
  ) ?? [];
9799
9795
  }, [circuitJsonKey]);
9800
9796
  const elements = useMemo6(() => {
9801
- return applyEditEvents(pcbElmsPreEdit, editEvents);
9797
+ return applyEditEvents({
9798
+ circuitJson: pcbElmsPreEdit,
9799
+ editEvents
9800
+ });
9802
9801
  }, [pcbElmsPreEdit, editEvents]);
9803
9802
  const onCreateEditEvent = (event) => {
9804
9803
  setEditEvents([...editEvents, event]);
@@ -9876,7 +9875,6 @@ var PCBViewer = ({
9876
9875
  };
9877
9876
  export {
9878
9877
  CanvasElementsRenderer,
9879
- PCBViewer,
9880
- applyEditEvents
9878
+ PCBViewer
9881
9879
  };
9882
9880
  //# sourceMappingURL=index.js.map