@tscircuit/3d-viewer 0.0.48 → 0.0.50

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
@@ -49,7 +49,7 @@ var useConvertChildrenToSoup = (children, defaultSoup) => {
49
49
 
50
50
  // src/CadViewer.tsx
51
51
  var import_soup_util2 = require("@tscircuit/soup-util");
52
- var import_react9 = require("react");
52
+ var import_react10 = require("react");
53
53
 
54
54
  // src/soup-to-3d/index.ts
55
55
  var import_soup_util = require("@tscircuit/soup-util");
@@ -451,7 +451,7 @@ var import_fiber3 = require("@react-three/fiber");
451
451
  // package.json
452
452
  var package_default = {
453
453
  name: "@tscircuit/3d-viewer",
454
- version: "0.0.47",
454
+ version: "0.0.48",
455
455
  main: "./dist/index.js",
456
456
  files: [
457
457
  "dist"
@@ -477,9 +477,9 @@ var package_default = {
477
477
  "@tscircuit/soup": "^0.0.69",
478
478
  "@tscircuit/soup-util": "^0.0.26",
479
479
  "@types/three": "^0.165.0",
480
- "jscad-electronics": "^0.0.22",
481
- "jscad-fiber": "^0.0.74",
482
- "jscad-planner": "^0.0.8",
480
+ "jscad-electronics": "^0.0.23",
481
+ "jscad-fiber": "^0.0.75",
482
+ "jscad-planner": "^0.0.11",
483
483
  react: "^18.3.1",
484
484
  "react-dom": "^18.3.1",
485
485
  "react-use-gesture": "^9.1.3",
@@ -673,7 +673,7 @@ var CadViewerContainer = ({
673
673
  }
674
674
  ),
675
675
  children,
676
- hoveredComponent.id && hoveredComponent.mousePosition && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
676
+ hoveredComponent && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
677
677
  import_drei3.Html,
678
678
  {
679
679
  position: hoveredComponent.mousePosition,
@@ -716,12 +716,11 @@ var CadViewerContainer = ({
716
716
  var import_react5 = require("react");
717
717
  var THREE2 = __toESM(require("three"));
718
718
  var import_jsx_runtime4 = require("react/jsx-runtime");
719
+ var Group = (props) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("group", { ...props });
719
720
  var ContainerWithTooltip = ({
720
721
  children,
721
722
  isHovered,
722
723
  onHover,
723
- componentId,
724
- name,
725
724
  position
726
725
  }) => {
727
726
  const lastValidPointRef = (0, import_react5.useRef)(null);
@@ -732,16 +731,16 @@ var ContainerWithTooltip = ({
732
731
  const point = e.point || (e.intersections && e.intersections.length > 0 ? e.intersections[0].point : null) || (position ? new THREE2.Vector3(...position) : null);
733
732
  if (point) {
734
733
  lastValidPointRef.current = point;
735
- onHover(componentId, name, [point.x, point.y, point.z]);
734
+ onHover({ mousePosition: [point.x, point.y, point.z] });
736
735
  } else {
737
- onHover(componentId, name);
736
+ onHover({});
738
737
  }
739
738
  } catch (error) {
740
739
  console.warn("Hover event error:", error);
741
- onHover(componentId, name);
740
+ onHover({});
742
741
  }
743
742
  },
744
- [componentId, name, onHover, position]
743
+ [position]
745
744
  );
746
745
  const handlePointerLeave = (0, import_react5.useCallback)(
747
746
  (e) => {
@@ -751,12 +750,15 @@ var ContainerWithTooltip = ({
751
750
  },
752
751
  [onHover]
753
752
  );
754
- const groupProps = {
755
- onPointerEnter: handlePointerEnter,
756
- onPointerMove: handlePointerEnter,
757
- onPointerLeave: handlePointerLeave
758
- };
759
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("group", { ...groupProps, children });
753
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
754
+ Group,
755
+ {
756
+ onPointerEnter: handlePointerEnter,
757
+ onPointerMove: handlePointerEnter,
758
+ onPointerLeave: handlePointerLeave,
759
+ children
760
+ }
761
+ );
760
762
  };
761
763
  var ContainerWithTooltip_default = ContainerWithTooltip;
762
764
 
@@ -833,53 +835,24 @@ function MixedStlModel({
833
835
  url,
834
836
  position,
835
837
  rotation,
836
- componentId,
837
- name,
838
838
  onHover,
839
839
  isHovered
840
840
  }) {
841
841
  const obj = useGlobalObjLoader(url);
842
842
  if (!obj) {
843
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
844
- ContainerWithTooltip_default,
845
- {
846
- componentId,
847
- name,
848
- isHovered,
849
- onHover,
850
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("mesh", { position, children: [
851
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("boxGeometry", { args: [0.5, 0.5, 0.5] }),
852
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("meshStandardMaterial", { transparent: true, color: "red", opacity: 0.25 })
853
- ] })
854
- }
855
- );
843
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ContainerWithTooltip_default, { isHovered, onHover, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("mesh", { position, children: [
844
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("boxGeometry", { args: [0.5, 0.5, 0.5] }),
845
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("meshStandardMaterial", { transparent: true, color: "red", opacity: 0.25 })
846
+ ] }) });
856
847
  }
857
848
  if (obj instanceof Error) {
858
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
859
- ContainerWithTooltip_default,
860
- {
861
- componentId,
862
- name,
863
- isHovered,
864
- onHover,
865
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("mesh", { position, children: [
866
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("boxGeometry", { args: [0.5, 0.5, 0.5] }),
867
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("meshStandardMaterial", { transparent: true, color: "red", opacity: 0.5 }),
868
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("meshBasicMaterial", { color: "red" })
869
- ] })
870
- }
871
- );
849
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ContainerWithTooltip_default, { isHovered, onHover, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("mesh", { position, children: [
850
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("boxGeometry", { args: [0.5, 0.5, 0.5] }),
851
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("meshStandardMaterial", { transparent: true, color: "red", opacity: 0.5 }),
852
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("meshBasicMaterial", { color: "red" })
853
+ ] }) });
872
854
  }
873
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
874
- ContainerWithTooltip_default,
875
- {
876
- componentId,
877
- name,
878
- isHovered,
879
- onHover,
880
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("primitive", { rotation, position, object: obj })
881
- }
882
- );
855
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ContainerWithTooltip_default, { isHovered, onHover, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("primitive", { rotation, position, object: obj }) });
883
856
  }
884
857
 
885
858
  // src/three-components/JscadModel.tsx
@@ -893,8 +866,6 @@ var JscadModel = ({
893
866
  jscadPlan,
894
867
  positionOffset,
895
868
  rotationOffset,
896
- componentId,
897
- name,
898
869
  onHover,
899
870
  isHovered
900
871
  }) => {
@@ -922,8 +893,6 @@ var JscadModel = ({
922
893
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
923
894
  ContainerWithTooltip_default,
924
895
  {
925
- componentId,
926
- name,
927
896
  isHovered,
928
897
  onHover,
929
898
  position: positionOffset,
@@ -951,27 +920,23 @@ var FootprinterModel = ({
951
920
  positionOffset,
952
921
  footprint,
953
922
  rotationOffset,
954
- componentId,
955
- name,
956
923
  onHover,
957
924
  isHovered
958
925
  }) => {
959
- const jscadPlan = (0, import_react8.useMemo)(() => {
926
+ const jscadOperations = (0, import_react8.useMemo)(() => {
960
927
  if (!footprint) return null;
961
- const jscadPlan2 = [];
962
- const root = createJSCADRoot(jscadPlan2);
928
+ const jscadOperations2 = [];
929
+ const root = createJSCADRoot(jscadOperations2);
963
930
  root.render(/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jscad_electronics.Footprinter3d, { footprint }));
964
- return jscadPlan2;
931
+ return jscadOperations2;
965
932
  }, [footprint]);
966
- if (!jscadPlan) return null;
967
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: jscadPlan.map((plan, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
933
+ if (!jscadOperations) return null;
934
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: jscadOperations.map((operation, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
968
935
  JscadModel,
969
936
  {
970
937
  positionOffset,
971
938
  rotationOffset,
972
- jscadPlan: plan,
973
- componentId,
974
- name,
939
+ jscadPlan: operation,
975
940
  onHover,
976
941
  isHovered
977
942
  },
@@ -982,31 +947,163 @@ var FootprinterModel = ({
982
947
  // src/utils/tuple.ts
983
948
  var tuple = (...args) => args;
984
949
 
985
- // src/CadViewer.tsx
950
+ // src/AnyCadComponent.tsx
986
951
  var import_jsx_runtime8 = require("react/jsx-runtime");
952
+ var AnyCadComponent = ({
953
+ cad_component,
954
+ onHover = () => {
955
+ },
956
+ isHovered = false
957
+ }) => {
958
+ const url = cad_component.model_obj_url ?? cad_component.model_stl_url;
959
+ const rotationOffset = cad_component.rotation ? tuple(
960
+ cad_component.rotation.x * Math.PI / 180,
961
+ cad_component.rotation.y * Math.PI / 180,
962
+ cad_component.rotation.z * Math.PI / 180
963
+ ) : void 0;
964
+ if (url) {
965
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
966
+ MixedStlModel,
967
+ {
968
+ url,
969
+ position: cad_component.position ? [
970
+ cad_component.position.x,
971
+ cad_component.position.y,
972
+ cad_component.position.z
973
+ ] : void 0,
974
+ rotation: rotationOffset,
975
+ onHover,
976
+ isHovered
977
+ },
978
+ cad_component.cad_component_id
979
+ );
980
+ }
981
+ if (cad_component.model_jscad) {
982
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
983
+ JscadModel,
984
+ {
985
+ jscadPlan: cad_component.model_jscad,
986
+ rotationOffset,
987
+ onHover,
988
+ isHovered
989
+ },
990
+ cad_component.cad_component_id
991
+ );
992
+ }
993
+ if (cad_component.footprinter_string) {
994
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
995
+ FootprinterModel,
996
+ {
997
+ positionOffset: cad_component.position ? [
998
+ cad_component.position.x,
999
+ cad_component.position.y,
1000
+ cad_component.position.z
1001
+ ] : void 0,
1002
+ rotationOffset,
1003
+ footprint: cad_component.footprinter_string,
1004
+ onHover,
1005
+ isHovered
1006
+ }
1007
+ );
1008
+ }
1009
+ };
1010
+
1011
+ // src/three-components/ThreeErrorBoundary.tsx
1012
+ var import_react9 = __toESM(require("react"));
1013
+ var ThreeErrorBoundary = class extends import_react9.default.Component {
1014
+ constructor(props) {
1015
+ super(props);
1016
+ this.state = { hasError: false, error: null };
1017
+ }
1018
+ static getDerivedStateFromError(error) {
1019
+ return { hasError: true, error };
1020
+ }
1021
+ render() {
1022
+ if (this.state.hasError && this.state.error) {
1023
+ return this.props.fallback({ error: this.state.error });
1024
+ }
1025
+ return this.props.children;
1026
+ }
1027
+ };
1028
+
1029
+ // src/three-components/Error3d.tsx
1030
+ var import_drei4 = require("@react-three/drei");
1031
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1032
+ var Error3d = ({
1033
+ error,
1034
+ cad_component
1035
+ }) => {
1036
+ let position = [0, 0, 0];
1037
+ if (cad_component?.position) {
1038
+ position = [
1039
+ cad_component.position.x,
1040
+ cad_component.position.y,
1041
+ cad_component.position.z
1042
+ ];
1043
+ position = position.map((p) => Number.isNaN(p) ? 0 : p);
1044
+ }
1045
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1046
+ "group",
1047
+ {
1048
+ position,
1049
+ children: [
1050
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1051
+ "mesh",
1052
+ {
1053
+ renderOrder: -99999,
1054
+ rotation: [Math.PI / 4, Math.PI / 4, 0],
1055
+ ref: (mesh) => {
1056
+ if (mesh) {
1057
+ mesh.renderOrder = 999999;
1058
+ }
1059
+ },
1060
+ children: [
1061
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("boxGeometry", { args: [0.5, 0.5, 0.5] }),
1062
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1063
+ "meshStandardMaterial",
1064
+ {
1065
+ depthTest: false,
1066
+ transparent: true,
1067
+ color: "red",
1068
+ opacity: 0.5
1069
+ }
1070
+ )
1071
+ ]
1072
+ }
1073
+ ),
1074
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1075
+ import_drei4.Text,
1076
+ {
1077
+ scale: [0.1, 0.1, 0.1],
1078
+ color: "red",
1079
+ anchorX: "center",
1080
+ anchorY: "middle",
1081
+ depthOffset: -99999,
1082
+ children: [
1083
+ error.toString().slice(0, 50),
1084
+ "..."
1085
+ ]
1086
+ }
1087
+ )
1088
+ ]
1089
+ }
1090
+ );
1091
+ };
1092
+
1093
+ // src/CadViewer.tsx
1094
+ var import_jsx_runtime10 = require("react/jsx-runtime");
987
1095
  var CadViewer = ({ soup, children }) => {
988
- const [hoveredComponent, setHoveredComponent] = (0, import_react9.useState)({
989
- id: null,
990
- name: null,
991
- mousePosition: null
992
- });
1096
+ const [hoveredComponent, setHoveredComponent] = (0, import_react10.useState)(null);
993
1097
  soup ??= useConvertChildrenToSoup(children, soup);
994
1098
  if (!soup) return null;
995
- const boardGeom = (0, import_react9.useMemo)(() => {
1099
+ const boardGeom = (0, import_react10.useMemo)(() => {
996
1100
  if (!soup.some((e) => e.type === "pcb_board")) return null;
997
1101
  return createBoardGeomFromSoup(soup);
998
1102
  }, [soup]);
999
- const { stls, loading } = useStlsFromGeom(boardGeom);
1103
+ const { stls: boardStls, loading } = useStlsFromGeom(boardGeom);
1000
1104
  const cad_components = (0, import_soup_util2.su)(soup).cad_component.list();
1001
- const handleHover = (componentId, componentName, mousePosition) => {
1002
- setHoveredComponent({
1003
- id: componentId,
1004
- name: componentName || null,
1005
- mousePosition: mousePosition || null
1006
- });
1007
- };
1008
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(CadViewerContainer, { hoveredComponent, children: [
1009
- stls.map(({ stlUrl, color }, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1105
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(CadViewerContainer, { hoveredComponent, children: [
1106
+ boardStls.map(({ stlUrl, color }, index) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1010
1107
  STLModel,
1011
1108
  {
1012
1109
  stlUrl,
@@ -1015,68 +1112,35 @@ var CadViewer = ({ soup, children }) => {
1015
1112
  },
1016
1113
  stlUrl
1017
1114
  )),
1018
- cad_components.map((cad_component) => {
1019
- const componentName = (0, import_soup_util2.su)(soup).source_component.getUsing({
1020
- source_component_id: cad_component.source_component_id
1021
- })?.name;
1022
- const url = cad_component.model_obj_url ?? cad_component.model_stl_url;
1023
- const rotationOffset = cad_component.rotation ? tuple(
1024
- cad_component.rotation.x * Math.PI / 180,
1025
- cad_component.rotation.y * Math.PI / 180,
1026
- cad_component.rotation.z * Math.PI / 180
1027
- ) : void 0;
1028
- if (url) {
1029
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1030
- MixedStlModel,
1031
- {
1032
- url,
1033
- position: cad_component.position ? [
1034
- cad_component.position.x,
1035
- cad_component.position.y,
1036
- cad_component.position.z
1037
- ] : void 0,
1038
- rotation: rotationOffset,
1039
- componentId: cad_component.cad_component_id,
1040
- name: componentName || cad_component.cad_component_id,
1041
- onHover: handleHover,
1042
- isHovered: hoveredComponent.id === cad_component.cad_component_id
1043
- },
1044
- cad_component.cad_component_id
1045
- );
1046
- }
1047
- if (cad_component.model_jscad) {
1048
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1049
- JscadModel,
1115
+ cad_components.map((cad_component) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1116
+ ThreeErrorBoundary,
1117
+ {
1118
+ fallback: ({ error }) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Error3d, { cad_component, error }),
1119
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1120
+ AnyCadComponent,
1050
1121
  {
1051
- jscadPlan: cad_component.model_jscad,
1052
- rotationOffset,
1053
- componentId: cad_component.cad_component_id,
1054
- name: componentName || cad_component.cad_component_id,
1055
- onHover: handleHover,
1056
- isHovered: hoveredComponent.id === cad_component.cad_component_id
1122
+ onHover: (e) => {
1123
+ if (!e) {
1124
+ setHoveredComponent(null);
1125
+ }
1126
+ if (!e.mousePosition) return;
1127
+ const componentName = (0, import_soup_util2.su)(soup).source_component.getUsing({
1128
+ source_component_id: cad_component.source_component_id
1129
+ })?.name;
1130
+ setHoveredComponent({
1131
+ cad_component_id: cad_component.cad_component_id,
1132
+ name: componentName ?? "<unknown>",
1133
+ mousePosition: e.mousePosition
1134
+ });
1135
+ },
1136
+ cad_component,
1137
+ isHovered: hoveredComponent?.cad_component_id === cad_component.cad_component_id
1057
1138
  },
1058
1139
  cad_component.cad_component_id
1059
- );
1060
- }
1061
- if (cad_component.footprinter_string) {
1062
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1063
- FootprinterModel,
1064
- {
1065
- positionOffset: cad_component.position ? [
1066
- cad_component.position.x,
1067
- cad_component.position.y,
1068
- cad_component.position.z
1069
- ] : void 0,
1070
- rotationOffset,
1071
- footprint: cad_component.footprinter_string,
1072
- componentId: cad_component.cad_component_id,
1073
- name: componentName || cad_component.cad_component_id,
1074
- onHover: handleHover,
1075
- isHovered: hoveredComponent.id === cad_component.cad_component_id
1076
- }
1077
- );
1078
- }
1079
- })
1140
+ )
1141
+ },
1142
+ cad_component.cad_component_id
1143
+ ))
1080
1144
  ] });
1081
1145
  };
1082
1146
  // Annotate the CommonJS export names for ESM import in node:
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.tsx","../src/hooks/use-convert-children-to-soup.ts","../src/CadViewer.tsx","../src/soup-to-3d/index.ts","../src/geoms/plated-hole.ts","../src/geoms/constants.ts","../src/geoms/create-board-with-outline.ts","../src/hooks/use-stls-from-geom.ts","../src/three-components/STLModel.tsx","../src/CadViewerContainer.tsx","../package.json","../src/three-components/cube-with-labeled-sides.tsx","../src/ContainerWithTooltip.tsx","../src/hooks/use-global-obj-loader.ts","../src/three-components/MixedStlModel.tsx","../src/three-components/JscadModel.tsx","../src/three-components/FootprinterModel.tsx","../src/utils/tuple.ts"],"sourcesContent":["export { CadViewer } from \"./CadViewer\"\n","import { Circuit } from \"@tscircuit/core\"\nimport { useMemo } from \"react\"\nimport type { AnyCircuitElement } from \"circuit-json\"\n\nexport const useConvertChildrenToSoup = (\n children?: any,\n defaultSoup?: AnyCircuitElement[],\n): AnyCircuitElement[] => {\n return useMemo(() => {\n if (!children) return\n const circuit = new Circuit()\n circuit.add(children)\n circuit.render()\n return circuit.getCircuitJson() as any\n }, [children])\n}\n","import type { AnySoupElement } from \"@tscircuit/soup\"\nimport { useConvertChildrenToSoup } from \"./hooks/use-convert-children-to-soup\"\nimport { su } from \"@tscircuit/soup-util\"\nimport { useMemo, useState } from \"react\"\nimport { createBoardGeomFromSoup } from \"./soup-to-3d\"\nimport { useStlsFromGeom } from \"./hooks/use-stls-from-geom\"\nimport { STLModel } from \"./three-components/STLModel\"\nimport { CadViewerContainer } from \"./CadViewerContainer\"\nimport { MixedStlModel } from \"./three-components/MixedStlModel\"\nimport { Euler } from \"three\"\nimport { JscadModel } from \"./three-components/JscadModel\"\nimport { Footprinter3d } from \"jscad-electronics\"\nimport { FootprinterModel } from \"./three-components/FootprinterModel\"\nimport { tuple } from \"./utils/tuple\"\n\ninterface Props {\n soup?: AnySoupElement[]\n children?: any\n}\n\nexport const CadViewer = ({ soup, children }: Props) => {\n const [hoveredComponent, setHoveredComponent] = useState<{\n id: string | null\n name: string | null\n mousePosition: [number, number, number] | null\n }>({\n id: null,\n name: null,\n mousePosition: null,\n })\n soup ??= useConvertChildrenToSoup(children, soup) as any\n\n if (!soup) return null\n\n const boardGeom = useMemo(() => {\n if (!soup.some((e) => e.type === \"pcb_board\")) return null\n return createBoardGeomFromSoup(soup)\n }, [soup])\n\n const { stls, loading } = useStlsFromGeom(boardGeom)\n\n const cad_components = su(soup).cad_component.list()\n\n const handleHover = (\n componentId: string | null,\n componentName?: string,\n mousePosition?: [number, number, number],\n ) => {\n setHoveredComponent({\n id: componentId,\n name: componentName || null,\n mousePosition: mousePosition || null,\n })\n }\n\n return (\n <CadViewerContainer hoveredComponent={hoveredComponent}>\n {stls.map(({ stlUrl, color }, index) => (\n <STLModel\n key={stlUrl}\n stlUrl={stlUrl}\n color={color}\n opacity={index === 0 ? 0.95 : 1}\n />\n ))}\n {cad_components.map((cad_component) => {\n const componentName = su(soup).source_component.getUsing({\n source_component_id: cad_component.source_component_id,\n })?.name\n const url = cad_component.model_obj_url ?? cad_component.model_stl_url\n const rotationOffset = cad_component.rotation\n ? tuple(\n (cad_component.rotation.x * Math.PI) / 180,\n (cad_component.rotation.y * Math.PI) / 180,\n (cad_component.rotation.z * Math.PI) / 180,\n )\n : undefined\n\n if (url) {\n return (\n <MixedStlModel\n key={cad_component.cad_component_id}\n url={url}\n position={\n cad_component.position\n ? [\n cad_component.position.x,\n cad_component.position.y,\n cad_component.position.z,\n ]\n : undefined\n }\n rotation={rotationOffset}\n componentId={cad_component.cad_component_id}\n name={componentName || cad_component.cad_component_id}\n onHover={handleHover}\n isHovered={hoveredComponent.id === cad_component.cad_component_id}\n />\n )\n }\n\n if (cad_component.model_jscad) {\n return (\n <JscadModel\n key={cad_component.cad_component_id}\n jscadPlan={cad_component.model_jscad as any}\n rotationOffset={rotationOffset}\n componentId={cad_component.cad_component_id}\n name={componentName || cad_component.cad_component_id}\n onHover={handleHover}\n isHovered={hoveredComponent.id === cad_component.cad_component_id}\n />\n )\n }\n\n if (cad_component.footprinter_string) {\n return (\n <FootprinterModel\n positionOffset={\n cad_component.position\n ? [\n cad_component.position.x,\n cad_component.position.y,\n cad_component.position.z,\n ]\n : undefined\n }\n rotationOffset={rotationOffset}\n footprint={cad_component.footprinter_string}\n componentId={cad_component.cad_component_id}\n name={componentName || cad_component.cad_component_id}\n onHover={handleHover}\n isHovered={hoveredComponent.id === cad_component.cad_component_id}\n />\n )\n }\n })}\n </CadViewerContainer>\n )\n}\n","import type { Geom3 } from \"@jscad/modeling/src/geometries/types\"\nimport type { AnySoupElement, PCBPlatedHole } from \"@tscircuit/soup\"\nimport { su } from \"@tscircuit/soup-util\"\nimport { translate } from \"@jscad/modeling/src/operations/transforms\"\nimport { cuboid, cylinder, line } from \"@jscad/modeling/src/primitives\"\nimport { colorize } from \"@jscad/modeling/src/colors\"\nimport { subtract, union } from \"@jscad/modeling/src/operations/booleans\"\nimport { platedHole } from \"../geoms/plated-hole\"\nimport { M, colors } from \"../geoms/constants\"\nimport { extrudeLinear } from \"@jscad/modeling/src/operations/extrusions\"\nimport { expand } from \"@jscad/modeling/src/operations/expansions\"\nimport { createBoardWithOutline } from \"src/geoms/create-board-with-outline\"\n\nexport const createBoardGeomFromSoup = (soup: AnySoupElement[]): Geom3[] => {\n const board = su(soup).pcb_board.list()[0]\n if (!board) {\n throw new Error(\"No pcb_board found\")\n }\n const plated_holes = su(soup).pcb_plated_hole.list()\n const holes = su(soup).pcb_hole.list()\n const pads = su(soup).pcb_smtpad.list()\n const traces = su(soup).pcb_trace.list()\n const pcb_vias = su(soup).pcb_via.list()\n\n // PCB Board\n let boardGeom: Geom3\n if (board.outline && board.outline.length > 0)\n boardGeom = createBoardWithOutline(board.outline, 1.2)\n else boardGeom = cuboid({ size: [board.width, board.height, 1.2] })\n\n const platedHoleGeoms: Geom3[] = []\n const holeGeoms: Geom3[] = []\n const padGeoms: Geom3[] = []\n const traceGeoms: Geom3[] = []\n const ctx = {\n pcbThickness: 1.2,\n }\n\n const addPlatedHole = (plated_hole: PCBPlatedHole) => {\n if (plated_hole.shape === \"circle\") {\n const cyGeom = cylinder({\n center: [plated_hole.x, plated_hole.y, 0],\n radius: plated_hole.hole_diameter / 2 + M,\n })\n\n boardGeom = subtract(boardGeom, cyGeom)\n\n const platedHoleGeom = platedHole(plated_hole, ctx)\n platedHoleGeoms.push(platedHoleGeom)\n } else if (plated_hole.shape === \"pill\") {\n const shouldRotate = plated_hole.hole_height! > plated_hole.hole_width!\n\n const holeWidth = shouldRotate\n ? plated_hole.hole_height!\n : plated_hole.hole_width!\n const holeHeight = shouldRotate\n ? plated_hole.hole_width!\n : plated_hole.hole_height!\n\n const holeRadius = holeHeight / 2\n const rectLength = Math.abs(holeWidth - holeHeight)\n\n const pillHole = union(\n cuboid({\n center: [plated_hole.x, plated_hole.y, 0],\n size: shouldRotate\n ? [holeHeight, rectLength, 1.5]\n : [rectLength, holeHeight, 1.5],\n }),\n cylinder({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y - rectLength / 2, 0]\n : [plated_hole.x - rectLength / 2, plated_hole.y, 0],\n radius: holeRadius,\n height: 1.5,\n }),\n cylinder({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y + rectLength / 2, 0]\n : [plated_hole.x + rectLength / 2, plated_hole.y, 0],\n radius: holeRadius,\n height: 1.5,\n }),\n )\n boardGeom = subtract(boardGeom, pillHole)\n\n const platedHoleGeom = platedHole(plated_hole, ctx)\n platedHoleGeoms.push(platedHoleGeom)\n }\n }\n\n for (const plated_hole of plated_holes) {\n addPlatedHole(plated_hole)\n }\n\n for (const hole of holes) {\n // @ts-expect-error\n if (hole.hole_shape === \"round\" || hole.hole_shape === \"circle\") {\n const cyGeom = cylinder({\n center: [hole.x, hole.y, 0],\n radius: hole.hole_diameter / 2 + M,\n })\n boardGeom = subtract(boardGeom, cyGeom)\n }\n }\n\n for (const pad of pads) {\n const layerSign = pad.layer === \"bottom\" ? -1 : 1\n if (pad.shape === \"rect\") {\n const padGeom = colorize(\n colors.copper,\n cuboid({\n center: [pad.x, pad.y, (layerSign * 1.2) / 2 + layerSign * M],\n size: [pad.width, pad.height, M],\n }),\n )\n padGeoms.push(padGeom)\n } else if (pad.shape === \"circle\") {\n const padGeom = colorize(\n colors.copper,\n cylinder({\n center: [pad.x, pad.y, (layerSign * 1.2) / 2 + layerSign * M],\n radius: pad.radius,\n height: M,\n }),\n )\n padGeoms.push(padGeom)\n }\n }\n\n for (const { route: mixedRoute } of traces) {\n if (mixedRoute.length < 2) continue\n\n // Group routes by continuous segments\n const routeSegments: (typeof mixedRoute)[] = []\n let currentSegment: typeof mixedRoute = [mixedRoute[0]!]\n let currentLayer =\n mixedRoute[0]!.route_type === \"wire\" ? mixedRoute[0]!.layer : \"top\"\n\n for (let i = 1; i < mixedRoute.length; i++) {\n const point = mixedRoute[i]!\n\n if (point.route_type === \"via\") {\n // Complete current segment and start a new one\n routeSegments.push(currentSegment)\n currentSegment = [point]\n } else if (point.route_type === \"wire\" && point.layer !== currentLayer) {\n // Complete current segment and start a new one on a different layer\n routeSegments.push(currentSegment)\n currentLayer = point.layer\n currentSegment = [point]\n } else {\n currentSegment.push(point)\n }\n }\n\n // Add the last segment\n routeSegments.push(currentSegment)\n\n // Render each route segment\n for (const route of routeSegments) {\n if (route.length < 2) continue\n\n const linePath = line(route.map((p) => [p.x, p.y]))\n const layerSign =\n route[0]!.route_type === \"via\"\n ? route[0]!.to_layer === \"top\"\n ? 1\n : -1\n : route[0]!.layer === \"top\"\n ? 1\n : -1\n\n let traceGeom = translate(\n [0, 0, (layerSign * 1.2) / 2],\n extrudeLinear(\n { height: M * layerSign },\n expand({ delta: 0.1, corners: \"edge\" }, linePath),\n ),\n )\n\n // Modify via subtraction to preserve trace geometry\n const viaSubtractions = pcb_vias.map((via) =>\n cylinder({\n center: [via.x, via.y, 0],\n radius: via.outer_diameter / 2,\n height: 5,\n }),\n )\n\n const holeSubtractions = plated_holes\n .filter((ph) => ph.shape === \"circle\")\n .map((ph) =>\n cylinder({\n center: [ph.x, ph.y, 0],\n radius: ph.outer_diameter / 2,\n height: 5,\n }),\n )\n\n // Subtract vias and holes without removing entire trace\n traceGeom = subtract(traceGeom, ...viaSubtractions, ...holeSubtractions)\n\n traceGeom = colorize(colors.fr4GreenSolderWithMask, traceGeom)\n\n traceGeoms.push(traceGeom)\n }\n }\n\n for (const via of pcb_vias) {\n addPlatedHole({\n x: via.x,\n y: via.y,\n hole_diameter: via.hole_diameter,\n outer_diameter: via.outer_diameter,\n shape: \"circle\",\n layers: [\"top\", \"bottom\"],\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: \"\",\n })\n }\n\n // Colorize to a PCB green color: #05A32E\n boardGeom = colorize(colors.fr4Green, boardGeom)\n\n return [boardGeom, ...platedHoleGeoms, ...padGeoms, ...traceGeoms]\n}\n","import type { PCBPlatedHole } from \"@tscircuit/soup\"\nimport type { Geom3 } from \"@jscad/modeling/src/geometries/types\"\nimport { cuboid, cylinder } from \"@jscad/modeling/src/primitives\"\nimport { colorize } from \"@jscad/modeling/src/colors\"\nimport { subtract, union } from \"@jscad/modeling/src/operations/booleans\"\nimport { M, colors } from \"./constants\"\nimport type { GeomContext } from \"../GeomContext\"\n\nexport const platedHole = (\n plated_hole: PCBPlatedHole,\n ctx: GeomContext,\n): Geom3 => {\n if (!(plated_hole as PCBPlatedHole).shape) plated_hole.shape = \"circle\"\n if (plated_hole.shape === \"circle\") {\n return colorize(\n colors.copper,\n subtract(\n union(\n cylinder({\n center: [plated_hole.x, plated_hole.y, 0],\n radius: plated_hole.hole_diameter / 2,\n height: 1.2,\n }),\n cylinder({\n center: [plated_hole.x, plated_hole.y, 1.2 / 2],\n radius: plated_hole.outer_diameter / 2,\n height: M,\n }),\n cylinder({\n center: [plated_hole.x, plated_hole.y, -1.2 / 2],\n radius: plated_hole.outer_diameter / 2,\n height: M,\n }),\n ),\n cylinder({\n center: [plated_hole.x, plated_hole.y, 0],\n radius: plated_hole.hole_diameter / 2 - M,\n height: 1.5,\n }),\n ),\n )\n }\n if (plated_hole.shape === \"pill\") {\n const shouldRotate = plated_hole.hole_height! > plated_hole.hole_width!\n\n const holeWidth = shouldRotate\n ? plated_hole.hole_height!\n : plated_hole.hole_width!\n const holeHeight = shouldRotate\n ? plated_hole.hole_width!\n : plated_hole.hole_height!\n const outerHeight = shouldRotate\n ? plated_hole.outer_width || holeWidth + 0.2\n : plated_hole.outer_height || holeHeight + 0.2\n\n const holeRadius = holeHeight / 2\n const rectLength = Math.abs(holeWidth - holeHeight)\n\n const mainRect = cuboid({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y, 0]\n : [plated_hole.x, plated_hole.y, 0],\n size: shouldRotate\n ? [holeHeight, rectLength, 1.2]\n : [rectLength, holeHeight, 1.2],\n })\n\n const leftCap = cylinder({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y - rectLength / 2, 0]\n : [plated_hole.x - rectLength / 2, plated_hole.y, 0],\n radius: holeRadius,\n height: 1.2,\n })\n\n const rightCap = cylinder({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y + rectLength / 2, 0]\n : [plated_hole.x + rectLength / 2, plated_hole.y, 0],\n radius: holeRadius,\n height: 1.2,\n })\n\n const outerMainRect = cuboid({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y, 1.2 / 2]\n : [plated_hole.x, plated_hole.y, 1.2 / 2],\n size: shouldRotate\n ? [outerHeight, rectLength, M]\n : [rectLength, outerHeight, M],\n })\n\n const outerLeftCap = cylinder({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y - rectLength / 2, 1.2 / 2]\n : [plated_hole.x - rectLength / 2, plated_hole.y, 1.2 / 2],\n radius: outerHeight / 2,\n height: M,\n })\n\n const outerRightCap = cylinder({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y + rectLength / 2, 1.2 / 2]\n : [plated_hole.x + rectLength / 2, plated_hole.y, 1.2 / 2],\n radius: outerHeight / 2,\n height: M,\n })\n\n const bottomMainRect = cuboid({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y, -1.2 / 2]\n : [plated_hole.x, plated_hole.y, -1.2 / 2],\n size: shouldRotate\n ? [outerHeight, rectLength, M]\n : [rectLength, outerHeight, M],\n })\n\n const bottomLeftCap = cylinder({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y - rectLength / 2, -1.2 / 2]\n : [plated_hole.x - rectLength / 2, plated_hole.y, -1.2 / 2],\n radius: outerHeight / 2,\n height: M,\n })\n\n const bottomRightCap = cylinder({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y + rectLength / 2, -1.2 / 2]\n : [plated_hole.x + rectLength / 2, plated_hole.y, -1.2 / 2],\n radius: outerHeight / 2,\n height: M,\n })\n return colorize(\n colors.copper,\n subtract(\n union(\n mainRect,\n leftCap,\n rightCap,\n outerMainRect,\n outerLeftCap,\n outerRightCap,\n bottomMainRect,\n bottomLeftCap,\n bottomRightCap,\n ),\n union(\n cuboid({\n center: [plated_hole.x, plated_hole.y, 0],\n size: shouldRotate\n ? [holeHeight - M, rectLength, 1.5]\n : [rectLength, holeHeight - M, 1.5],\n }),\n cylinder({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y - rectLength / 2, 0]\n : [plated_hole.x - rectLength / 2, plated_hole.y, 0],\n radius: holeRadius - M,\n height: 1.5,\n }),\n cylinder({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y + rectLength / 2, 0]\n : [plated_hole.x + rectLength / 2, plated_hole.y, 0],\n radius: holeRadius - M,\n height: 1.5,\n }),\n ),\n ),\n )\n // biome-ignore lint/style/noUselessElse: <explanation>\n } else {\n throw new Error(`Unsupported plated hole shape: ${plated_hole.shape}`)\n }\n}\n","import type { RGB } from \"@jscad/modeling/src/colors\"\n\nexport const M = 0.01\n\nexport const colors = {\n copper: [0.9, 0.6, 0.2],\n fr4Green: [0x05 / 255, 0xa3 / 255, 0x2e / 255],\n fr4GreenSolderWithMask: [0x00 / 255, 0x98 / 255, 0x13 / 255],\n} satisfies Record<string, RGB>\n","import { extrudeLinear } from \"@jscad/modeling/src/operations/extrusions\"\nimport { polygon } from \"@jscad/modeling/src/primitives\"\nimport type { Geom2, Geom3 } from \"@jscad/modeling/src/geometries/types\"\nimport type { Vec2 } from \"@jscad/modeling/src/maths/types\"\nimport type { Point } from \"@tscircuit/soup\"\nimport { translate } from \"@jscad/modeling/src/operations/transforms\"\n\nconst arePointsClockwise = (points: Vec2[]): boolean => {\n let area = 0\n for (let i = 0; i < points.length; i++) {\n const j = (i + 1) % points.length\n area += points[i]![0] * points[j]![1]\n area -= points[j]![0] * points[i]![1]\n }\n const signedArea = area / 2\n return signedArea <= 0\n}\n\nexport const createBoardWithOutline = (points: Point[], depth = 1.2): Geom3 => {\n let outline: Vec2[] = points.map((point) => [point.x, point.y])\n\n if (arePointsClockwise(outline)) {\n outline = outline.reverse()\n }\n\n const shape: Geom2 = polygon({ points: outline })\n\n let board: Geom3 = extrudeLinear({ height: depth }, shape)\n\n board = translate([0, 0, -depth / 2], board)\n\n return board\n}\n","import { useState, useEffect } from \"react\"\nimport stlSerializer from \"@jscad/stl-serializer\"\nimport { Geom3 } from \"@jscad/modeling/src/geometries/types\"\n\nfunction blobToBase64Url(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => {\n resolve(reader.result as string)\n }\n reader.onerror = reject\n reader.readAsDataURL(blob)\n })\n}\n\ntype StlObj = { stlUrl: string; color: number[] }\n\nexport const useStlsFromGeom = (\n geom: Geom3[] | Geom3 | null,\n): {\n stls: StlObj[]\n loading: boolean\n} => {\n const [stls, setStls] = useState<StlObj[]>([])\n const [loading, setLoading] = useState(true)\n\n useEffect(() => {\n if (!geom) return\n const generateStls = async () => {\n setLoading(true)\n const geometries = Array.isArray(geom) ? geom : [geom]\n\n const stlPromises = geometries.map(async (g) => {\n const rawData = stlSerializer.serialize({ binary: true }, [g])\n const blobData = new Blob(rawData)\n const stlUrl = await blobToBase64Url(blobData)\n return { stlUrl, color: g.color! }\n })\n\n try {\n const generatedStls = await Promise.all(stlPromises)\n setStls(generatedStls)\n } catch (error) {\n console.error(\"Error generating STLs:\", error)\n setStls([])\n } finally {\n setLoading(false)\n }\n }\n\n generateStls()\n }, [geom])\n\n return { stls, loading }\n}\n","import { useLoader } from \"@react-three/fiber\"\nimport { useRef } from \"react\"\nimport * as THREE from \"three\"\nimport { MTLLoader, OBJLoader, STLLoader } from \"three-stdlib\"\n\nexport function STLModel({\n stlUrl,\n mtlUrl,\n color,\n opacity = 1,\n}: {\n stlUrl: string\n color?: any\n mtlUrl?: string\n opacity?: number\n}) {\n const geom = useLoader(STLLoader, stlUrl)\n const mesh = useRef<THREE.Mesh>()\n\n // TODO handle mtl url\n\n return (\n <mesh ref={mesh as any}>\n <primitive object={geom} attach=\"geometry\" />\n <meshStandardMaterial\n color={color}\n transparent={opacity !== 1}\n opacity={opacity}\n />\n {/* <Outlines thickness={0.05} color=\"black\" opacity={0.25} /> */}\n </mesh>\n )\n}\n","import { Grid, OrbitControls } from \"@react-three/drei\"\nimport { Canvas, useFrame } from \"@react-three/fiber\"\nimport packageJson from \"../package.json\"\nimport { CubeWithLabeledSides } from \"./three-components/cube-with-labeled-sides\"\n\nexport const RotationTracker = () => {\n useFrame(({ camera }) => {\n window.TSCI_MAIN_CAMERA_ROTATION = camera.rotation\n })\n\n return <></>\n}\n\nimport { Html } from \"@react-three/drei\"\n\nexport const CadViewerContainer = ({\n children,\n hoveredComponent,\n}: {\n children: any\n hoveredComponent: {\n id: string | null\n name: string | null\n mousePosition: [number, number, number] | null\n }\n}) => {\n return (\n <div style={{ position: \"relative\", width: \"100%\", height: \"100%\" }}>\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: 120,\n height: 120,\n }}\n >\n <Canvas\n camera={{\n up: [0, 0, 1],\n position: [1, 1, 1],\n }}\n style={{ zIndex: 10 }}\n >\n <ambientLight intensity={Math.PI / 2} />\n <CubeWithLabeledSides />\n </Canvas>\n </div>\n <Canvas\n scene={{ up: [0, 0, 1] }}\n camera={{ up: [0, 0, 1], position: [5, 5, 5] }}\n >\n <RotationTracker />\n <OrbitControls autoRotate autoRotateSpeed={1} />\n <ambientLight intensity={Math.PI / 2} />\n <pointLight\n position={[-10, -10, 10]}\n decay={0}\n intensity={Math.PI / 4}\n />\n <Grid\n rotation={[Math.PI / 2, 0, 0]}\n infiniteGrid={true}\n cellSize={1}\n sectionSize={10}\n />\n {children}\n {hoveredComponent.id && hoveredComponent.mousePosition && (\n <Html\n position={hoveredComponent.mousePosition}\n style={{\n fontFamily: \"sans-serif\",\n transform: \"translate3d(50%, 50%, 0)\",\n backgroundColor: \"white\",\n padding: \"5px\",\n borderRadius: \"3px\",\n pointerEvents: \"none\",\n }}\n >\n {hoveredComponent.name}\n </Html>\n )}\n </Canvas>\n <div\n style={{\n position: \"absolute\",\n right: 24,\n bottom: 24,\n fontFamily: \"sans-serif\",\n color: \"white\",\n WebkitTextStroke: \"0.5px rgba(0, 0, 0, 0.5)\",\n fontSize: 11,\n }}\n >\n @{packageJson.version}\n </div>\n </div>\n )\n}\n","{\n \"name\": \"@tscircuit/3d-viewer\",\n \"version\": \"0.0.47\",\n \"main\": \"./dist/index.js\",\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"start\": \"bun run storybook\",\n \"dev:old\": \"bunx --bun vite\",\n \"build\": \"tsup ./src/index.tsx --dts --sourcemap\",\n \"prepublish\": \"npm run build\",\n \"preview\": \"vite preview\",\n \"storybook\": \"storybook dev -p 6006\",\n \"build-storybook\": \"storybook build\",\n \"format\": \"biome format . --write\"\n },\n \"dependencies\": {\n \"@jscad/modeling\": \"^2.12.2\",\n \"@jscad/regl-renderer\": \"^2.6.9\",\n \"@jscad/stl-serializer\": \"^2.1.17\",\n \"@react-three/drei\": \"^9.115.0\",\n \"@react-three/fiber\": \"^8.16.8\",\n \"@tscircuit/core\": \"^0.0.136\",\n \"@tscircuit/react-fiber\": \"^1.1.29\",\n \"@tscircuit/soup\": \"^0.0.69\",\n \"@tscircuit/soup-util\": \"^0.0.26\",\n \"@types/three\": \"^0.165.0\",\n \"jscad-electronics\": \"^0.0.22\",\n \"jscad-fiber\": \"^0.0.74\",\n \"jscad-planner\": \"^0.0.8\",\n \"react\": \"^18.3.1\",\n \"react-dom\": \"^18.3.1\",\n \"react-use-gesture\": \"^9.1.3\",\n \"three\": \"^0.165.0\",\n \"three-stdlib\": \"^2.30.3\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"^1.8.3\",\n \"@chromatic-com/storybook\": \"^1.5.0\",\n \"@storybook/addon-essentials\": \"^8.1.10\",\n \"@storybook/addon-interactions\": \"^8.1.10\",\n \"@storybook/addon-links\": \"^8.1.10\",\n \"@storybook/addon-onboarding\": \"^8.1.10\",\n \"@storybook/blocks\": \"^8.1.10\",\n \"@storybook/builder-vite\": \"^8.1.10\",\n \"@storybook/react\": \"^8.1.10\",\n \"@storybook/react-vite\": \"^8.1.10\",\n \"@storybook/test\": \"^8.1.10\",\n \"@types/react\": \"^18.3.3\",\n \"@types/react-dom\": \"^18.3.0\",\n \"@vitejs/plugin-react\": \"^4.3.1\",\n \"circuit-json\": \"^0.0.77\",\n \"storybook\": \"^8.1.10\",\n \"strip-ansi\": \"^7.1.0\",\n \"tsup\": \"^8.1.0\",\n \"typescript\": \"^5.5.3\",\n \"vite\": \"^5.3.1\",\n \"vite-tsconfig-paths\": \"^4.3.2\"\n }\n}\n","import { Text } from \"@react-three/drei\"\nimport { useFrame } from \"@react-three/fiber\"\nimport { useRef } from \"react\"\nimport * as THREE from \"three\"\n\ndeclare global {\n interface Window {\n TSCI_MAIN_CAMERA_ROTATION: THREE.Euler\n }\n}\nif (typeof window !== \"undefined\") {\n window.TSCI_MAIN_CAMERA_ROTATION = new THREE.Euler(0, 0, 0)\n}\n\nfunction computePointInFront(rotationVector, distance) {\n // Create a quaternion from the rotation vector\n const quaternion = new THREE.Quaternion().setFromEuler(\n new THREE.Euler(rotationVector.x, rotationVector.y, rotationVector.z),\n )\n\n // Create a vector pointing forward (along the negative z-axis)\n const forwardVector = new THREE.Vector3(0, 0, 1)\n\n // Apply the rotation to the forward vector\n forwardVector.applyQuaternion(quaternion)\n\n // Scale the rotated vector by the distance\n const result = forwardVector.multiplyScalar(distance)\n\n return result\n}\n\nexport const CubeWithLabeledSides = ({}: any) => {\n const ref = useRef<THREE.Mesh>()\n const rotationTrackingRef = useRef({ lastRotation: new THREE.Euler() })\n useFrame((state, delta) => {\n if (!ref.current) return\n\n const mainRot = window.TSCI_MAIN_CAMERA_ROTATION\n\n // Use window.TSCI_CAMERA_ROTATION to compute the position of the camera\n const cameraPosition = computePointInFront(mainRot, 2)\n\n state.camera.position.copy(cameraPosition)\n state.camera.lookAt(0, 0, 0)\n })\n return (\n <mesh ref={ref as any} rotation={[Math.PI / 2, 0, 0]}>\n <boxGeometry args={[1, 1, 1]} />\n <meshStandardMaterial color=\"white\" />\n <Text position={[0, 0, 0.51]} fontSize={0.25} color=\"black\">\n Front\n </Text>\n <Text\n position={[0, 0, -0.51]}\n fontSize={0.25}\n color=\"black\"\n rotation={[0, Math.PI, 0]}\n >\n Back\n </Text>\n <Text\n position={[0.51, 0, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[0, Math.PI / 2, 0]}\n >\n Right\n </Text>\n <Text\n position={[-0.51, 0, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[0, -Math.PI / 2, 0]}\n >\n Left\n </Text>\n <Text\n position={[0, 0.51, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[-Math.PI / 2, 0, 0]}\n >\n Top\n </Text>\n <Text\n position={[0, -0.51, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[Math.PI / 2, 0, 0]}\n >\n Bottom\n </Text>\n <lineSegments\n args={[new THREE.EdgesGeometry(new THREE.BoxGeometry(1, 1, 1))]}\n material={\n new THREE.LineBasicMaterial({\n color: 0x000000,\n linewidth: 2,\n })\n }\n />\n </mesh>\n )\n}\n","import { Html } from \"@react-three/drei\"\nimport { GroupProps, useThree } from \"@react-three/fiber\"\nimport { useRef, useCallback } from \"react\"\nimport type { Vector3 } from \"three\"\nimport * as THREE from \"three\"\n\nconst ContainerWithTooltip = ({\n children,\n isHovered,\n onHover,\n componentId,\n name,\n position,\n}: {\n children: React.ReactNode\n componentId: string\n name: string\n position?: Vector3 | [number, number, number]\n onHover: (\n id: string | null,\n name?: string,\n mousePosition?: [number, number, number],\n ) => void\n isHovered: boolean\n}) => {\n const lastValidPointRef = useRef<THREE.Vector3 | null>(null)\n\n const handlePointerEnter = useCallback(\n (e: any) => {\n e.stopPropagation()\n\n try {\n // Fallback to event position if raycaster fails\n const point =\n e.point ||\n (e.intersections && e.intersections.length > 0\n ? e.intersections[0].point\n : null) ||\n (position\n ? new THREE.Vector3(...(position as [number, number, number]))\n : null)\n\n if (point) {\n lastValidPointRef.current = point\n onHover(componentId, name, [point.x, point.y, point.z])\n } else {\n onHover(componentId, name)\n }\n } catch (error) {\n console.warn(\"Hover event error:\", error)\n onHover(componentId, name)\n }\n },\n [componentId, name, onHover, position],\n )\n\n const handlePointerLeave = useCallback(\n (e: any) => {\n e.stopPropagation()\n lastValidPointRef.current = null\n onHover(null)\n },\n [onHover],\n )\n\n const groupProps: GroupProps = {\n onPointerEnter: handlePointerEnter,\n onPointerMove: handlePointerEnter,\n onPointerLeave: handlePointerLeave,\n }\n\n return <group {...groupProps}>{children}</group>\n}\n\nexport default ContainerWithTooltip\n","import { useState, useEffect } from \"react\"\nimport type { Group } from \"three\"\nimport { MTLLoader, OBJLoader } from \"three-stdlib\"\n\n// Define the type for our cache\ninterface CacheItem {\n promise: Promise<any>\n result: Group | null\n}\n\ndeclare global {\n interface Window {\n TSCIRCUIT_OBJ_LOADER_CACHE: Map<string, CacheItem>\n }\n}\n\n// Ensure the global cache exists\nif (typeof window !== \"undefined\" && !window.TSCIRCUIT_OBJ_LOADER_CACHE) {\n window.TSCIRCUIT_OBJ_LOADER_CACHE = new Map<string, CacheItem>()\n}\n\nexport function useGlobalObjLoader(url: string | null): Group | null | Error {\n const [obj, setObj] = useState<Group | null | Error>(null)\n\n useEffect(() => {\n if (!url) return\n\n const cache = window.TSCIRCUIT_OBJ_LOADER_CACHE\n let hasUrlChanged = false\n\n async function loadAndParseObj() {\n try {\n const response = await fetch(url!)\n const text = await response.text()\n\n const mtlContent = text\n .match(/newmtl[\\s\\S]*?endmtl/g)\n ?.join(\"\\n\")!\n .replace(/d 0\\./g, \"d 1.\")!\n const objContent = text.replace(/newmtl[\\s\\S]*?endmtl/g, \"\")\n\n const mtlLoader = new MTLLoader()\n mtlLoader.setMaterialOptions({\n invertTrProperty: true,\n })\n const materials = mtlLoader.parse(\n mtlContent.replace(\n /Kd\\s+([\\d.]+)\\s+([\\d.]+)\\s+([\\d.]+)/g,\n \"Kd $2 $2 $2\",\n ),\n \"test.mtl\",\n )\n\n const objLoader = new OBJLoader()\n objLoader.setMaterials(materials)\n return objLoader.parse(objContent)\n } catch (error) {\n return error as Error\n }\n }\n\n function loadUrl() {\n if (cache.has(url!)) {\n const cacheItem = cache.get(url!)!\n if (cacheItem.result) {\n // If we have a result, clone it\n return Promise.resolve(cacheItem.result.clone())\n }\n // If we're still loading, return the existing promise\n return cacheItem.promise.then((result) => result.clone())\n }\n // If it's not in the cache, create a new promise and cache it\n const promise = loadAndParseObj().then((result) => {\n if (result instanceof Error) {\n // If the result is an Error, return it\n return result\n }\n cache.set(url!, { ...cache.get(url!)!, result })\n return result\n })\n cache.set(url!, { promise, result: null })\n return promise\n }\n\n loadUrl()\n .then((result) => {\n if (hasUrlChanged) return\n setObj(result)\n })\n .catch((error) => {\n console.error(error)\n })\n\n return () => {\n hasUrlChanged = true\n }\n }, [url])\n\n return obj\n}\n","import ContainerWithTooltip from \"src/ContainerWithTooltip\"\nimport { useGlobalObjLoader } from \"src/hooks/use-global-obj-loader\"\nimport type { Euler, Vector3 } from \"three\"\n\nexport function MixedStlModel({\n url,\n position,\n rotation,\n componentId,\n name,\n onHover,\n isHovered,\n}: {\n url: string\n position?: Vector3 | [number, number, number]\n rotation?: Euler | [number, number, number]\n componentId: string\n name: string\n onHover: (id: string | null) => void\n isHovered: boolean\n}) {\n const obj = useGlobalObjLoader(url)\n\n if (!obj) {\n return (\n <ContainerWithTooltip\n componentId={componentId}\n name={name}\n isHovered={isHovered}\n onHover={onHover}\n >\n <mesh position={position}>\n <boxGeometry args={[0.5, 0.5, 0.5]} />\n <meshStandardMaterial transparent color=\"red\" opacity={0.25} />\n </mesh>\n </ContainerWithTooltip>\n )\n }\n\n // Check if obj is valid before rendering\n if (obj instanceof Error) {\n return (\n <ContainerWithTooltip\n componentId={componentId}\n name={name}\n isHovered={isHovered}\n onHover={onHover}\n >\n <mesh position={position}>\n <boxGeometry args={[0.5, 0.5, 0.5]} />\n <meshStandardMaterial transparent color=\"red\" opacity={0.5} />\n <meshBasicMaterial color=\"red\" />\n </mesh>\n </ContainerWithTooltip>\n )\n }\n return (\n <ContainerWithTooltip\n componentId={componentId}\n name={name}\n isHovered={isHovered}\n onHover={onHover}\n >\n <primitive rotation={rotation} position={position} object={obj} />\n </ContainerWithTooltip>\n )\n}\n","import type { JscadOperation } from \"jscad-planner\"\nimport { executeJscadOperations } from \"jscad-planner\"\nimport jscad from \"@jscad/modeling\"\nimport { convertCSGToThreeGeom } from \"jscad-fiber\"\nimport * as THREE from \"three\"\nimport { useMemo } from \"react\"\nimport ContainerWithTooltip from \"src/ContainerWithTooltip\"\n\nexport const JscadModel = ({\n jscadPlan,\n positionOffset,\n rotationOffset,\n componentId,\n name,\n onHover,\n isHovered,\n}: {\n jscadPlan: JscadOperation\n positionOffset?: [number, number, number]\n rotationOffset?: [number, number, number]\n componentId: string\n name: string\n onHover: (id: string | null) => void\n isHovered: boolean\n}) => {\n const { threeGeom, material } = useMemo(() => {\n const jscadObject = executeJscadOperations(jscad as any, jscadPlan)\n\n const threeGeom = convertCSGToThreeGeom(jscadObject)\n\n const material = new THREE.MeshStandardMaterial({\n vertexColors: true,\n side: THREE.DoubleSide, // Ensure both sides are visible\n })\n return { threeGeom, material }\n }, [jscadPlan])\n useMemo(() => {\n if (isHovered) {\n const color = new THREE.Color(material.color.getHex())\n material.emissive.copy(color)\n material.emissive.setRGB(0, 0, 1)\n material.emissiveIntensity = 0.2\n } else {\n material.emissiveIntensity = 0\n }\n }, [isHovered, material])\n if (!threeGeom) return null\n\n return (\n <ContainerWithTooltip\n componentId={componentId}\n name={name}\n isHovered={isHovered}\n onHover={onHover}\n position={positionOffset}\n >\n <mesh\n geometry={threeGeom}\n material={material}\n position={positionOffset}\n rotation={rotationOffset}\n />\n </ContainerWithTooltip>\n )\n}\n","import { Footprinter3d } from \"jscad-electronics\"\nimport { createJSCADRenderer } from \"jscad-fiber\"\nimport { jscadPlanner } from \"jscad-planner\"\nimport { useMemo } from \"react\"\nimport { JscadModel } from \"./JscadModel\"\n\nconst { createJSCADRoot } = createJSCADRenderer(jscadPlanner as any)\n\nexport const FootprinterModel = ({\n positionOffset,\n footprint,\n rotationOffset,\n componentId,\n name,\n onHover,\n isHovered,\n}: {\n positionOffset: any\n footprint: string\n rotationOffset?: [number, number, number]\n componentId: string\n name: string\n onHover: (id: string | null) => void\n isHovered: boolean\n}) => {\n // biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>\n const jscadPlan = useMemo(() => {\n if (!footprint) return null\n const jscadPlan: any[] = []\n const root = createJSCADRoot(jscadPlan)\n root.render(<Footprinter3d footprint={footprint} />)\n return jscadPlan\n }, [footprint])\n\n if (!jscadPlan) return null\n\n return (\n <>\n {jscadPlan.map((plan, index) => (\n <JscadModel\n // biome-ignore lint/suspicious/noArrayIndexKey: <explanation>\n key={index}\n positionOffset={positionOffset}\n rotationOffset={rotationOffset}\n jscadPlan={plan}\n componentId={componentId}\n name={name}\n onHover={onHover}\n isHovered={isHovered}\n />\n ))}\n </>\n )\n}\n","export const tuple = <T extends any[]>(...args: T): T => args\n"],"mappings":"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","names":["import_soup_util","import_react","import_transforms","import_primitives","import_colors","import_booleans","import_extrusions","import_primitives","import_react","stlSerializer","import_react","import_drei","import_fiber","import_fiber","import_react","import_jsx_runtime","import_drei","import_jsx_runtime","import_react","THREE","import_jsx_runtime","import_react","import_three_stdlib","import_jsx_runtime","THREE","import_react","import_jsx_runtime","jscad","threeGeom","material","import_jscad_fiber","import_jscad_planner","import_react","import_jsx_runtime","jscadPlan","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../src/index.tsx","../src/hooks/use-convert-children-to-soup.ts","../src/CadViewer.tsx","../src/soup-to-3d/index.ts","../src/geoms/plated-hole.ts","../src/geoms/constants.ts","../src/geoms/create-board-with-outline.ts","../src/hooks/use-stls-from-geom.ts","../src/three-components/STLModel.tsx","../src/CadViewerContainer.tsx","../package.json","../src/three-components/cube-with-labeled-sides.tsx","../src/ContainerWithTooltip.tsx","../src/hooks/use-global-obj-loader.ts","../src/three-components/MixedStlModel.tsx","../src/three-components/JscadModel.tsx","../src/three-components/FootprinterModel.tsx","../src/utils/tuple.ts","../src/AnyCadComponent.tsx","../src/three-components/ThreeErrorBoundary.tsx","../src/three-components/Error3d.tsx"],"sourcesContent":["export { CadViewer } from \"./CadViewer\"\n","import { Circuit } from \"@tscircuit/core\"\nimport { useMemo } from \"react\"\nimport type { AnyCircuitElement } from \"circuit-json\"\n\nexport const useConvertChildrenToSoup = (\n children?: any,\n defaultSoup?: AnyCircuitElement[],\n): AnyCircuitElement[] => {\n return useMemo(() => {\n if (!children) return\n const circuit = new Circuit()\n circuit.add(children)\n circuit.render()\n return circuit.getCircuitJson() as any\n }, [children])\n}\n","import type { AnySoupElement } from \"@tscircuit/soup\"\nimport { useConvertChildrenToSoup } from \"./hooks/use-convert-children-to-soup\"\nimport { su } from \"@tscircuit/soup-util\"\nimport { useEffect, useMemo, useState } from \"react\"\nimport { createBoardGeomFromSoup } from \"./soup-to-3d\"\nimport { useStlsFromGeom } from \"./hooks/use-stls-from-geom\"\nimport { STLModel } from \"./three-components/STLModel\"\nimport { CadViewerContainer } from \"./CadViewerContainer\"\nimport { MixedStlModel } from \"./three-components/MixedStlModel\"\nimport { Euler } from \"three\"\nimport { JscadModel } from \"./three-components/JscadModel\"\nimport { Footprinter3d } from \"jscad-electronics\"\nimport { FootprinterModel } from \"./three-components/FootprinterModel\"\nimport { tuple } from \"./utils/tuple\"\nimport { AnyCadComponent } from \"./AnyCadComponent\"\nimport { Text } from \"@react-three/drei\"\nimport { ThreeErrorBoundary } from \"./three-components/ThreeErrorBoundary\"\nimport { Error3d } from \"./three-components/Error3d\"\n\ninterface Props {\n soup?: AnySoupElement[]\n children?: any\n}\n\nexport const CadViewer = ({ soup, children }: Props) => {\n const [hoveredComponent, setHoveredComponent] = useState<null | {\n cad_component_id: string\n name: string\n mousePosition: [number, number, number]\n }>(null)\n soup ??= useConvertChildrenToSoup(children, soup) as any\n\n if (!soup) return null\n\n const boardGeom = useMemo(() => {\n if (!soup.some((e) => e.type === \"pcb_board\")) return null\n return createBoardGeomFromSoup(soup)\n }, [soup])\n\n const { stls: boardStls, loading } = useStlsFromGeom(boardGeom)\n\n const cad_components = su(soup).cad_component.list()\n\n return (\n <CadViewerContainer hoveredComponent={hoveredComponent}>\n {boardStls.map(({ stlUrl, color }, index) => (\n <STLModel\n key={stlUrl}\n stlUrl={stlUrl}\n color={color}\n opacity={index === 0 ? 0.95 : 1}\n />\n ))}\n {cad_components.map((cad_component) => (\n <ThreeErrorBoundary\n key={cad_component.cad_component_id}\n fallback={({ error }) => (\n <Error3d cad_component={cad_component} error={error} />\n )}\n >\n <AnyCadComponent\n key={cad_component.cad_component_id}\n onHover={(e) => {\n // TODO this should be done by onUnhover\n if (!e) {\n setHoveredComponent(null)\n }\n if (!e.mousePosition) return\n\n const componentName = su(soup as any).source_component.getUsing({\n source_component_id: cad_component.source_component_id,\n })?.name\n setHoveredComponent({\n cad_component_id: cad_component.cad_component_id,\n name: componentName ?? \"<unknown>\",\n mousePosition: e.mousePosition,\n })\n }}\n cad_component={cad_component}\n isHovered={\n hoveredComponent?.cad_component_id ===\n cad_component.cad_component_id\n }\n />\n </ThreeErrorBoundary>\n ))}\n </CadViewerContainer>\n )\n}\n","import type { Geom3 } from \"@jscad/modeling/src/geometries/types\"\nimport type { AnySoupElement, PCBPlatedHole } from \"@tscircuit/soup\"\nimport { su } from \"@tscircuit/soup-util\"\nimport { translate } from \"@jscad/modeling/src/operations/transforms\"\nimport { cuboid, cylinder, line } from \"@jscad/modeling/src/primitives\"\nimport { colorize } from \"@jscad/modeling/src/colors\"\nimport { subtract, union } from \"@jscad/modeling/src/operations/booleans\"\nimport { platedHole } from \"../geoms/plated-hole\"\nimport { M, colors } from \"../geoms/constants\"\nimport { extrudeLinear } from \"@jscad/modeling/src/operations/extrusions\"\nimport { expand } from \"@jscad/modeling/src/operations/expansions\"\nimport { createBoardWithOutline } from \"src/geoms/create-board-with-outline\"\n\nexport const createBoardGeomFromSoup = (soup: AnySoupElement[]): Geom3[] => {\n const board = su(soup).pcb_board.list()[0]\n if (!board) {\n throw new Error(\"No pcb_board found\")\n }\n const plated_holes = su(soup).pcb_plated_hole.list()\n const holes = su(soup).pcb_hole.list()\n const pads = su(soup).pcb_smtpad.list()\n const traces = su(soup).pcb_trace.list()\n const pcb_vias = su(soup).pcb_via.list()\n\n // PCB Board\n let boardGeom: Geom3\n if (board.outline && board.outline.length > 0)\n boardGeom = createBoardWithOutline(board.outline, 1.2)\n else boardGeom = cuboid({ size: [board.width, board.height, 1.2] })\n\n const platedHoleGeoms: Geom3[] = []\n const holeGeoms: Geom3[] = []\n const padGeoms: Geom3[] = []\n const traceGeoms: Geom3[] = []\n const ctx = {\n pcbThickness: 1.2,\n }\n\n const addPlatedHole = (plated_hole: PCBPlatedHole) => {\n if (plated_hole.shape === \"circle\") {\n const cyGeom = cylinder({\n center: [plated_hole.x, plated_hole.y, 0],\n radius: plated_hole.hole_diameter / 2 + M,\n })\n\n boardGeom = subtract(boardGeom, cyGeom)\n\n const platedHoleGeom = platedHole(plated_hole, ctx)\n platedHoleGeoms.push(platedHoleGeom)\n } else if (plated_hole.shape === \"pill\") {\n const shouldRotate = plated_hole.hole_height! > plated_hole.hole_width!\n\n const holeWidth = shouldRotate\n ? plated_hole.hole_height!\n : plated_hole.hole_width!\n const holeHeight = shouldRotate\n ? plated_hole.hole_width!\n : plated_hole.hole_height!\n\n const holeRadius = holeHeight / 2\n const rectLength = Math.abs(holeWidth - holeHeight)\n\n const pillHole = union(\n cuboid({\n center: [plated_hole.x, plated_hole.y, 0],\n size: shouldRotate\n ? [holeHeight, rectLength, 1.5]\n : [rectLength, holeHeight, 1.5],\n }),\n cylinder({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y - rectLength / 2, 0]\n : [plated_hole.x - rectLength / 2, plated_hole.y, 0],\n radius: holeRadius,\n height: 1.5,\n }),\n cylinder({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y + rectLength / 2, 0]\n : [plated_hole.x + rectLength / 2, plated_hole.y, 0],\n radius: holeRadius,\n height: 1.5,\n }),\n )\n boardGeom = subtract(boardGeom, pillHole)\n\n const platedHoleGeom = platedHole(plated_hole, ctx)\n platedHoleGeoms.push(platedHoleGeom)\n }\n }\n\n for (const plated_hole of plated_holes) {\n addPlatedHole(plated_hole)\n }\n\n for (const hole of holes) {\n // @ts-expect-error\n if (hole.hole_shape === \"round\" || hole.hole_shape === \"circle\") {\n const cyGeom = cylinder({\n center: [hole.x, hole.y, 0],\n radius: hole.hole_diameter / 2 + M,\n })\n boardGeom = subtract(boardGeom, cyGeom)\n }\n }\n\n for (const pad of pads) {\n const layerSign = pad.layer === \"bottom\" ? -1 : 1\n if (pad.shape === \"rect\") {\n const padGeom = colorize(\n colors.copper,\n cuboid({\n center: [pad.x, pad.y, (layerSign * 1.2) / 2 + layerSign * M],\n size: [pad.width, pad.height, M],\n }),\n )\n padGeoms.push(padGeom)\n } else if (pad.shape === \"circle\") {\n const padGeom = colorize(\n colors.copper,\n cylinder({\n center: [pad.x, pad.y, (layerSign * 1.2) / 2 + layerSign * M],\n radius: pad.radius,\n height: M,\n }),\n )\n padGeoms.push(padGeom)\n }\n }\n\n for (const { route: mixedRoute } of traces) {\n if (mixedRoute.length < 2) continue\n\n // Group routes by continuous segments\n const routeSegments: (typeof mixedRoute)[] = []\n let currentSegment: typeof mixedRoute = [mixedRoute[0]!]\n let currentLayer =\n mixedRoute[0]!.route_type === \"wire\" ? mixedRoute[0]!.layer : \"top\"\n\n for (let i = 1; i < mixedRoute.length; i++) {\n const point = mixedRoute[i]!\n\n if (point.route_type === \"via\") {\n // Complete current segment and start a new one\n routeSegments.push(currentSegment)\n currentSegment = [point]\n } else if (point.route_type === \"wire\" && point.layer !== currentLayer) {\n // Complete current segment and start a new one on a different layer\n routeSegments.push(currentSegment)\n currentLayer = point.layer\n currentSegment = [point]\n } else {\n currentSegment.push(point)\n }\n }\n\n // Add the last segment\n routeSegments.push(currentSegment)\n\n // Render each route segment\n for (const route of routeSegments) {\n if (route.length < 2) continue\n\n const linePath = line(route.map((p) => [p.x, p.y]))\n const layerSign =\n route[0]!.route_type === \"via\"\n ? route[0]!.to_layer === \"top\"\n ? 1\n : -1\n : route[0]!.layer === \"top\"\n ? 1\n : -1\n\n let traceGeom = translate(\n [0, 0, (layerSign * 1.2) / 2],\n extrudeLinear(\n { height: M * layerSign },\n expand({ delta: 0.1, corners: \"edge\" }, linePath),\n ),\n )\n\n // Modify via subtraction to preserve trace geometry\n const viaSubtractions = pcb_vias.map((via) =>\n cylinder({\n center: [via.x, via.y, 0],\n radius: via.outer_diameter / 2,\n height: 5,\n }),\n )\n\n const holeSubtractions = plated_holes\n .filter((ph) => ph.shape === \"circle\")\n .map((ph) =>\n cylinder({\n center: [ph.x, ph.y, 0],\n radius: ph.outer_diameter / 2,\n height: 5,\n }),\n )\n\n // Subtract vias and holes without removing entire trace\n traceGeom = subtract(traceGeom, ...viaSubtractions, ...holeSubtractions)\n\n traceGeom = colorize(colors.fr4GreenSolderWithMask, traceGeom)\n\n traceGeoms.push(traceGeom)\n }\n }\n\n for (const via of pcb_vias) {\n addPlatedHole({\n x: via.x,\n y: via.y,\n hole_diameter: via.hole_diameter,\n outer_diameter: via.outer_diameter,\n shape: \"circle\",\n layers: [\"top\", \"bottom\"],\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: \"\",\n })\n }\n\n // Colorize to a PCB green color: #05A32E\n boardGeom = colorize(colors.fr4Green, boardGeom)\n\n return [boardGeom, ...platedHoleGeoms, ...padGeoms, ...traceGeoms]\n}\n","import type { PCBPlatedHole } from \"@tscircuit/soup\"\nimport type { Geom3 } from \"@jscad/modeling/src/geometries/types\"\nimport { cuboid, cylinder } from \"@jscad/modeling/src/primitives\"\nimport { colorize } from \"@jscad/modeling/src/colors\"\nimport { subtract, union } from \"@jscad/modeling/src/operations/booleans\"\nimport { M, colors } from \"./constants\"\nimport type { GeomContext } from \"../GeomContext\"\n\nexport const platedHole = (\n plated_hole: PCBPlatedHole,\n ctx: GeomContext,\n): Geom3 => {\n if (!(plated_hole as PCBPlatedHole).shape) plated_hole.shape = \"circle\"\n if (plated_hole.shape === \"circle\") {\n return colorize(\n colors.copper,\n subtract(\n union(\n cylinder({\n center: [plated_hole.x, plated_hole.y, 0],\n radius: plated_hole.hole_diameter / 2,\n height: 1.2,\n }),\n cylinder({\n center: [plated_hole.x, plated_hole.y, 1.2 / 2],\n radius: plated_hole.outer_diameter / 2,\n height: M,\n }),\n cylinder({\n center: [plated_hole.x, plated_hole.y, -1.2 / 2],\n radius: plated_hole.outer_diameter / 2,\n height: M,\n }),\n ),\n cylinder({\n center: [plated_hole.x, plated_hole.y, 0],\n radius: plated_hole.hole_diameter / 2 - M,\n height: 1.5,\n }),\n ),\n )\n }\n if (plated_hole.shape === \"pill\") {\n const shouldRotate = plated_hole.hole_height! > plated_hole.hole_width!\n\n const holeWidth = shouldRotate\n ? plated_hole.hole_height!\n : plated_hole.hole_width!\n const holeHeight = shouldRotate\n ? plated_hole.hole_width!\n : plated_hole.hole_height!\n const outerHeight = shouldRotate\n ? plated_hole.outer_width || holeWidth + 0.2\n : plated_hole.outer_height || holeHeight + 0.2\n\n const holeRadius = holeHeight / 2\n const rectLength = Math.abs(holeWidth - holeHeight)\n\n const mainRect = cuboid({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y, 0]\n : [plated_hole.x, plated_hole.y, 0],\n size: shouldRotate\n ? [holeHeight, rectLength, 1.2]\n : [rectLength, holeHeight, 1.2],\n })\n\n const leftCap = cylinder({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y - rectLength / 2, 0]\n : [plated_hole.x - rectLength / 2, plated_hole.y, 0],\n radius: holeRadius,\n height: 1.2,\n })\n\n const rightCap = cylinder({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y + rectLength / 2, 0]\n : [plated_hole.x + rectLength / 2, plated_hole.y, 0],\n radius: holeRadius,\n height: 1.2,\n })\n\n const outerMainRect = cuboid({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y, 1.2 / 2]\n : [plated_hole.x, plated_hole.y, 1.2 / 2],\n size: shouldRotate\n ? [outerHeight, rectLength, M]\n : [rectLength, outerHeight, M],\n })\n\n const outerLeftCap = cylinder({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y - rectLength / 2, 1.2 / 2]\n : [plated_hole.x - rectLength / 2, plated_hole.y, 1.2 / 2],\n radius: outerHeight / 2,\n height: M,\n })\n\n const outerRightCap = cylinder({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y + rectLength / 2, 1.2 / 2]\n : [plated_hole.x + rectLength / 2, plated_hole.y, 1.2 / 2],\n radius: outerHeight / 2,\n height: M,\n })\n\n const bottomMainRect = cuboid({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y, -1.2 / 2]\n : [plated_hole.x, plated_hole.y, -1.2 / 2],\n size: shouldRotate\n ? [outerHeight, rectLength, M]\n : [rectLength, outerHeight, M],\n })\n\n const bottomLeftCap = cylinder({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y - rectLength / 2, -1.2 / 2]\n : [plated_hole.x - rectLength / 2, plated_hole.y, -1.2 / 2],\n radius: outerHeight / 2,\n height: M,\n })\n\n const bottomRightCap = cylinder({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y + rectLength / 2, -1.2 / 2]\n : [plated_hole.x + rectLength / 2, plated_hole.y, -1.2 / 2],\n radius: outerHeight / 2,\n height: M,\n })\n return colorize(\n colors.copper,\n subtract(\n union(\n mainRect,\n leftCap,\n rightCap,\n outerMainRect,\n outerLeftCap,\n outerRightCap,\n bottomMainRect,\n bottomLeftCap,\n bottomRightCap,\n ),\n union(\n cuboid({\n center: [plated_hole.x, plated_hole.y, 0],\n size: shouldRotate\n ? [holeHeight - M, rectLength, 1.5]\n : [rectLength, holeHeight - M, 1.5],\n }),\n cylinder({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y - rectLength / 2, 0]\n : [plated_hole.x - rectLength / 2, plated_hole.y, 0],\n radius: holeRadius - M,\n height: 1.5,\n }),\n cylinder({\n center: shouldRotate\n ? [plated_hole.x, plated_hole.y + rectLength / 2, 0]\n : [plated_hole.x + rectLength / 2, plated_hole.y, 0],\n radius: holeRadius - M,\n height: 1.5,\n }),\n ),\n ),\n )\n // biome-ignore lint/style/noUselessElse: <explanation>\n } else {\n throw new Error(`Unsupported plated hole shape: ${plated_hole.shape}`)\n }\n}\n","import type { RGB } from \"@jscad/modeling/src/colors\"\n\nexport const M = 0.01\n\nexport const colors = {\n copper: [0.9, 0.6, 0.2],\n fr4Green: [0x05 / 255, 0xa3 / 255, 0x2e / 255],\n fr4GreenSolderWithMask: [0x00 / 255, 0x98 / 255, 0x13 / 255],\n} satisfies Record<string, RGB>\n","import { extrudeLinear } from \"@jscad/modeling/src/operations/extrusions\"\nimport { polygon } from \"@jscad/modeling/src/primitives\"\nimport type { Geom2, Geom3 } from \"@jscad/modeling/src/geometries/types\"\nimport type { Vec2 } from \"@jscad/modeling/src/maths/types\"\nimport type { Point } from \"@tscircuit/soup\"\nimport { translate } from \"@jscad/modeling/src/operations/transforms\"\n\nconst arePointsClockwise = (points: Vec2[]): boolean => {\n let area = 0\n for (let i = 0; i < points.length; i++) {\n const j = (i + 1) % points.length\n area += points[i]![0] * points[j]![1]\n area -= points[j]![0] * points[i]![1]\n }\n const signedArea = area / 2\n return signedArea <= 0\n}\n\nexport const createBoardWithOutline = (points: Point[], depth = 1.2): Geom3 => {\n let outline: Vec2[] = points.map((point) => [point.x, point.y])\n\n if (arePointsClockwise(outline)) {\n outline = outline.reverse()\n }\n\n const shape: Geom2 = polygon({ points: outline })\n\n let board: Geom3 = extrudeLinear({ height: depth }, shape)\n\n board = translate([0, 0, -depth / 2], board)\n\n return board\n}\n","import { useState, useEffect } from \"react\"\nimport stlSerializer from \"@jscad/stl-serializer\"\nimport { Geom3 } from \"@jscad/modeling/src/geometries/types\"\n\nfunction blobToBase64Url(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => {\n resolve(reader.result as string)\n }\n reader.onerror = reject\n reader.readAsDataURL(blob)\n })\n}\n\ntype StlObj = { stlUrl: string; color: number[] }\n\nexport const useStlsFromGeom = (\n geom: Geom3[] | Geom3 | null,\n): {\n stls: StlObj[]\n loading: boolean\n} => {\n const [stls, setStls] = useState<StlObj[]>([])\n const [loading, setLoading] = useState(true)\n\n useEffect(() => {\n if (!geom) return\n const generateStls = async () => {\n setLoading(true)\n const geometries = Array.isArray(geom) ? geom : [geom]\n\n const stlPromises = geometries.map(async (g) => {\n const rawData = stlSerializer.serialize({ binary: true }, [g])\n const blobData = new Blob(rawData)\n const stlUrl = await blobToBase64Url(blobData)\n return { stlUrl, color: g.color! }\n })\n\n try {\n const generatedStls = await Promise.all(stlPromises)\n setStls(generatedStls)\n } catch (error) {\n console.error(\"Error generating STLs:\", error)\n setStls([])\n } finally {\n setLoading(false)\n }\n }\n\n generateStls()\n }, [geom])\n\n return { stls, loading }\n}\n","import { useLoader } from \"@react-three/fiber\"\nimport { useRef } from \"react\"\nimport * as THREE from \"three\"\nimport { MTLLoader, OBJLoader, STLLoader } from \"three-stdlib\"\n\nexport function STLModel({\n stlUrl,\n mtlUrl,\n color,\n opacity = 1,\n}: {\n stlUrl: string\n color?: any\n mtlUrl?: string\n opacity?: number\n}) {\n const geom = useLoader(STLLoader, stlUrl)\n const mesh = useRef<THREE.Mesh>()\n\n // TODO handle mtl url\n\n return (\n <mesh ref={mesh as any}>\n <primitive object={geom} attach=\"geometry\" />\n <meshStandardMaterial\n color={color}\n transparent={opacity !== 1}\n opacity={opacity}\n />\n {/* <Outlines thickness={0.05} color=\"black\" opacity={0.25} /> */}\n </mesh>\n )\n}\n","import { Grid, OrbitControls } from \"@react-three/drei\"\nimport { Canvas, useFrame } from \"@react-three/fiber\"\nimport packageJson from \"../package.json\"\nimport { CubeWithLabeledSides } from \"./three-components/cube-with-labeled-sides\"\n\nexport const RotationTracker = () => {\n useFrame(({ camera }) => {\n window.TSCI_MAIN_CAMERA_ROTATION = camera.rotation\n })\n\n return <></>\n}\n\nimport { Html } from \"@react-three/drei\"\n\nexport const CadViewerContainer = ({\n children,\n hoveredComponent,\n}: {\n children: any\n hoveredComponent: {\n cad_component_id: string\n name: string\n mousePosition: [number, number, number]\n } | null\n}) => {\n return (\n <div style={{ position: \"relative\", width: \"100%\", height: \"100%\" }}>\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: 120,\n height: 120,\n }}\n >\n <Canvas\n camera={{\n up: [0, 0, 1],\n position: [1, 1, 1],\n }}\n style={{ zIndex: 10 }}\n >\n <ambientLight intensity={Math.PI / 2} />\n <CubeWithLabeledSides />\n </Canvas>\n </div>\n <Canvas\n scene={{ up: [0, 0, 1] }}\n camera={{ up: [0, 0, 1], position: [5, 5, 5] }}\n >\n <RotationTracker />\n <OrbitControls autoRotate autoRotateSpeed={1} />\n <ambientLight intensity={Math.PI / 2} />\n <pointLight\n position={[-10, -10, 10]}\n decay={0}\n intensity={Math.PI / 4}\n />\n <Grid\n rotation={[Math.PI / 2, 0, 0]}\n infiniteGrid={true}\n cellSize={1}\n sectionSize={10}\n />\n {children}\n {hoveredComponent && (\n <Html\n position={hoveredComponent.mousePosition}\n style={{\n fontFamily: \"sans-serif\",\n transform: \"translate3d(50%, 50%, 0)\",\n backgroundColor: \"white\",\n padding: \"5px\",\n borderRadius: \"3px\",\n pointerEvents: \"none\",\n }}\n >\n {hoveredComponent.name}\n </Html>\n )}\n </Canvas>\n <div\n style={{\n position: \"absolute\",\n right: 24,\n bottom: 24,\n fontFamily: \"sans-serif\",\n color: \"white\",\n WebkitTextStroke: \"0.5px rgba(0, 0, 0, 0.5)\",\n fontSize: 11,\n }}\n >\n @{packageJson.version}\n </div>\n </div>\n )\n}\n","{\n \"name\": \"@tscircuit/3d-viewer\",\n \"version\": \"0.0.48\",\n \"main\": \"./dist/index.js\",\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"start\": \"bun run storybook\",\n \"dev:old\": \"bunx --bun vite\",\n \"build\": \"tsup ./src/index.tsx --dts --sourcemap\",\n \"prepublish\": \"npm run build\",\n \"preview\": \"vite preview\",\n \"storybook\": \"storybook dev -p 6006\",\n \"build-storybook\": \"storybook build\",\n \"format\": \"biome format . --write\"\n },\n \"dependencies\": {\n \"@jscad/modeling\": \"^2.12.2\",\n \"@jscad/regl-renderer\": \"^2.6.9\",\n \"@jscad/stl-serializer\": \"^2.1.17\",\n \"@react-three/drei\": \"^9.115.0\",\n \"@react-three/fiber\": \"^8.16.8\",\n \"@tscircuit/core\": \"^0.0.136\",\n \"@tscircuit/react-fiber\": \"^1.1.29\",\n \"@tscircuit/soup\": \"^0.0.69\",\n \"@tscircuit/soup-util\": \"^0.0.26\",\n \"@types/three\": \"^0.165.0\",\n \"jscad-electronics\": \"^0.0.23\",\n \"jscad-fiber\": \"^0.0.75\",\n \"jscad-planner\": \"^0.0.11\",\n \"react\": \"^18.3.1\",\n \"react-dom\": \"^18.3.1\",\n \"react-use-gesture\": \"^9.1.3\",\n \"three\": \"^0.165.0\",\n \"three-stdlib\": \"^2.30.3\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"^1.8.3\",\n \"@chromatic-com/storybook\": \"^1.5.0\",\n \"@storybook/addon-essentials\": \"^8.1.10\",\n \"@storybook/addon-interactions\": \"^8.1.10\",\n \"@storybook/addon-links\": \"^8.1.10\",\n \"@storybook/addon-onboarding\": \"^8.1.10\",\n \"@storybook/blocks\": \"^8.1.10\",\n \"@storybook/builder-vite\": \"^8.1.10\",\n \"@storybook/react\": \"^8.1.10\",\n \"@storybook/react-vite\": \"^8.1.10\",\n \"@storybook/test\": \"^8.1.10\",\n \"@types/react\": \"^18.3.3\",\n \"@types/react-dom\": \"^18.3.0\",\n \"@vitejs/plugin-react\": \"^4.3.1\",\n \"circuit-json\": \"^0.0.77\",\n \"storybook\": \"^8.1.10\",\n \"strip-ansi\": \"^7.1.0\",\n \"tsup\": \"^8.1.0\",\n \"typescript\": \"^5.5.3\",\n \"vite\": \"^5.3.1\",\n \"vite-tsconfig-paths\": \"^4.3.2\"\n }\n}\n","import { Text } from \"@react-three/drei\"\nimport { useFrame } from \"@react-three/fiber\"\nimport { useRef } from \"react\"\nimport * as THREE from \"three\"\n\ndeclare global {\n interface Window {\n TSCI_MAIN_CAMERA_ROTATION: THREE.Euler\n }\n}\nif (typeof window !== \"undefined\") {\n window.TSCI_MAIN_CAMERA_ROTATION = new THREE.Euler(0, 0, 0)\n}\n\nfunction computePointInFront(rotationVector, distance) {\n // Create a quaternion from the rotation vector\n const quaternion = new THREE.Quaternion().setFromEuler(\n new THREE.Euler(rotationVector.x, rotationVector.y, rotationVector.z),\n )\n\n // Create a vector pointing forward (along the negative z-axis)\n const forwardVector = new THREE.Vector3(0, 0, 1)\n\n // Apply the rotation to the forward vector\n forwardVector.applyQuaternion(quaternion)\n\n // Scale the rotated vector by the distance\n const result = forwardVector.multiplyScalar(distance)\n\n return result\n}\n\nexport const CubeWithLabeledSides = ({}: any) => {\n const ref = useRef<THREE.Mesh>()\n const rotationTrackingRef = useRef({ lastRotation: new THREE.Euler() })\n useFrame((state, delta) => {\n if (!ref.current) return\n\n const mainRot = window.TSCI_MAIN_CAMERA_ROTATION\n\n // Use window.TSCI_CAMERA_ROTATION to compute the position of the camera\n const cameraPosition = computePointInFront(mainRot, 2)\n\n state.camera.position.copy(cameraPosition)\n state.camera.lookAt(0, 0, 0)\n })\n return (\n <mesh ref={ref as any} rotation={[Math.PI / 2, 0, 0]}>\n <boxGeometry args={[1, 1, 1]} />\n <meshStandardMaterial color=\"white\" />\n <Text position={[0, 0, 0.51]} fontSize={0.25} color=\"black\">\n Front\n </Text>\n <Text\n position={[0, 0, -0.51]}\n fontSize={0.25}\n color=\"black\"\n rotation={[0, Math.PI, 0]}\n >\n Back\n </Text>\n <Text\n position={[0.51, 0, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[0, Math.PI / 2, 0]}\n >\n Right\n </Text>\n <Text\n position={[-0.51, 0, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[0, -Math.PI / 2, 0]}\n >\n Left\n </Text>\n <Text\n position={[0, 0.51, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[-Math.PI / 2, 0, 0]}\n >\n Top\n </Text>\n <Text\n position={[0, -0.51, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[Math.PI / 2, 0, 0]}\n >\n Bottom\n </Text>\n <lineSegments\n args={[new THREE.EdgesGeometry(new THREE.BoxGeometry(1, 1, 1))]}\n material={\n new THREE.LineBasicMaterial({\n color: 0x000000,\n linewidth: 2,\n })\n }\n />\n </mesh>\n )\n}\n","import { Html } from \"@react-three/drei\"\nimport { GroupProps, useThree } from \"@react-three/fiber\"\nimport { useRef, useCallback } from \"react\"\nimport type { Vector3 } from \"three\"\nimport * as THREE from \"three\"\n\nconst Group = (props: GroupProps) => <group {...props} />\n\nconst ContainerWithTooltip = ({\n children,\n isHovered,\n onHover,\n position,\n}: {\n children: React.ReactNode\n position?: Vector3 | [number, number, number]\n onHover: (e: any) => void\n isHovered: boolean\n}) => {\n const lastValidPointRef = useRef<THREE.Vector3 | null>(null)\n\n const handlePointerEnter = useCallback(\n (e: any) => {\n e.stopPropagation()\n\n try {\n // Fallback to event position if raycaster fails\n const point =\n e.point ||\n (e.intersections && e.intersections.length > 0\n ? e.intersections[0].point\n : null) ||\n (position\n ? new THREE.Vector3(...(position as [number, number, number]))\n : null)\n\n if (point) {\n lastValidPointRef.current = point\n onHover({ mousePosition: [point.x, point.y, point.z] })\n } else {\n onHover({})\n }\n } catch (error) {\n console.warn(\"Hover event error:\", error)\n onHover({})\n }\n },\n [position],\n )\n\n const handlePointerLeave = useCallback(\n (e: any) => {\n e.stopPropagation()\n lastValidPointRef.current = null\n\n // TODO REPLACE WITH onUnhover\n onHover(null)\n },\n [onHover],\n )\n\n return (\n <Group\n onPointerEnter={handlePointerEnter}\n onPointerMove={handlePointerEnter}\n onPointerLeave={handlePointerLeave}\n >\n {children}\n </Group>\n )\n}\n\nexport default ContainerWithTooltip\n","import { useState, useEffect } from \"react\"\nimport type { Group } from \"three\"\nimport { MTLLoader, OBJLoader } from \"three-stdlib\"\n\n// Define the type for our cache\ninterface CacheItem {\n promise: Promise<any>\n result: Group | null\n}\n\ndeclare global {\n interface Window {\n TSCIRCUIT_OBJ_LOADER_CACHE: Map<string, CacheItem>\n }\n}\n\n// Ensure the global cache exists\nif (typeof window !== \"undefined\" && !window.TSCIRCUIT_OBJ_LOADER_CACHE) {\n window.TSCIRCUIT_OBJ_LOADER_CACHE = new Map<string, CacheItem>()\n}\n\nexport function useGlobalObjLoader(url: string | null): Group | null | Error {\n const [obj, setObj] = useState<Group | null | Error>(null)\n\n useEffect(() => {\n if (!url) return\n\n const cache = window.TSCIRCUIT_OBJ_LOADER_CACHE\n let hasUrlChanged = false\n\n async function loadAndParseObj() {\n try {\n const response = await fetch(url!)\n const text = await response.text()\n\n const mtlContent = text\n .match(/newmtl[\\s\\S]*?endmtl/g)\n ?.join(\"\\n\")!\n .replace(/d 0\\./g, \"d 1.\")!\n const objContent = text.replace(/newmtl[\\s\\S]*?endmtl/g, \"\")\n\n const mtlLoader = new MTLLoader()\n mtlLoader.setMaterialOptions({\n invertTrProperty: true,\n })\n const materials = mtlLoader.parse(\n mtlContent.replace(\n /Kd\\s+([\\d.]+)\\s+([\\d.]+)\\s+([\\d.]+)/g,\n \"Kd $2 $2 $2\",\n ),\n \"test.mtl\",\n )\n\n const objLoader = new OBJLoader()\n objLoader.setMaterials(materials)\n return objLoader.parse(objContent)\n } catch (error) {\n return error as Error\n }\n }\n\n function loadUrl() {\n if (cache.has(url!)) {\n const cacheItem = cache.get(url!)!\n if (cacheItem.result) {\n // If we have a result, clone it\n return Promise.resolve(cacheItem.result.clone())\n }\n // If we're still loading, return the existing promise\n return cacheItem.promise.then((result) => result.clone())\n }\n // If it's not in the cache, create a new promise and cache it\n const promise = loadAndParseObj().then((result) => {\n if (result instanceof Error) {\n // If the result is an Error, return it\n return result\n }\n cache.set(url!, { ...cache.get(url!)!, result })\n return result\n })\n cache.set(url!, { promise, result: null })\n return promise\n }\n\n loadUrl()\n .then((result) => {\n if (hasUrlChanged) return\n setObj(result)\n })\n .catch((error) => {\n console.error(error)\n })\n\n return () => {\n hasUrlChanged = true\n }\n }, [url])\n\n return obj\n}\n","import ContainerWithTooltip from \"src/ContainerWithTooltip\"\nimport { useGlobalObjLoader } from \"src/hooks/use-global-obj-loader\"\nimport type { Euler, Vector3 } from \"three\"\n\nexport function MixedStlModel({\n url,\n position,\n rotation,\n onHover,\n isHovered,\n}: {\n url: string\n position?: Vector3 | [number, number, number]\n rotation?: Euler | [number, number, number]\n onHover: (e: any) => void\n isHovered: boolean\n}) {\n const obj = useGlobalObjLoader(url)\n\n if (!obj) {\n return (\n <ContainerWithTooltip isHovered={isHovered} onHover={onHover}>\n <mesh position={position}>\n <boxGeometry args={[0.5, 0.5, 0.5]} />\n <meshStandardMaterial transparent color=\"red\" opacity={0.25} />\n </mesh>\n </ContainerWithTooltip>\n )\n }\n\n // Check if obj is valid before rendering\n if (obj instanceof Error) {\n return (\n <ContainerWithTooltip isHovered={isHovered} onHover={onHover}>\n <mesh position={position}>\n <boxGeometry args={[0.5, 0.5, 0.5]} />\n <meshStandardMaterial transparent color=\"red\" opacity={0.5} />\n <meshBasicMaterial color=\"red\" />\n </mesh>\n </ContainerWithTooltip>\n )\n }\n return (\n <ContainerWithTooltip isHovered={isHovered} onHover={onHover}>\n <primitive rotation={rotation} position={position} object={obj} />\n </ContainerWithTooltip>\n )\n}\n","import type { JscadOperation } from \"jscad-planner\"\nimport { executeJscadOperations } from \"jscad-planner\"\nimport jscad from \"@jscad/modeling\"\nimport { convertCSGToThreeGeom } from \"jscad-fiber\"\nimport * as THREE from \"three\"\nimport { useMemo } from \"react\"\nimport ContainerWithTooltip from \"src/ContainerWithTooltip\"\n\nexport const JscadModel = ({\n jscadPlan,\n positionOffset,\n rotationOffset,\n onHover,\n isHovered,\n}: {\n jscadPlan: JscadOperation\n positionOffset?: [number, number, number]\n rotationOffset?: [number, number, number]\n onHover: (e: any) => void\n isHovered: boolean\n}) => {\n const { threeGeom, material } = useMemo(() => {\n const jscadObject = executeJscadOperations(jscad as any, jscadPlan)\n\n const threeGeom = convertCSGToThreeGeom(jscadObject)\n\n const material = new THREE.MeshStandardMaterial({\n vertexColors: true,\n side: THREE.DoubleSide, // Ensure both sides are visible\n })\n return { threeGeom, material }\n }, [jscadPlan])\n\n useMemo(() => {\n if (isHovered) {\n const color = new THREE.Color(material.color.getHex())\n material.emissive.copy(color)\n material.emissive.setRGB(0, 0, 1)\n material.emissiveIntensity = 0.2\n } else {\n material.emissiveIntensity = 0\n }\n }, [isHovered, material])\n if (!threeGeom) return null\n\n return (\n <ContainerWithTooltip\n isHovered={isHovered}\n onHover={onHover}\n position={positionOffset}\n >\n <mesh\n geometry={threeGeom}\n material={material}\n position={positionOffset}\n rotation={rotationOffset}\n />\n </ContainerWithTooltip>\n )\n}\n","import { Footprinter3d } from \"jscad-electronics\"\nimport { createJSCADRenderer } from \"jscad-fiber\"\nimport { jscadPlanner } from \"jscad-planner\"\nimport { useMemo } from \"react\"\nimport { JscadModel } from \"./JscadModel\"\n\nconst { createJSCADRoot } = createJSCADRenderer(jscadPlanner as any)\n\nexport const FootprinterModel = ({\n positionOffset,\n footprint,\n rotationOffset,\n onHover,\n isHovered,\n}: {\n positionOffset: any\n footprint: string\n rotationOffset?: [number, number, number]\n onHover: (e: any) => void\n isHovered: boolean\n}) => {\n const jscadOperations = useMemo(() => {\n if (!footprint) return null\n const jscadOperations: any[] = []\n const root = createJSCADRoot(jscadOperations)\n root.render(<Footprinter3d footprint={footprint} />)\n return jscadOperations\n }, [footprint])\n\n if (!jscadOperations) return null\n\n return (\n <>\n {jscadOperations.map((operation, index) => (\n <JscadModel\n // biome-ignore lint/suspicious/noArrayIndexKey: <explanation>\n key={index}\n positionOffset={positionOffset}\n rotationOffset={rotationOffset}\n jscadPlan={operation}\n onHover={onHover}\n isHovered={isHovered}\n />\n ))}\n </>\n )\n}\n","export const tuple = <T extends any[]>(...args: T): T => args\n","import type { AnyCircuitElement, CadComponent } from \"circuit-json\"\nimport { useConvertChildrenToSoup } from \"./hooks/use-convert-children-to-soup\"\nimport { su } from \"@tscircuit/soup-util\"\nimport { useMemo, useState } from \"react\"\nimport { createBoardGeomFromSoup } from \"./soup-to-3d\"\nimport { useStlsFromGeom } from \"./hooks/use-stls-from-geom\"\nimport { STLModel } from \"./three-components/STLModel\"\nimport { CadViewerContainer } from \"./CadViewerContainer\"\nimport { MixedStlModel } from \"./three-components/MixedStlModel\"\nimport { Euler } from \"three\"\nimport { JscadModel } from \"./three-components/JscadModel\"\nimport { Footprinter3d } from \"jscad-electronics\"\nimport { FootprinterModel } from \"./three-components/FootprinterModel\"\nimport { tuple } from \"./utils/tuple\"\n\nexport const AnyCadComponent = ({\n cad_component,\n onHover = () => {},\n isHovered = false,\n}: {\n cad_component: CadComponent\n onHover?: (e: any) => void\n isHovered?: boolean\n}) => {\n const url = cad_component.model_obj_url ?? cad_component.model_stl_url\n const rotationOffset = cad_component.rotation\n ? tuple(\n (cad_component.rotation.x * Math.PI) / 180,\n (cad_component.rotation.y * Math.PI) / 180,\n (cad_component.rotation.z * Math.PI) / 180,\n )\n : undefined\n\n if (url) {\n return (\n <MixedStlModel\n key={cad_component.cad_component_id}\n url={url}\n position={\n cad_component.position\n ? [\n cad_component.position.x,\n cad_component.position.y,\n cad_component.position.z,\n ]\n : undefined\n }\n rotation={rotationOffset}\n onHover={onHover}\n isHovered={isHovered}\n />\n )\n }\n\n if (cad_component.model_jscad) {\n return (\n <JscadModel\n key={cad_component.cad_component_id}\n jscadPlan={cad_component.model_jscad as any}\n rotationOffset={rotationOffset}\n onHover={onHover}\n isHovered={isHovered}\n />\n )\n }\n\n if (cad_component.footprinter_string) {\n return (\n <FootprinterModel\n positionOffset={\n cad_component.position\n ? [\n cad_component.position.x,\n cad_component.position.y,\n cad_component.position.z,\n ]\n : undefined\n }\n rotationOffset={rotationOffset}\n footprint={cad_component.footprinter_string}\n onHover={onHover}\n isHovered={isHovered}\n />\n )\n }\n}\n","import React from \"react\"\n\ninterface Props {\n children: React.ReactNode\n fallback: (props: { error: Error }) => any\n}\n\ninterface State {\n hasError: boolean\n error: Error | null\n}\n\nexport class ThreeErrorBoundary extends React.Component<Props, State> {\n constructor(props: Props) {\n super(props)\n this.state = { hasError: false, error: null }\n }\n\n static getDerivedStateFromError(error: Error): State {\n return { hasError: true, error }\n }\n\n override render() {\n if (this.state.hasError && this.state.error) {\n return this.props.fallback({ error: this.state.error })\n }\n\n return this.props.children\n }\n}\n","import { Text } from \"@react-three/drei\"\nimport type { CadComponent } from \"circuit-json\"\n\nexport const Error3d = ({\n error,\n cad_component,\n}: { error: any; cad_component?: CadComponent }) => {\n let position = [0, 0, 0]\n if (cad_component?.position) {\n position = [\n cad_component.position.x,\n cad_component.position.y,\n cad_component.position.z,\n ]\n // make sure the position doesn't have any NaN values\n position = position.map((p) => (Number.isNaN(p) ? 0 : p))\n }\n return (\n <group\n // @ts-expect-error\n position={position}\n >\n <mesh\n renderOrder={-99999}\n rotation={[Math.PI / 4, Math.PI / 4, 0]}\n ref={(mesh) => {\n if (mesh) {\n mesh.renderOrder = 999999\n }\n }}\n >\n <boxGeometry args={[0.5, 0.5, 0.5]} />\n <meshStandardMaterial\n depthTest={false}\n transparent\n color=\"red\"\n opacity={0.5}\n />\n </mesh>\n <Text\n scale={[0.1, 0.1, 0.1]}\n color=\"red\" // default\n anchorX=\"center\" // default\n anchorY=\"middle\" // default\n depthOffset={-99999}\n >\n {error.toString().slice(0, 50)}...\n </Text>\n </group>\n ) as any\n}\n"],"mappings":"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","names":["import_soup_util","import_react","import_transforms","import_primitives","import_colors","import_booleans","import_extrusions","import_primitives","import_react","stlSerializer","import_react","import_drei","import_fiber","import_fiber","import_react","import_jsx_runtime","import_drei","import_jsx_runtime","import_react","THREE","import_jsx_runtime","import_react","import_three_stdlib","import_jsx_runtime","THREE","import_react","import_jsx_runtime","jscad","threeGeom","material","import_jscad_fiber","import_jscad_planner","import_react","import_jsx_runtime","jscadOperations","import_jsx_runtime","import_react","React","import_drei","import_jsx_runtime","import_jsx_runtime"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/3d-viewer",
3
- "version": "0.0.48",
3
+ "version": "0.0.50",
4
4
  "main": "./dist/index.js",
5
5
  "files": [
6
6
  "dist"
@@ -26,9 +26,9 @@
26
26
  "@tscircuit/soup": "^0.0.69",
27
27
  "@tscircuit/soup-util": "^0.0.26",
28
28
  "@types/three": "^0.165.0",
29
- "jscad-electronics": "^0.0.22",
30
- "jscad-fiber": "^0.0.74",
31
- "jscad-planner": "^0.0.8",
29
+ "jscad-electronics": "^0.0.23",
30
+ "jscad-fiber": "^0.0.75",
31
+ "jscad-planner": "^0.0.11",
32
32
  "react": "^18.3.1",
33
33
  "react-dom": "^18.3.1",
34
34
  "react-use-gesture": "^9.1.3",