@tscircuit/pcb-viewer 1.11.258 → 1.11.260

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
@@ -6421,7 +6421,7 @@ var ToastContainer = () => {
6421
6421
  };
6422
6422
 
6423
6423
  // src/PCBViewer.tsx
6424
- import { useEffect as useEffect16, useMemo as useMemo7, useRef as useRef11, useState as useState11 } from "react";
6424
+ import { useEffect as useEffect16, useMemo as useMemo8, useRef as useRef11, useState as useState11 } from "react";
6425
6425
 
6426
6426
  // node_modules/react-use/esm/misc/util.js
6427
6427
  var noop = function() {
@@ -6972,7 +6972,7 @@ function addInteractionMetadataToPrimitives({
6972
6972
  }
6973
6973
 
6974
6974
  // src/components/CanvasElementsRenderer.tsx
6975
- import { useCallback as useCallback5, useMemo as useMemo6, useState as useState10 } from "react";
6975
+ import { useCallback as useCallback5, useMemo as useMemo7, useState as useState10 } from "react";
6976
6976
 
6977
6977
  // src/lib/util/expand-stroke.ts
6978
6978
  function getExpandedStroke(strokeInput, defaultWidth) {
@@ -9902,7 +9902,7 @@ var WarningGraphicsOverlay = ({
9902
9902
  };
9903
9903
 
9904
9904
  // src/components/DimensionOverlay.tsx
9905
- import { useCallback as useCallback3, useEffect as useEffect7, useMemo as useMemo3, useRef as useRef5, useState as useState3 } from "react";
9905
+ import { useCallback as useCallback3, useEffect as useEffect7, useMemo as useMemo4, useRef as useRef5, useState as useState3 } from "react";
9906
9906
  import { applyToPoint as applyToPoint8, identity as identity4, inverse as inverse2 } from "transformation-matrix";
9907
9907
 
9908
9908
  // src/lib/util/get-primitive-bounding-box.ts
@@ -10055,6 +10055,101 @@ var getPrimitiveBoundingBox = (primitive) => {
10055
10055
  }
10056
10056
  };
10057
10057
 
10058
+ // src/hooks/useDiagonalLabel.ts
10059
+ import { useMemo as useMemo3 } from "react";
10060
+
10061
+ // src/lib/util/calculate-diagonal-label.ts
10062
+ function calculateDiagonalLabel(params) {
10063
+ const {
10064
+ dimensionStart,
10065
+ dimensionEnd,
10066
+ screenDimensionStart,
10067
+ screenDimensionEnd,
10068
+ flipX,
10069
+ flipY
10070
+ } = params;
10071
+ const deltaX = dimensionEnd.x - dimensionStart.x;
10072
+ const deltaY = dimensionEnd.y - dimensionStart.y;
10073
+ const distance5 = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
10074
+ const screenDeltaX = screenDimensionEnd.x - screenDimensionStart.x;
10075
+ const screenDeltaY = screenDimensionEnd.y - screenDimensionStart.y;
10076
+ const screenDistance = Math.sqrt(
10077
+ screenDeltaX * screenDeltaX + screenDeltaY * screenDeltaY
10078
+ );
10079
+ const angle = Math.atan2(screenDeltaY, screenDeltaX) * (180 / Math.PI);
10080
+ const normalizedAngle = Math.abs(angle) % 90;
10081
+ const angleFromAxis = Math.min(normalizedAngle, 90 - normalizedAngle);
10082
+ const isDiagonal = angleFromAxis > 15;
10083
+ const midX = (screenDimensionStart.x + screenDimensionEnd.x) / 2;
10084
+ const midY = (screenDimensionStart.y + screenDimensionEnd.y) / 2;
10085
+ const offsetDistance = 15;
10086
+ const perpendicularAngle = angle + 90;
10087
+ let offsetX = Math.cos(perpendicularAngle * Math.PI / 180) * offsetDistance;
10088
+ let offsetY = Math.sin(perpendicularAngle * Math.PI / 180) * offsetDistance;
10089
+ const isNE = screenDeltaX > 0 && screenDeltaY < 0;
10090
+ const isNW = screenDeltaX < 0 && screenDeltaY < 0;
10091
+ const isSE = screenDeltaX > 0 && screenDeltaY > 0;
10092
+ const isSW = screenDeltaX < 0 && screenDeltaY > 0;
10093
+ if (flipX !== flipY && !isNE) {
10094
+ offsetX = -offsetX;
10095
+ offsetY = -offsetY;
10096
+ }
10097
+ if (isNE) {
10098
+ const lessOffset = -45;
10099
+ offsetX += Math.cos(perpendicularAngle * Math.PI / 180) * lessOffset;
10100
+ offsetY += Math.sin(perpendicularAngle * Math.PI / 180) * lessOffset;
10101
+ }
10102
+ if (isSE) {
10103
+ const seAdjust = -10;
10104
+ offsetX += Math.cos(perpendicularAngle * Math.PI / 180) + seAdjust * 2;
10105
+ offsetY += Math.sin(perpendicularAngle * Math.PI / 180) + seAdjust;
10106
+ }
10107
+ if (isSW) {
10108
+ const reduceOffset = 10;
10109
+ offsetX += Math.cos(perpendicularAngle * Math.PI / 180) * reduceOffset;
10110
+ offsetY += Math.sin(perpendicularAngle * Math.PI / 180) * reduceOffset;
10111
+ }
10112
+ const x = midX + offsetX;
10113
+ const y = midY + offsetY;
10114
+ return {
10115
+ distance: distance5,
10116
+ screenDistance,
10117
+ x,
10118
+ y,
10119
+ show: distance5 > 0.01 && screenDistance > 30 && isDiagonal
10120
+ };
10121
+ }
10122
+
10123
+ // src/hooks/useDiagonalLabel.ts
10124
+ function useDiagonalLabel(params) {
10125
+ const {
10126
+ dimensionStart,
10127
+ dimensionEnd,
10128
+ screenDimensionStart,
10129
+ screenDimensionEnd,
10130
+ flipX,
10131
+ flipY
10132
+ } = params;
10133
+ return useMemo3(
10134
+ () => calculateDiagonalLabel({
10135
+ dimensionStart,
10136
+ dimensionEnd,
10137
+ screenDimensionStart,
10138
+ screenDimensionEnd,
10139
+ flipX,
10140
+ flipY
10141
+ }),
10142
+ [
10143
+ dimensionStart,
10144
+ dimensionEnd,
10145
+ screenDimensionStart,
10146
+ screenDimensionEnd,
10147
+ flipX,
10148
+ flipY
10149
+ ]
10150
+ );
10151
+ }
10152
+
10058
10153
  // src/components/DimensionOverlay.tsx
10059
10154
  import { Fragment, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
10060
10155
  var SNAP_THRESHOLD_PX = 16;
@@ -10101,7 +10196,7 @@ var DimensionOverlay = ({
10101
10196
  const containerRef = useRef5(null);
10102
10197
  const container = containerRef.current;
10103
10198
  const containerBounds = container?.getBoundingClientRect();
10104
- const elementBoundingBoxes = useMemo3(() => {
10199
+ const elementBoundingBoxes = useMemo4(() => {
10105
10200
  const boundingBoxes = /* @__PURE__ */ new Map();
10106
10201
  for (const primitive of primitives) {
10107
10202
  if (!primitive._element) continue;
@@ -10116,7 +10211,7 @@ var DimensionOverlay = ({
10116
10211
  }
10117
10212
  return boundingBoxes;
10118
10213
  }, [primitives]);
10119
- const snappingPoints = useMemo3(() => {
10214
+ const snappingPoints = useMemo4(() => {
10120
10215
  const points = [];
10121
10216
  elementBoundingBoxes.forEach((bounds, element) => {
10122
10217
  if (!bounds) return;
@@ -10141,9 +10236,14 @@ var DimensionOverlay = ({
10141
10236
  });
10142
10237
  }
10143
10238
  });
10239
+ points.push({
10240
+ anchor: "origin",
10241
+ point: { x: 0, y: 0 },
10242
+ element: null
10243
+ });
10144
10244
  return points;
10145
10245
  }, [elementBoundingBoxes]);
10146
- const snappingPointsWithScreen = useMemo3(() => {
10246
+ const snappingPointsWithScreen = useMemo4(() => {
10147
10247
  return snappingPoints.map((snap, index) => ({
10148
10248
  ...snap,
10149
10249
  id: `${index}-${snap.anchor}`,
@@ -10250,6 +10350,14 @@ var DimensionOverlay = ({
10250
10350
  };
10251
10351
  arrowScreenBounds.width = arrowScreenBounds.right - arrowScreenBounds.left;
10252
10352
  arrowScreenBounds.height = arrowScreenBounds.bottom - arrowScreenBounds.top;
10353
+ const diagonalLabel = useDiagonalLabel({
10354
+ dimensionStart: dStart,
10355
+ dimensionEnd: dEnd,
10356
+ screenDimensionStart: screenDStart,
10357
+ screenDimensionEnd: screenDEnd,
10358
+ flipX: arrowScreenBounds.flipX,
10359
+ flipY: arrowScreenBounds.flipY
10360
+ });
10253
10361
  return /* @__PURE__ */ jsxs4(
10254
10362
  "div",
10255
10363
  {
@@ -10303,6 +10411,24 @@ var DimensionOverlay = ({
10303
10411
  children: [
10304
10412
  children,
10305
10413
  dimensionToolVisible && /* @__PURE__ */ jsxs4(Fragment, { children: [
10414
+ diagonalLabel.show && /* @__PURE__ */ jsx6(
10415
+ "div",
10416
+ {
10417
+ style: {
10418
+ position: "absolute",
10419
+ left: diagonalLabel.x,
10420
+ top: diagonalLabel.y,
10421
+ color: "red",
10422
+ mixBlendMode: "difference",
10423
+ pointerEvents: "none",
10424
+ fontSize: 12,
10425
+ fontFamily: "sans-serif",
10426
+ whiteSpace: "nowrap",
10427
+ zIndex: zIndexMap.dimensionOverlay
10428
+ },
10429
+ children: diagonalLabel.distance.toFixed(2)
10430
+ }
10431
+ ),
10306
10432
  /* @__PURE__ */ jsx6(
10307
10433
  "div",
10308
10434
  {
@@ -11567,7 +11693,7 @@ var ErrorOverlay = ({
11567
11693
  };
11568
11694
 
11569
11695
  // src/components/MouseElementTracker.tsx
11570
- import { useState as useState7, useMemo as useMemo4 } from "react";
11696
+ import { useState as useState7, useMemo as useMemo5 } from "react";
11571
11697
  import { applyToPoint as applyToPoint12, inverse as inverse5 } from "transformation-matrix";
11572
11698
 
11573
11699
  // src/components/ElementOverlayBox.tsx
@@ -11984,7 +12110,7 @@ var MouseElementTracker = ({
11984
12110
  }) => {
11985
12111
  const [mousedPrimitives, setMousedPrimitives] = useState7([]);
11986
12112
  const [mousePos, setMousePos] = useState7({ x: 0, y: 0 });
11987
- const highlightedPrimitives = useMemo4(() => {
12113
+ const highlightedPrimitives = useMemo5(() => {
11988
12114
  const highlightedPrimitives2 = [];
11989
12115
  for (const primitive of mousedPrimitives) {
11990
12116
  if (primitive._element?.type === "pcb_via") continue;
@@ -12348,15 +12474,15 @@ var PcbGroupOverlay = ({
12348
12474
 
12349
12475
  // src/components/RatsNestOverlay.tsx
12350
12476
  import { applyToPoint as applyToPoint14, identity as identity9 } from "transformation-matrix";
12351
- import { useMemo as useMemo5 } from "react";
12477
+ import { useMemo as useMemo6 } from "react";
12352
12478
  import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
12353
12479
  var RatsNestOverlay = ({ transform, soup, children }) => {
12354
12480
  const isShowingRatsNest = useGlobalStore((s) => s.is_showing_rats_nest);
12355
- const { netMap, idToNetMap } = useMemo5(
12481
+ const { netMap, idToNetMap } = useMemo6(
12356
12482
  () => getFullConnectivityMapFromCircuitJson(soup || []),
12357
12483
  [soup]
12358
12484
  );
12359
- const ratsNestLines = useMemo5(() => {
12485
+ const ratsNestLines = useMemo6(() => {
12360
12486
  if (!soup || !isShowingRatsNest) return [];
12361
12487
  const getElementPosition = (id) => {
12362
12488
  const element = su(soup)[id.replace(/_\d+$/, "")].get(id);
@@ -12461,7 +12587,7 @@ import { css as css3 } from "@emotion/css";
12461
12587
  // package.json
12462
12588
  var package_default = {
12463
12589
  name: "@tscircuit/pcb-viewer",
12464
- version: "1.11.257",
12590
+ version: "1.11.259",
12465
12591
  main: "dist/index.js",
12466
12592
  type: "module",
12467
12593
  repository: "tscircuit/pcb-viewer",
@@ -13295,11 +13421,11 @@ var CanvasElementsRenderer = (props) => {
13295
13421
  const isShowingCopperPours = useGlobalStore(
13296
13422
  (state) => state.is_showing_copper_pours
13297
13423
  );
13298
- const elementsToRender = useMemo6(
13424
+ const elementsToRender = useMemo7(
13299
13425
  () => isShowingCopperPours ? elements : elements.filter((elm) => elm.type !== "pcb_copper_pour"),
13300
13426
  [elements, isShowingCopperPours]
13301
13427
  );
13302
- const [primitivesWithoutInteractionMetadata, connectivityMap] = useMemo6(() => {
13428
+ const [primitivesWithoutInteractionMetadata, connectivityMap] = useMemo7(() => {
13303
13429
  const primitivesWithoutInteractionMetadata2 = elementsToRender.flatMap(
13304
13430
  (elm) => convertElementToPrimitives(elm, props.elements)
13305
13431
  );
@@ -13312,7 +13438,7 @@ var CanvasElementsRenderer = (props) => {
13312
13438
  drawingObjectIdsWithMouseOver: /* @__PURE__ */ new Set(),
13313
13439
  primitiveIdsInMousedOverNet: []
13314
13440
  });
13315
- const errorRelatedIds = useMemo6(() => {
13441
+ const errorRelatedIds = useMemo7(() => {
13316
13442
  if (!hoveredErrorId) return [];
13317
13443
  const errorElements = elements.filter(
13318
13444
  (el) => el.type.includes("error")
@@ -13331,7 +13457,7 @@ var CanvasElementsRenderer = (props) => {
13331
13457
  }
13332
13458
  return relatedIds;
13333
13459
  }, [hoveredErrorId, elements]);
13334
- const primitives = useMemo6(() => {
13460
+ const primitives = useMemo7(() => {
13335
13461
  const combinedPrimitiveIds = [
13336
13462
  ...hoverState.primitiveIdsInMousedOverNet,
13337
13463
  ...errorRelatedIds
@@ -13505,7 +13631,7 @@ var PCBViewer = ({
13505
13631
  editEvents = editEventsProp ?? editEvents;
13506
13632
  const initialRenderCompleted = useRef11(false);
13507
13633
  const touchStartRef = useRef11(null);
13508
- const circuitJsonKey = useMemo7(
13634
+ const circuitJsonKey = useMemo8(
13509
13635
  () => calculateCircuitJsonKey(circuitJson),
13510
13636
  [circuitJson]
13511
13637
  );
@@ -13538,12 +13664,12 @@ var PCBViewer = ({
13538
13664
  initialRenderCompleted.current = true;
13539
13665
  }
13540
13666
  }, [circuitJson, refDimensions]);
13541
- const pcbElmsPreEdit = useMemo7(() => {
13667
+ const pcbElmsPreEdit = useMemo8(() => {
13542
13668
  return circuitJson?.filter(
13543
13669
  (e) => e.type.startsWith("pcb_") || e.type.startsWith("source_")
13544
13670
  ) ?? [];
13545
13671
  }, [circuitJsonKey]);
13546
- const elements = useMemo7(() => {
13672
+ const elements = useMemo8(() => {
13547
13673
  return applyEditEvents({
13548
13674
  circuitJson: pcbElmsPreEdit,
13549
13675
  editEvents
@@ -13560,7 +13686,7 @@ var PCBViewer = ({
13560
13686
  setEditEvents(newEditEvents);
13561
13687
  onEditEventsChanged?.(newEditEvents);
13562
13688
  };
13563
- const mergedInitialState = useMemo7(
13689
+ const mergedInitialState = useMemo8(
13564
13690
  () => ({
13565
13691
  ...initialState,
13566
13692
  ...disablePcbGroups && { is_showing_pcb_groups: false }