@tscircuit/3d-viewer 0.0.40 → 0.0.42

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_react8 = require("react");
52
+ var import_react9 = require("react");
53
53
 
54
54
  // src/soup-to-3d/index.ts
55
55
  var import_soup_util = require("@tscircuit/soup-util");
@@ -104,52 +104,52 @@ var platedHole = (plated_hole, ctx) => {
104
104
  );
105
105
  }
106
106
  if (plated_hole.shape === "pill") {
107
- const holeWidth = plated_hole.hole_width;
108
- const holeHeight = plated_hole.hole_height;
109
- const outerWidth = plated_hole.outer_width || holeWidth + 0.2;
110
- const outerHeight = plated_hole.outer_height || holeHeight + 0.2;
107
+ const shouldRotate = plated_hole.hole_height > plated_hole.hole_width;
108
+ const holeWidth = shouldRotate ? plated_hole.hole_height : plated_hole.hole_width;
109
+ const holeHeight = shouldRotate ? plated_hole.hole_width : plated_hole.hole_height;
110
+ const outerHeight = shouldRotate ? plated_hole.outer_width || holeWidth + 0.2 : plated_hole.outer_height || holeHeight + 0.2;
111
111
  const holeRadius = holeHeight / 2;
112
- const outerRadius = outerHeight / 2;
112
+ const rectLength = Math.abs(holeWidth - holeHeight);
113
113
  const mainRect = (0, import_primitives.cuboid)({
114
- center: [plated_hole.x, plated_hole.y, 0],
115
- size: [holeWidth - holeHeight, holeHeight, 1.2]
114
+ center: shouldRotate ? [plated_hole.x, plated_hole.y, 0] : [plated_hole.x, plated_hole.y, 0],
115
+ size: shouldRotate ? [holeHeight, rectLength, 1.2] : [rectLength, holeHeight, 1.2]
116
116
  });
117
117
  const leftCap = (0, import_primitives.cylinder)({
118
- center: [plated_hole.x - (holeWidth - holeHeight) / 2, plated_hole.y, 0],
118
+ center: shouldRotate ? [plated_hole.x, plated_hole.y - rectLength / 2, 0] : [plated_hole.x - rectLength / 2, plated_hole.y, 0],
119
119
  radius: holeRadius,
120
120
  height: 1.2
121
121
  });
122
122
  const rightCap = (0, import_primitives.cylinder)({
123
- center: [plated_hole.x + (holeWidth - holeHeight) / 2, plated_hole.y, 0],
123
+ center: shouldRotate ? [plated_hole.x, plated_hole.y + rectLength / 2, 0] : [plated_hole.x + rectLength / 2, plated_hole.y, 0],
124
124
  radius: holeRadius,
125
125
  height: 1.2
126
126
  });
127
127
  const outerMainRect = (0, import_primitives.cuboid)({
128
- center: [plated_hole.x, plated_hole.y, 1.2 / 2],
129
- size: [outerWidth - outerHeight, outerHeight, M]
128
+ center: shouldRotate ? [plated_hole.x, plated_hole.y, 1.2 / 2] : [plated_hole.x, plated_hole.y, 1.2 / 2],
129
+ size: shouldRotate ? [outerHeight, rectLength, M] : [rectLength, outerHeight, M]
130
130
  });
131
131
  const outerLeftCap = (0, import_primitives.cylinder)({
132
- center: [plated_hole.x - (outerWidth - outerHeight) / 2, plated_hole.y, 1.2 / 2],
133
- radius: outerRadius,
132
+ center: shouldRotate ? [plated_hole.x, plated_hole.y - rectLength / 2, 1.2 / 2] : [plated_hole.x - rectLength / 2, plated_hole.y, 1.2 / 2],
133
+ radius: outerHeight / 2,
134
134
  height: M
135
135
  });
136
136
  const outerRightCap = (0, import_primitives.cylinder)({
137
- center: [plated_hole.x + (outerWidth - outerHeight) / 2, plated_hole.y, 1.2 / 2],
138
- radius: outerRadius,
137
+ center: shouldRotate ? [plated_hole.x, plated_hole.y + rectLength / 2, 1.2 / 2] : [plated_hole.x + rectLength / 2, plated_hole.y, 1.2 / 2],
138
+ radius: outerHeight / 2,
139
139
  height: M
140
140
  });
141
141
  const bottomMainRect = (0, import_primitives.cuboid)({
142
- center: [plated_hole.x, plated_hole.y, -1.2 / 2],
143
- size: [outerWidth - outerHeight, outerHeight, M]
142
+ center: shouldRotate ? [plated_hole.x, plated_hole.y, -1.2 / 2] : [plated_hole.x, plated_hole.y, -1.2 / 2],
143
+ size: shouldRotate ? [outerHeight, rectLength, M] : [rectLength, outerHeight, M]
144
144
  });
145
145
  const bottomLeftCap = (0, import_primitives.cylinder)({
146
- center: [plated_hole.x - (outerWidth - outerHeight) / 2, plated_hole.y, -1.2 / 2],
147
- radius: outerRadius,
146
+ center: shouldRotate ? [plated_hole.x, plated_hole.y - rectLength / 2, -1.2 / 2] : [plated_hole.x - rectLength / 2, plated_hole.y, -1.2 / 2],
147
+ radius: outerHeight / 2,
148
148
  height: M
149
149
  });
150
150
  const bottomRightCap = (0, import_primitives.cylinder)({
151
- center: [plated_hole.x + (outerWidth - outerHeight) / 2, plated_hole.y, -1.2 / 2],
152
- radius: outerRadius,
151
+ center: shouldRotate ? [plated_hole.x, plated_hole.y + rectLength / 2, -1.2 / 2] : [plated_hole.x + rectLength / 2, plated_hole.y, -1.2 / 2],
152
+ radius: outerHeight / 2,
153
153
  height: M
154
154
  });
155
155
  return (0, import_colors.colorize)(
@@ -166,22 +166,22 @@ var platedHole = (plated_hole, ctx) => {
166
166
  bottomLeftCap,
167
167
  bottomRightCap
168
168
  ),
169
- [
169
+ (0, import_booleans.union)(
170
170
  (0, import_primitives.cuboid)({
171
171
  center: [plated_hole.x, plated_hole.y, 0],
172
- size: [holeWidth - holeHeight - M * 2, holeHeight - M * 2, 1.5]
172
+ size: shouldRotate ? [holeHeight - M, rectLength, 1.5] : [rectLength, holeHeight - M, 1.5]
173
173
  }),
174
174
  (0, import_primitives.cylinder)({
175
- center: [plated_hole.x - (holeWidth - holeHeight) / 2, plated_hole.y, 0],
175
+ center: shouldRotate ? [plated_hole.x, plated_hole.y - rectLength / 2, 0] : [plated_hole.x - rectLength / 2, plated_hole.y, 0],
176
176
  radius: holeRadius - M,
177
177
  height: 1.5
178
178
  }),
179
179
  (0, import_primitives.cylinder)({
180
- center: [plated_hole.x + (holeWidth - holeHeight) / 2, plated_hole.y, 0],
180
+ center: shouldRotate ? [plated_hole.x, plated_hole.y + rectLength / 2, 0] : [plated_hole.x + rectLength / 2, plated_hole.y, 0],
181
181
  radius: holeRadius - M,
182
182
  height: 1.5
183
183
  })
184
- ]
184
+ )
185
185
  )
186
186
  );
187
187
  } else {
@@ -250,19 +250,23 @@ var createBoardGeomFromSoup = (soup) => {
250
250
  const platedHoleGeom = platedHole(plated_hole, ctx);
251
251
  platedHoleGeoms.push(platedHoleGeom);
252
252
  } else if (plated_hole.shape === "pill") {
253
- const holeRadius = plated_hole.hole_height / 2;
253
+ const shouldRotate = plated_hole.hole_height > plated_hole.hole_width;
254
+ const holeWidth = shouldRotate ? plated_hole.hole_height : plated_hole.hole_width;
255
+ const holeHeight = shouldRotate ? plated_hole.hole_width : plated_hole.hole_height;
256
+ const holeRadius = holeHeight / 2;
257
+ const rectLength = Math.abs(holeWidth - holeHeight);
254
258
  const pillHole = (0, import_booleans2.union)(
255
259
  (0, import_primitives3.cuboid)({
256
260
  center: [plated_hole.x, plated_hole.y, 0],
257
- size: [plated_hole.hole_width - plated_hole.hole_height, plated_hole.hole_height, 1.5]
261
+ size: shouldRotate ? [holeHeight, rectLength, 1.5] : [rectLength, holeHeight, 1.5]
258
262
  }),
259
263
  (0, import_primitives3.cylinder)({
260
- center: [plated_hole.x - (plated_hole.hole_width - plated_hole.hole_height) / 2, plated_hole.y, 0],
264
+ center: shouldRotate ? [plated_hole.x, plated_hole.y - rectLength / 2, 0] : [plated_hole.x - rectLength / 2, plated_hole.y, 0],
261
265
  radius: holeRadius,
262
266
  height: 1.5
263
267
  }),
264
268
  (0, import_primitives3.cylinder)({
265
- center: [plated_hole.x + (plated_hole.hole_width - plated_hole.hole_height) / 2, plated_hole.y, 0],
269
+ center: shouldRotate ? [plated_hole.x, plated_hole.y + rectLength / 2, 0] : [plated_hole.x + rectLength / 2, plated_hole.y, 0],
266
270
  radius: holeRadius,
267
271
  height: 1.5
268
272
  })
@@ -455,7 +459,7 @@ var import_fiber3 = require("@react-three/fiber");
455
459
  // package.json
456
460
  var package_default = {
457
461
  name: "@tscircuit/3d-viewer",
458
- version: "0.0.39",
462
+ version: "0.0.41",
459
463
  main: "./dist/index.js",
460
464
  files: [
461
465
  "dist"
@@ -467,7 +471,8 @@ var package_default = {
467
471
  prepublish: "npm run build",
468
472
  preview: "vite preview",
469
473
  storybook: "storybook dev -p 6006",
470
- "build-storybook": "storybook build"
474
+ "build-storybook": "storybook build",
475
+ format: "biome format . --write"
471
476
  },
472
477
  dependencies: {
473
478
  "@jscad/modeling": "^2.12.2",
@@ -703,6 +708,9 @@ var CadViewerContainer = ({ children }) => {
703
708
 
704
709
  // src/ContainerWithTooltip.tsx
705
710
  var import_drei3 = require("@react-three/drei");
711
+ var import_fiber4 = require("@react-three/fiber");
712
+ var import_react5 = require("react");
713
+ var THREE2 = __toESM(require("three"));
706
714
  var import_jsx_runtime4 = require("react/jsx-runtime");
707
715
  var ContainerWithTooltip = ({
708
716
  children,
@@ -712,45 +720,68 @@ var ContainerWithTooltip = ({
712
720
  name,
713
721
  position
714
722
  }) => {
715
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
716
- "group",
717
- {
718
- ...{
719
- onPointerOver: () => onHover(componentId),
720
- onPointerOut: () => onHover(null)
721
- },
722
- children: [
723
- children,
724
- isHovered && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
725
- import_drei3.Html,
726
- {
727
- position,
728
- style: {
729
- fontFamily: "sans-serif",
730
- transform: "translate3d(50%, 50%, 0)",
731
- backgroundColor: "white",
732
- padding: "5px",
733
- borderRadius: "3px",
734
- pointerEvents: "none"
735
- },
736
- children: name
737
- }
738
- )
739
- ]
723
+ const [mousePosition, setMousePosition] = (0, import_react5.useState)([0, 0, 0]);
724
+ const { camera } = (0, import_fiber4.useThree)();
725
+ const mouseRef = (0, import_react5.useRef)(new THREE2.Vector2());
726
+ (0, import_fiber4.useFrame)(() => {
727
+ if (isHovered) {
728
+ const vector = new THREE2.Vector3(mouseRef.current.x, mouseRef.current.y, 0.5);
729
+ vector.unproject(camera);
730
+ setMousePosition([vector.x, vector.y, vector.z]);
740
731
  }
741
- );
732
+ });
733
+ const groupProps = {
734
+ position,
735
+ onPointerEnter: (e) => {
736
+ e.stopPropagation();
737
+ mouseRef.current.set(
738
+ e.clientX / window.innerWidth * 2 - 1,
739
+ -(e.clientY / window.innerHeight) * 2 + 1
740
+ );
741
+ onHover(componentId);
742
+ },
743
+ onPointerMove: (e) => {
744
+ e.stopPropagation();
745
+ mouseRef.current.set(
746
+ e.clientX / window.innerWidth * 2 - 1,
747
+ -(e.clientY / window.innerHeight) * 2 + 1
748
+ );
749
+ },
750
+ onPointerLeave: (e) => {
751
+ e.stopPropagation();
752
+ onHover(null);
753
+ }
754
+ };
755
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("group", { ...groupProps, children: [
756
+ children,
757
+ isHovered && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
758
+ import_drei3.Html,
759
+ {
760
+ position: mousePosition,
761
+ style: {
762
+ fontFamily: "sans-serif",
763
+ transform: "translate3d(50%, 50%, 0)",
764
+ backgroundColor: "white",
765
+ padding: "5px",
766
+ borderRadius: "3px",
767
+ pointerEvents: "none"
768
+ },
769
+ children: name
770
+ }
771
+ )
772
+ ] });
742
773
  };
743
774
  var ContainerWithTooltip_default = ContainerWithTooltip;
744
775
 
745
776
  // src/hooks/use-global-obj-loader.ts
746
- var import_react5 = require("react");
777
+ var import_react6 = require("react");
747
778
  var import_three_stdlib2 = require("three-stdlib");
748
779
  if (typeof window !== "undefined" && !window.TSCIRCUIT_OBJ_LOADER_CACHE) {
749
780
  window.TSCIRCUIT_OBJ_LOADER_CACHE = /* @__PURE__ */ new Map();
750
781
  }
751
782
  function useGlobalObjLoader(url) {
752
- const [obj, setObj] = (0, import_react5.useState)(null);
753
- (0, import_react5.useEffect)(() => {
783
+ const [obj, setObj] = (0, import_react6.useState)(null);
784
+ (0, import_react6.useEffect)(() => {
754
785
  if (!url) return;
755
786
  const cache = window.TSCIRCUIT_OBJ_LOADER_CACHE;
756
787
  let hasUrlChanged = false;
@@ -868,8 +899,8 @@ function MixedStlModel({
868
899
  var import_jscad_planner = require("jscad-planner");
869
900
  var import_modeling = __toESM(require("@jscad/modeling"));
870
901
  var import_jscad_fiber = require("jscad-fiber");
871
- var THREE2 = __toESM(require("three"));
872
- var import_react6 = require("react");
902
+ var THREE3 = __toESM(require("three"));
903
+ var import_react7 = require("react");
873
904
  var import_jsx_runtime6 = require("react/jsx-runtime");
874
905
  var JscadModel = ({
875
906
  jscadPlan,
@@ -880,19 +911,19 @@ var JscadModel = ({
880
911
  onHover,
881
912
  isHovered
882
913
  }) => {
883
- const { threeGeom, material } = (0, import_react6.useMemo)(() => {
914
+ const { threeGeom, material } = (0, import_react7.useMemo)(() => {
884
915
  const jscadObject = (0, import_jscad_planner.executeJscadOperations)(import_modeling.default, jscadPlan);
885
916
  const threeGeom2 = (0, import_jscad_fiber.convertCSGToThreeGeom)(jscadObject);
886
- const material2 = new THREE2.MeshStandardMaterial({
917
+ const material2 = new THREE3.MeshStandardMaterial({
887
918
  vertexColors: true,
888
- side: THREE2.DoubleSide
919
+ side: THREE3.DoubleSide
889
920
  // Ensure both sides are visible
890
921
  });
891
922
  return { threeGeom: threeGeom2, material: material2 };
892
923
  }, [jscadPlan]);
893
- (0, import_react6.useMemo)(() => {
924
+ (0, import_react7.useMemo)(() => {
894
925
  if (isHovered) {
895
- const color = new THREE2.Color(material.color.getHex());
926
+ const color = new THREE3.Color(material.color.getHex());
896
927
  material.emissive.copy(color);
897
928
  material.emissive.setRGB(0, 0, 1);
898
929
  material.emissiveIntensity = 0.2;
@@ -926,7 +957,7 @@ var JscadModel = ({
926
957
  var import_jscad_electronics = require("jscad-electronics");
927
958
  var import_jscad_fiber2 = require("jscad-fiber");
928
959
  var import_jscad_planner2 = require("jscad-planner");
929
- var import_react7 = require("react");
960
+ var import_react8 = require("react");
930
961
  var import_jsx_runtime7 = require("react/jsx-runtime");
931
962
  var { createJSCADRoot } = (0, import_jscad_fiber2.createJSCADRenderer)(import_jscad_planner2.jscadPlanner);
932
963
  var FootprinterModel = ({
@@ -938,7 +969,7 @@ var FootprinterModel = ({
938
969
  onHover,
939
970
  isHovered
940
971
  }) => {
941
- const jscadPlan = (0, import_react7.useMemo)(() => {
972
+ const jscadPlan = (0, import_react8.useMemo)(() => {
942
973
  if (!footprint) return null;
943
974
  const jscadPlan2 = [];
944
975
  const root = createJSCADRoot(jscadPlan2);
@@ -967,10 +998,10 @@ var tuple = (...args) => args;
967
998
  // src/CadViewer.tsx
968
999
  var import_jsx_runtime8 = require("react/jsx-runtime");
969
1000
  var CadViewer = ({ soup, children }) => {
970
- const [hoveredComponent, setHoveredComponent] = (0, import_react8.useState)(null);
1001
+ const [hoveredComponent, setHoveredComponent] = (0, import_react9.useState)(null);
971
1002
  soup ??= useConvertChildrenToSoup(children, soup);
972
1003
  if (!soup) return null;
973
- const boardGeom = (0, import_react8.useMemo)(() => {
1004
+ const boardGeom = (0, import_react9.useMemo)(() => {
974
1005
  if (!soup.some((e) => e.type === "pcb_board")) return null;
975
1006
  return createBoardGeomFromSoup(soup);
976
1007
  }, [soup]);
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<string | null>(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, loading } = useStlsFromGeom(boardGeom)\n\n const cad_components = su(soup).cad_component.list()\n\n // TODO canvas/camera etc.\n return (\n <CadViewerContainer>\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={setHoveredComponent}\n isHovered={hoveredComponent === 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={setHoveredComponent}\n isHovered={hoveredComponent === 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={setHoveredComponent}\n isHovered={hoveredComponent === 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 // Create pill-shaped hole in board\n const holeRadius = plated_hole.hole_height! / 2\n const pillHole = union(\n cuboid({\n center: [plated_hole.x, plated_hole.y, 0],\n size: [plated_hole.hole_width! - plated_hole.hole_height!, plated_hole.hole_height!, 1.5],\n }),\n cylinder({\n center: [plated_hole.x - (plated_hole.hole_width! - plated_hole.hole_height!) / 2, plated_hole.y, 0],\n radius: holeRadius,\n height: 1.5,\n }),\n cylinder({\n center: [plated_hole.x + (plated_hole.hole_width! - plated_hole.hole_height!) / 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 const subRoutes = mixedRoute.reduce(\n (c, p) => {\n // @ts-ignore\n const lastLayer = c.current?.[c.current.length - 1]?.layer\n if (\n p.route_type === \"via\" ||\n (p.route_type === \"wire\" && p.layer !== lastLayer)\n ) {\n if (c.current.length > 2) {\n c.allPrev.push(c.current)\n }\n c.current = p.route_type === \"wire\" ? [p] : []\n return c\n }\n c.current.push(p)\n return c\n },\n {\n current: [] as typeof mixedRoute,\n allPrev: [] as Array<typeof mixedRoute>,\n },\n )\n for (const route of subRoutes.allPrev.concat([subRoutes.current])) {\n // TODO break into segments based on layers\n const linePath = line(route.map((p) => [p.x, p.y]))\n\n const layer = route[0]!.route_type === \"wire\" ? route[0]!.layer : \"top\"\n const layerSign = layer === \"top\" ? 1 : -1\n // traceGeoms.push(traceGeom)\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 // HACK: Subtract all vias from every trace- this mostly is because the\n // vias aren't inside the route- we should probably pre-filter to make sure\n // that vias are only near the route\n for (const via of pcb_vias) {\n traceGeom = subtract(\n traceGeom,\n cylinder({\n center: [via.x, via.y, 0],\n radius: via.outer_diameter / 2,\n height: 5,\n }),\n )\n }\n for (const ph of plated_holes) {\n if (ph.shape === \"circle\") {\n traceGeom = subtract(\n traceGeom,\n cylinder({\n center: [ph.x, ph.y, 0],\n radius: ph.outer_diameter / 2,\n height: 5,\n }),\n )\n }\n }\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 } if (plated_hole.shape === \"pill\") {\n const holeWidth = plated_hole.hole_width\n const holeHeight = plated_hole.hole_height\n const outerWidth = plated_hole.outer_width || holeWidth + 0.2\n const outerHeight = plated_hole.outer_height || holeHeight + 0.2\n const holeRadius = holeHeight / 2\n const outerRadius = outerHeight / 2\n\n // Create inner hole pill shape\n const mainRect = cuboid({\n center: [plated_hole.x, plated_hole.y, 0],\n size: [holeWidth - holeHeight, holeHeight, 1.2]\n })\n \n const leftCap = cylinder({\n center: [plated_hole.x - (holeWidth - holeHeight)/2, plated_hole.y, 0],\n radius: holeRadius,\n height: 1.2\n })\n\n const rightCap = cylinder({\n center: [plated_hole.x + (holeWidth - holeHeight)/2, plated_hole.y, 0],\n radius: holeRadius,\n height: 1.2\n })\n\n // Create outer pads\n const outerMainRect = cuboid({\n center: [plated_hole.x, plated_hole.y, 1.2/2],\n size: [outerWidth - outerHeight, outerHeight, M]\n })\n\n const outerLeftCap = cylinder({\n center: [plated_hole.x - (outerWidth - outerHeight)/2, plated_hole.y, 1.2/2],\n radius: outerRadius,\n height: M\n })\n\n const outerRightCap = cylinder({\n center: [plated_hole.x + (outerWidth - outerHeight)/2, plated_hole.y, 1.2/2],\n radius: outerRadius,\n height: M\n })\n\n // Bottom pads\n const bottomMainRect = cuboid({\n center: [plated_hole.x, plated_hole.y, -1.2/2],\n size: [outerWidth - outerHeight, outerHeight, M]\n })\n\n const bottomLeftCap = cylinder({\n center: [plated_hole.x - (outerWidth - outerHeight)/2, plated_hole.y, -1.2/2],\n radius: outerRadius,\n height: M\n })\n\n const bottomRightCap = cylinder({\n center: [plated_hole.x + (outerWidth - outerHeight)/2, plated_hole.y, -1.2/2],\n radius: outerRadius,\n height: M\n })\n\n return colorize(\n colors.copper,\n subtract(\n union(\n mainRect, leftCap, rightCap,\n outerMainRect, outerLeftCap, outerRightCap,\n bottomMainRect, bottomLeftCap, bottomRightCap\n ),[\n cuboid({\n center: [plated_hole.x, plated_hole.y, 0],\n size: [holeWidth - holeHeight - M*2, holeHeight - M*2, 1.5]\n }),\n cylinder({\n center: [plated_hole.x - (holeWidth - holeHeight)/2, plated_hole.y, 0],\n radius: holeRadius - M,\n height: 1.5\n }),\n cylinder({\n center: [plated_hole.x + (holeWidth - holeHeight)/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}","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\nexport const CadViewerContainer = ({ children }: { children: any }) => {\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 // rotation: [-Math.PI / 2, 0, 0],\n // lookAt: new THREE.Vector3(0, 0, 0),\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 </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 // color: \"rgba(255, 255, 255, 0.75)\",\n // textShadow:\n // \"0px 0px 1px rgba(0, 0, 0, 0.5), 0px 0px 2px 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.39\",\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 },\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.21\",\n \"jscad-fiber\": \"^0.0.63\",\n \"jscad-planner\": \"^0.0.7\",\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 type { Vector3 } 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: (id: string | null) => void\n isHovered: boolean\n}) => {\n return (\n <group\n {...{\n onPointerOver: () => onHover(componentId),\n onPointerOut: () => onHover(null),\n }}\n >\n {children}\n {isHovered && (\n <Html\n position={position}\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 {name}\n </Html>\n )}\n </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}","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_jsx_runtime","import_drei","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"],"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<string | null>(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, loading } = useStlsFromGeom(boardGeom)\n\n const cad_components = su(soup).cad_component.list()\n\n // TODO canvas/camera etc.\n return (\n <CadViewerContainer>\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={setHoveredComponent}\n isHovered={hoveredComponent === 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={setHoveredComponent}\n isHovered={hoveredComponent === 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={setHoveredComponent}\n isHovered={hoveredComponent === 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 const subRoutes = mixedRoute.reduce(\n (c, p) => {\n // @ts-ignore\n const lastLayer = c.current?.[c.current.length - 1]?.layer\n if (\n p.route_type === \"via\" ||\n (p.route_type === \"wire\" && p.layer !== lastLayer)\n ) {\n if (c.current.length > 2) {\n c.allPrev.push(c.current)\n }\n c.current = p.route_type === \"wire\" ? [p] : []\n return c\n }\n c.current.push(p)\n return c\n },\n {\n current: [] as typeof mixedRoute,\n allPrev: [] as Array<typeof mixedRoute>,\n },\n )\n for (const route of subRoutes.allPrev.concat([subRoutes.current])) {\n // TODO break into segments based on layers\n const linePath = line(route.map((p) => [p.x, p.y]))\n\n const layer = route[0]!.route_type === \"wire\" ? route[0]!.layer : \"top\"\n const layerSign = layer === \"top\" ? 1 : -1\n // traceGeoms.push(traceGeom)\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 // HACK: Subtract all vias from every trace- this mostly is because the\n // vias aren't inside the route- we should probably pre-filter to make sure\n // that vias are only near the route\n for (const via of pcb_vias) {\n traceGeom = subtract(\n traceGeom,\n cylinder({\n center: [via.x, via.y, 0],\n radius: via.outer_diameter / 2,\n height: 5,\n }),\n )\n }\n for (const ph of plated_holes) {\n if (ph.shape === \"circle\") {\n traceGeom = subtract(\n traceGeom,\n cylinder({\n center: [ph.x, ph.y, 0],\n radius: ph.outer_diameter / 2,\n height: 5,\n }),\n )\n }\n }\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\nexport const CadViewerContainer = ({ children }: { children: any }) => {\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 // rotation: [-Math.PI / 2, 0, 0],\n // lookAt: new THREE.Vector3(0, 0, 0),\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 </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 // color: \"rgba(255, 255, 255, 0.75)\",\n // textShadow:\n // \"0px 0px 1px rgba(0, 0, 0, 0.5), 0px 0px 2px 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.41\",\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.21\",\n \"jscad-fiber\": \"^0.0.63\",\n \"jscad-planner\": \"^0.0.7\",\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, useFrame, useThree } from \"@react-three/fiber\"\nimport { useRef, useState } 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: (id: string | null) => void\n isHovered: boolean\n}) => {\n const [mousePosition, setMousePosition] = useState<[number, number, number]>([0, 0, 0])\n const { camera } = useThree()\n const mouseRef = useRef(new THREE.Vector2())\n \n // Update tooltip position on every frame when hovered\n useFrame(() => {\n if (isHovered) {\n // Project the stored mouse coordinates into 3D space\n const vector = new THREE.Vector3(mouseRef.current.x, mouseRef.current.y, 0.5)\n vector.unproject(camera)\n setMousePosition([vector.x, vector.y, vector.z])\n }\n })\n\n const groupProps: GroupProps = {\n position,\n onPointerEnter: (e) => {\n e.stopPropagation()\n // Store normalized mouse coordinates\n mouseRef.current.set(\n (e.clientX / window.innerWidth) * 2 - 1,\n -(e.clientY / window.innerHeight) * 2 + 1\n )\n onHover(componentId)\n },\n onPointerMove: (e) => {\n e.stopPropagation()\n // Update normalized mouse coordinates\n mouseRef.current.set(\n (e.clientX / window.innerWidth) * 2 - 1,\n -(e.clientY / window.innerHeight) * 2 + 1\n )\n },\n onPointerLeave: (e) => {\n e.stopPropagation()\n onHover(null)\n }\n }\n\n return (\n <group {...groupProps}>\n {children}\n {isHovered && (\n <Html\n position={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 {name}\n </Html>\n )}\n </group>\n )\n}\n\nexport default ContainerWithTooltip","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_jsx_runtime","import_drei","import_fiber","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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/3d-viewer",
3
- "version": "0.0.40",
3
+ "version": "0.0.42",
4
4
  "main": "./dist/index.js",
5
5
  "files": [
6
6
  "dist"
@@ -12,7 +12,8 @@
12
12
  "prepublish": "npm run build",
13
13
  "preview": "vite preview",
14
14
  "storybook": "storybook dev -p 6006",
15
- "build-storybook": "storybook build"
15
+ "build-storybook": "storybook build",
16
+ "format": "biome format . --write"
16
17
  },
17
18
  "dependencies": {
18
19
  "@jscad/modeling": "^2.12.2",