@tscircuit/3d-viewer 0.0.351 → 0.0.353
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +6 -5
- package/dist/index.js +255 -262
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import * as THREE from 'three';
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
2
|
import { AnyCircuitElement, PcbBoard } from 'circuit-json';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import * as THREE from 'three';
|
|
4
5
|
import { GLTFExporterOptions } from 'three-stdlib';
|
|
5
6
|
import { ManifoldToplevel } from 'manifold-3d/manifold.d.ts';
|
|
6
7
|
import { JSDOM } from 'jsdom';
|
|
7
8
|
|
|
8
|
-
declare const CadViewer:
|
|
9
|
+
declare const CadViewer: (props: any) => react_jsx_runtime.JSX.Element;
|
|
9
10
|
|
|
10
11
|
interface CircuitToSvgOptions {
|
|
11
12
|
width?: number;
|
|
@@ -33,11 +34,11 @@ type Options = Omit<GLTFExporterOptions, "animations" | "includeCustomExtensions
|
|
|
33
34
|
declare function useSaveGltfAs(options?: Options & {
|
|
34
35
|
filename?: string;
|
|
35
36
|
}): [
|
|
36
|
-
ref3D:
|
|
37
|
+
ref3D: React.ForwardedRef<THREE.Object3D>,
|
|
37
38
|
saveAs: (filename?: string) => Promise<void>
|
|
38
39
|
];
|
|
39
40
|
declare function useExportGltfUrl(options?: Options): [
|
|
40
|
-
ref3D:
|
|
41
|
+
ref3D: React.ForwardedRef<THREE.Object3D>,
|
|
41
42
|
url: string | undefined,
|
|
42
43
|
error: ErrorEvent | undefined
|
|
43
44
|
];
|
package/dist/index.js
CHANGED
|
@@ -14228,7 +14228,7 @@ var require_browser = __commonJS({
|
|
|
14228
14228
|
});
|
|
14229
14229
|
|
|
14230
14230
|
// src/CadViewer.tsx
|
|
14231
|
-
import { useState as
|
|
14231
|
+
import { useState as useState15, useCallback as useCallback8, useRef as useRef9, useEffect as useEffect22 } from "react";
|
|
14232
14232
|
|
|
14233
14233
|
// src/CadViewerJscad.tsx
|
|
14234
14234
|
import { su as su4 } from "@tscircuit/circuit-json-util";
|
|
@@ -25583,7 +25583,7 @@ import * as THREE10 from "three";
|
|
|
25583
25583
|
// package.json
|
|
25584
25584
|
var package_default = {
|
|
25585
25585
|
name: "@tscircuit/3d-viewer",
|
|
25586
|
-
version: "0.0.
|
|
25586
|
+
version: "0.0.352",
|
|
25587
25587
|
main: "./dist/index.js",
|
|
25588
25588
|
module: "./dist/index.js",
|
|
25589
25589
|
type: "module",
|
|
@@ -25912,6 +25912,7 @@ var Canvas = forwardRef(
|
|
|
25912
25912
|
}
|
|
25913
25913
|
camera.lookAt(0, 0, 0);
|
|
25914
25914
|
scene.add(rootObject.current);
|
|
25915
|
+
window.__TSCIRCUIT_THREE_OBJECT = rootObject.current;
|
|
25915
25916
|
setContextState({
|
|
25916
25917
|
scene,
|
|
25917
25918
|
camera,
|
|
@@ -25949,6 +25950,9 @@ var Canvas = forwardRef(
|
|
|
25949
25950
|
}
|
|
25950
25951
|
renderer.dispose();
|
|
25951
25952
|
scene.remove(rootObject.current);
|
|
25953
|
+
if (window.__TSCIRCUIT_THREE_OBJECT === rootObject.current) {
|
|
25954
|
+
window.__TSCIRCUIT_THREE_OBJECT = void 0;
|
|
25955
|
+
}
|
|
25952
25956
|
};
|
|
25953
25957
|
}, [scene, addFrameListener, removeFrameListener]);
|
|
25954
25958
|
return /* @__PURE__ */ jsx9("div", { ref: mountRef, style: { width: "100%", height: "100%", ...style }, children: contextState && /* @__PURE__ */ jsx9(ThreeContext.Provider, { value: contextState, children: /* @__PURE__ */ jsx9(HoverProvider, { children }) }) });
|
|
@@ -25994,14 +25998,9 @@ var OrbitControls = ({
|
|
|
25994
25998
|
]);
|
|
25995
25999
|
useEffect11(() => {
|
|
25996
26000
|
if (!controls || !onStart) return;
|
|
25997
|
-
|
|
25998
|
-
if (event.button !== 2) {
|
|
25999
|
-
onStart();
|
|
26000
|
-
}
|
|
26001
|
-
};
|
|
26002
|
-
controls.addEventListener("start", handleStart);
|
|
26001
|
+
controls.addEventListener("start", onStart);
|
|
26003
26002
|
return () => {
|
|
26004
|
-
controls.removeEventListener("start",
|
|
26003
|
+
controls.removeEventListener("start", onStart);
|
|
26005
26004
|
};
|
|
26006
26005
|
}, [controls, onStart]);
|
|
26007
26006
|
useEffect11(() => {
|
|
@@ -27768,7 +27767,7 @@ var CadViewerJscad = forwardRef3(
|
|
|
27768
27767
|
|
|
27769
27768
|
// src/CadViewerManifold.tsx
|
|
27770
27769
|
import { su as su13 } from "@tscircuit/circuit-json-util";
|
|
27771
|
-
import {
|
|
27770
|
+
import { useEffect as useEffect20, useMemo as useMemo18, useState as useState13 } from "react";
|
|
27772
27771
|
|
|
27773
27772
|
// src/hooks/useManifoldBoardBuilder.ts
|
|
27774
27773
|
import { useState as useState12, useEffect as useEffect19, useMemo as useMemo17, useRef as useRef7 } from "react";
|
|
@@ -28878,51 +28877,50 @@ var BoardMeshes = ({
|
|
|
28878
28877
|
return null;
|
|
28879
28878
|
};
|
|
28880
28879
|
var MANIFOLD_CDN_BASE_URL = "https://cdn.jsdelivr.net/npm/manifold-3d@3.2.1";
|
|
28881
|
-
var CadViewerManifold =
|
|
28882
|
-
|
|
28883
|
-
|
|
28884
|
-
|
|
28885
|
-
|
|
28886
|
-
|
|
28887
|
-
|
|
28888
|
-
|
|
28889
|
-
|
|
28890
|
-
|
|
28891
|
-
|
|
28892
|
-
|
|
28893
|
-
|
|
28894
|
-
|
|
28895
|
-
|
|
28896
|
-
|
|
28897
|
-
|
|
28898
|
-
|
|
28899
|
-
|
|
28900
|
-
|
|
28901
|
-
|
|
28902
|
-
|
|
28903
|
-
|
|
28904
|
-
|
|
28905
|
-
|
|
28906
|
-
|
|
28907
|
-
|
|
28880
|
+
var CadViewerManifold = ({
|
|
28881
|
+
circuitJson: circuitJsonProp,
|
|
28882
|
+
autoRotateDisabled,
|
|
28883
|
+
clickToInteractEnabled,
|
|
28884
|
+
onUserInteraction,
|
|
28885
|
+
children
|
|
28886
|
+
}) => {
|
|
28887
|
+
const childrenCircuitJson = useConvertChildrenToSoup(children);
|
|
28888
|
+
const circuitJson = useMemo18(() => {
|
|
28889
|
+
return circuitJsonProp ?? childrenCircuitJson;
|
|
28890
|
+
}, [circuitJsonProp, childrenCircuitJson]);
|
|
28891
|
+
const [manifoldJSModule, setManifoldJSModule] = useState13(null);
|
|
28892
|
+
const [manifoldLoadingError, setManifoldLoadingError] = useState13(null);
|
|
28893
|
+
useEffect20(() => {
|
|
28894
|
+
const initManifold = async (ManifoldModule) => {
|
|
28895
|
+
try {
|
|
28896
|
+
const loadedModule = await ManifoldModule();
|
|
28897
|
+
loadedModule.setup();
|
|
28898
|
+
setManifoldJSModule(loadedModule);
|
|
28899
|
+
} catch (error) {
|
|
28900
|
+
console.error("Failed to initialize Manifold:", error);
|
|
28901
|
+
setManifoldLoadingError(
|
|
28902
|
+
`Failed to initialize Manifold: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
28903
|
+
);
|
|
28904
|
+
}
|
|
28905
|
+
};
|
|
28906
|
+
if (window.ManifoldModule) {
|
|
28907
|
+
initManifold(window.ManifoldModule);
|
|
28908
|
+
return;
|
|
28909
|
+
}
|
|
28910
|
+
const eventName = "manifoldLoaded";
|
|
28911
|
+
const handleLoad = () => {
|
|
28908
28912
|
if (window.ManifoldModule) {
|
|
28909
28913
|
initManifold(window.ManifoldModule);
|
|
28910
|
-
|
|
28914
|
+
} else {
|
|
28915
|
+
const errText = "ManifoldModule not found on window after script load.";
|
|
28916
|
+
console.error(errText);
|
|
28917
|
+
setManifoldLoadingError(errText);
|
|
28911
28918
|
}
|
|
28912
|
-
|
|
28913
|
-
|
|
28914
|
-
|
|
28915
|
-
|
|
28916
|
-
|
|
28917
|
-
const errText = "ManifoldModule not found on window after script load.";
|
|
28918
|
-
console.error(errText);
|
|
28919
|
-
setManifoldLoadingError(errText);
|
|
28920
|
-
}
|
|
28921
|
-
};
|
|
28922
|
-
window.addEventListener(eventName, handleLoad, { once: true });
|
|
28923
|
-
const script = document.createElement("script");
|
|
28924
|
-
script.type = "module";
|
|
28925
|
-
script.innerHTML = `
|
|
28919
|
+
};
|
|
28920
|
+
window.addEventListener(eventName, handleLoad, { once: true });
|
|
28921
|
+
const script = document.createElement("script");
|
|
28922
|
+
script.type = "module";
|
|
28923
|
+
script.innerHTML = `
|
|
28926
28924
|
try {
|
|
28927
28925
|
const { default: ManifoldModule } = await import('${MANIFOLD_CDN_BASE_URL}/manifold.js');
|
|
28928
28926
|
window.ManifoldModule = ManifoldModule;
|
|
@@ -28932,125 +28930,123 @@ try {
|
|
|
28932
28930
|
window.dispatchEvent(new CustomEvent('${eventName}'));
|
|
28933
28931
|
}
|
|
28934
28932
|
`.trim();
|
|
28935
|
-
|
|
28936
|
-
|
|
28937
|
-
|
|
28938
|
-
|
|
28939
|
-
|
|
28940
|
-
|
|
28941
|
-
|
|
28942
|
-
|
|
28943
|
-
|
|
28944
|
-
|
|
28945
|
-
|
|
28946
|
-
|
|
28947
|
-
|
|
28948
|
-
|
|
28949
|
-
|
|
28950
|
-
|
|
28951
|
-
|
|
28952
|
-
|
|
28953
|
-
|
|
28954
|
-
|
|
28955
|
-
|
|
28956
|
-
|
|
28957
|
-
|
|
28958
|
-
|
|
28959
|
-
|
|
28960
|
-
|
|
28961
|
-
|
|
28962
|
-
|
|
28963
|
-
|
|
28933
|
+
const scriptError = (err) => {
|
|
28934
|
+
const errText = "Failed to load Manifold loader script.";
|
|
28935
|
+
console.error(errText, err);
|
|
28936
|
+
setManifoldLoadingError(errText);
|
|
28937
|
+
window.removeEventListener(eventName, handleLoad);
|
|
28938
|
+
};
|
|
28939
|
+
script.addEventListener("error", scriptError);
|
|
28940
|
+
document.body.appendChild(script);
|
|
28941
|
+
return () => {
|
|
28942
|
+
window.removeEventListener(eventName, handleLoad);
|
|
28943
|
+
script.removeEventListener("error", scriptError);
|
|
28944
|
+
};
|
|
28945
|
+
}, []);
|
|
28946
|
+
const {
|
|
28947
|
+
geoms,
|
|
28948
|
+
textures,
|
|
28949
|
+
pcbThickness,
|
|
28950
|
+
error: builderError,
|
|
28951
|
+
isLoading: builderIsLoading,
|
|
28952
|
+
boardData
|
|
28953
|
+
} = useManifoldBoardBuilder(manifoldJSModule, circuitJson);
|
|
28954
|
+
const geometryMeshes = useMemo18(() => createGeometryMeshes(geoms), [geoms]);
|
|
28955
|
+
const textureMeshes = useMemo18(
|
|
28956
|
+
() => createTextureMeshes(textures, boardData, pcbThickness),
|
|
28957
|
+
[textures, boardData, pcbThickness]
|
|
28958
|
+
);
|
|
28959
|
+
const cadComponents = useMemo18(
|
|
28960
|
+
() => su13(circuitJson).cad_component.list(),
|
|
28961
|
+
[circuitJson]
|
|
28962
|
+
);
|
|
28963
|
+
const boardDimensions = useMemo18(() => {
|
|
28964
|
+
if (!boardData) return void 0;
|
|
28965
|
+
const { width: width10 = 0, height: height10 = 0 } = boardData;
|
|
28966
|
+
return { width: width10, height: height10 };
|
|
28967
|
+
}, [boardData]);
|
|
28968
|
+
const initialCameraPosition = useMemo18(() => {
|
|
28969
|
+
if (!boardData) return [5, 5, 5];
|
|
28970
|
+
const { width: width10 = 0, height: height10 = 0 } = boardData;
|
|
28971
|
+
const safeWidth = Math.max(width10, 1);
|
|
28972
|
+
const safeHeight = Math.max(height10, 1);
|
|
28973
|
+
const largestDim = Math.max(safeWidth, safeHeight, 5);
|
|
28974
|
+
return [largestDim * 0.75, largestDim * 0.75, largestDim * 0.75];
|
|
28975
|
+
}, [boardData]);
|
|
28976
|
+
if (manifoldLoadingError) {
|
|
28977
|
+
return /* @__PURE__ */ jsxs7(
|
|
28978
|
+
"div",
|
|
28979
|
+
{
|
|
28980
|
+
style: {
|
|
28981
|
+
color: "red",
|
|
28982
|
+
padding: "1em",
|
|
28983
|
+
border: "1px solid red",
|
|
28984
|
+
margin: "1em"
|
|
28985
|
+
},
|
|
28986
|
+
children: [
|
|
28987
|
+
"Error: ",
|
|
28988
|
+
manifoldLoadingError
|
|
28989
|
+
]
|
|
28990
|
+
}
|
|
28964
28991
|
);
|
|
28965
|
-
|
|
28966
|
-
|
|
28967
|
-
|
|
28968
|
-
|
|
28969
|
-
|
|
28970
|
-
const initialCameraPosition = useMemo18(() => {
|
|
28971
|
-
if (!boardData) return [5, 5, 5];
|
|
28972
|
-
const { width: width10 = 0, height: height10 = 0 } = boardData;
|
|
28973
|
-
const safeWidth = Math.max(width10, 1);
|
|
28974
|
-
const safeHeight = Math.max(height10, 1);
|
|
28975
|
-
const largestDim = Math.max(safeWidth, safeHeight, 5);
|
|
28976
|
-
return [largestDim * 0.75, largestDim * 0.75, largestDim * 0.75];
|
|
28977
|
-
}, [boardData]);
|
|
28978
|
-
if (manifoldLoadingError) {
|
|
28979
|
-
return /* @__PURE__ */ jsxs7(
|
|
28980
|
-
"div",
|
|
28981
|
-
{
|
|
28982
|
-
style: {
|
|
28983
|
-
color: "red",
|
|
28984
|
-
padding: "1em",
|
|
28985
|
-
border: "1px solid red",
|
|
28986
|
-
margin: "1em"
|
|
28987
|
-
},
|
|
28988
|
-
children: [
|
|
28989
|
-
"Error: ",
|
|
28990
|
-
manifoldLoadingError
|
|
28991
|
-
]
|
|
28992
|
-
}
|
|
28993
|
-
);
|
|
28994
|
-
}
|
|
28995
|
-
if (!manifoldJSModule) {
|
|
28996
|
-
return /* @__PURE__ */ jsx13("div", { style: { padding: "1em" }, children: "Loading Manifold module..." });
|
|
28997
|
-
}
|
|
28998
|
-
if (builderError) {
|
|
28999
|
-
return /* @__PURE__ */ jsxs7(
|
|
29000
|
-
"div",
|
|
29001
|
-
{
|
|
29002
|
-
style: {
|
|
29003
|
-
color: "red",
|
|
29004
|
-
padding: "1em",
|
|
29005
|
-
border: "1px solid red",
|
|
29006
|
-
margin: "1em"
|
|
29007
|
-
},
|
|
29008
|
-
children: [
|
|
29009
|
-
"Error: ",
|
|
29010
|
-
builderError
|
|
29011
|
-
]
|
|
29012
|
-
}
|
|
29013
|
-
);
|
|
29014
|
-
}
|
|
29015
|
-
if (builderIsLoading) {
|
|
29016
|
-
return /* @__PURE__ */ jsx13("div", { style: { padding: "1em" }, children: "Processing board geometry..." });
|
|
29017
|
-
}
|
|
28992
|
+
}
|
|
28993
|
+
if (!manifoldJSModule) {
|
|
28994
|
+
return /* @__PURE__ */ jsx13("div", { style: { padding: "1em" }, children: "Loading Manifold module..." });
|
|
28995
|
+
}
|
|
28996
|
+
if (builderError) {
|
|
29018
28997
|
return /* @__PURE__ */ jsxs7(
|
|
29019
|
-
|
|
28998
|
+
"div",
|
|
29020
28999
|
{
|
|
29021
|
-
|
|
29022
|
-
|
|
29023
|
-
|
|
29024
|
-
|
|
29025
|
-
|
|
29026
|
-
|
|
29000
|
+
style: {
|
|
29001
|
+
color: "red",
|
|
29002
|
+
padding: "1em",
|
|
29003
|
+
border: "1px solid red",
|
|
29004
|
+
margin: "1em"
|
|
29005
|
+
},
|
|
29027
29006
|
children: [
|
|
29028
|
-
|
|
29029
|
-
|
|
29030
|
-
{
|
|
29031
|
-
geometryMeshes,
|
|
29032
|
-
textureMeshes
|
|
29033
|
-
}
|
|
29034
|
-
),
|
|
29035
|
-
cadComponents.map((cad_component2) => /* @__PURE__ */ jsx13(
|
|
29036
|
-
ThreeErrorBoundary,
|
|
29037
|
-
{
|
|
29038
|
-
fallback: ({ error }) => /* @__PURE__ */ jsx13(Error3d, { cad_component: cad_component2, error }),
|
|
29039
|
-
children: /* @__PURE__ */ jsx13(
|
|
29040
|
-
AnyCadComponent,
|
|
29041
|
-
{
|
|
29042
|
-
cad_component: cad_component2,
|
|
29043
|
-
circuitJson
|
|
29044
|
-
}
|
|
29045
|
-
)
|
|
29046
|
-
},
|
|
29047
|
-
cad_component2.cad_component_id
|
|
29048
|
-
))
|
|
29007
|
+
"Error: ",
|
|
29008
|
+
builderError
|
|
29049
29009
|
]
|
|
29050
29010
|
}
|
|
29051
29011
|
);
|
|
29052
29012
|
}
|
|
29053
|
-
)
|
|
29013
|
+
if (builderIsLoading) {
|
|
29014
|
+
return /* @__PURE__ */ jsx13("div", { style: { padding: "1em" }, children: "Processing board geometry..." });
|
|
29015
|
+
}
|
|
29016
|
+
return /* @__PURE__ */ jsxs7(
|
|
29017
|
+
CadViewerContainer,
|
|
29018
|
+
{
|
|
29019
|
+
initialCameraPosition,
|
|
29020
|
+
autoRotateDisabled,
|
|
29021
|
+
clickToInteractEnabled,
|
|
29022
|
+
boardDimensions,
|
|
29023
|
+
onUserInteraction,
|
|
29024
|
+
children: [
|
|
29025
|
+
/* @__PURE__ */ jsx13(
|
|
29026
|
+
BoardMeshes,
|
|
29027
|
+
{
|
|
29028
|
+
geometryMeshes,
|
|
29029
|
+
textureMeshes
|
|
29030
|
+
}
|
|
29031
|
+
),
|
|
29032
|
+
cadComponents.map((cad_component2) => /* @__PURE__ */ jsx13(
|
|
29033
|
+
ThreeErrorBoundary,
|
|
29034
|
+
{
|
|
29035
|
+
fallback: ({ error }) => /* @__PURE__ */ jsx13(Error3d, { cad_component: cad_component2, error }),
|
|
29036
|
+
children: /* @__PURE__ */ jsx13(
|
|
29037
|
+
AnyCadComponent,
|
|
29038
|
+
{
|
|
29039
|
+
cad_component: cad_component2,
|
|
29040
|
+
circuitJson
|
|
29041
|
+
}
|
|
29042
|
+
)
|
|
29043
|
+
},
|
|
29044
|
+
cad_component2.cad_component_id
|
|
29045
|
+
))
|
|
29046
|
+
]
|
|
29047
|
+
}
|
|
29048
|
+
);
|
|
29049
|
+
};
|
|
29054
29050
|
var CadViewerManifold_default = CadViewerManifold;
|
|
29055
29051
|
|
|
29056
29052
|
// src/hooks/useContextMenu.ts
|
|
@@ -29155,87 +29151,42 @@ var useContextMenu = ({ containerRef }) => {
|
|
|
29155
29151
|
};
|
|
29156
29152
|
};
|
|
29157
29153
|
|
|
29158
|
-
// src/hooks/
|
|
29154
|
+
// src/hooks/useGlobalDownloadGltf.ts
|
|
29155
|
+
import { useCallback as useCallback7 } from "react";
|
|
29159
29156
|
import { GLTFExporter } from "three-stdlib";
|
|
29160
|
-
|
|
29161
|
-
|
|
29162
|
-
|
|
29163
|
-
|
|
29164
|
-
|
|
29165
|
-
const saveAs = async (filename) => {
|
|
29166
|
-
const name = filename ?? options.filename ?? "";
|
|
29167
|
-
if (options.binary == null) options.binary = name.endsWith(".glb");
|
|
29168
|
-
if (!instanceRef.current) {
|
|
29169
|
-
console.error("No 3D object available for export");
|
|
29170
|
-
return;
|
|
29171
|
-
}
|
|
29172
|
-
try {
|
|
29173
|
-
const url = await parse(instanceRef.current);
|
|
29174
|
-
link.download = name;
|
|
29175
|
-
link.href = url;
|
|
29176
|
-
link.dispatchEvent(new MouseEvent("click"));
|
|
29177
|
-
URL.revokeObjectURL(url);
|
|
29178
|
-
} catch (error) {
|
|
29179
|
-
console.error("Failed to export GLTF:", error);
|
|
29180
|
-
}
|
|
29181
|
-
};
|
|
29182
|
-
useEffect22(
|
|
29183
|
-
() => () => {
|
|
29184
|
-
link.remove();
|
|
29185
|
-
instanceRef.current = null;
|
|
29186
|
-
},
|
|
29187
|
-
[]
|
|
29188
|
-
);
|
|
29189
|
-
const ref = useCallback7((obj3D) => {
|
|
29190
|
-
instanceRef.current = obj3D;
|
|
29191
|
-
}, []);
|
|
29192
|
-
return [ref, saveAs];
|
|
29193
|
-
}
|
|
29194
|
-
function useExportGltfUrl(options = {}) {
|
|
29195
|
-
const parse = useParser(options);
|
|
29196
|
-
const [url, setUrl] = useState15();
|
|
29197
|
-
const [error, setError] = useState15();
|
|
29198
|
-
const instanceRef = useRef9(null);
|
|
29199
|
-
const ref = useCallback7(
|
|
29200
|
-
(instance) => {
|
|
29201
|
-
instanceRef.current = instance;
|
|
29202
|
-
if (instance) {
|
|
29203
|
-
parse(instance).then(setUrl).catch(setError);
|
|
29204
|
-
}
|
|
29205
|
-
},
|
|
29206
|
-
[parse]
|
|
29207
|
-
);
|
|
29208
|
-
useEffect22(() => () => URL.revokeObjectURL(url), [url]);
|
|
29209
|
-
return [ref, url, error];
|
|
29210
|
-
}
|
|
29211
|
-
function useParser(options = {}) {
|
|
29212
|
-
const exporter = useMemo19(() => new GLTFExporter(), []);
|
|
29213
|
-
return (instance) => {
|
|
29214
|
-
const { promise, resolve, reject } = Promise.withResolvers();
|
|
29157
|
+
var useGlobalDownloadGltf = () => {
|
|
29158
|
+
return useCallback7(() => {
|
|
29159
|
+
const root = window.__TSCIRCUIT_THREE_OBJECT;
|
|
29160
|
+
if (!root) return;
|
|
29161
|
+
const exporter = new GLTFExporter();
|
|
29215
29162
|
exporter.parse(
|
|
29216
|
-
|
|
29163
|
+
root,
|
|
29217
29164
|
(gltf) => {
|
|
29218
|
-
const type = options.binary ? "gltf-binary" : "gltf+json";
|
|
29219
29165
|
const blob = new Blob(
|
|
29220
29166
|
[gltf instanceof ArrayBuffer ? gltf : JSON.stringify(gltf)],
|
|
29221
|
-
{ type:
|
|
29167
|
+
{ type: "model/gltf+json" }
|
|
29222
29168
|
);
|
|
29223
|
-
|
|
29169
|
+
const url = URL.createObjectURL(blob);
|
|
29170
|
+
const link = document.createElement("a");
|
|
29171
|
+
link.href = url;
|
|
29172
|
+
link.download = "scene.gltf";
|
|
29173
|
+
link.click();
|
|
29174
|
+
URL.revokeObjectURL(url);
|
|
29224
29175
|
},
|
|
29225
|
-
|
|
29226
|
-
|
|
29176
|
+
(err) => {
|
|
29177
|
+
console.error("Failed to export GLTF", err);
|
|
29178
|
+
}
|
|
29227
29179
|
);
|
|
29228
|
-
|
|
29229
|
-
|
|
29230
|
-
}
|
|
29180
|
+
}, []);
|
|
29181
|
+
};
|
|
29231
29182
|
|
|
29232
29183
|
// src/CadViewer.tsx
|
|
29233
29184
|
import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
29234
|
-
var CadViewer =
|
|
29235
|
-
const [engine, setEngine] =
|
|
29236
|
-
const containerRef =
|
|
29237
|
-
const [autoRotate, setAutoRotate] =
|
|
29238
|
-
const [autoRotateUserToggled, setAutoRotateUserToggled] =
|
|
29185
|
+
var CadViewer = (props) => {
|
|
29186
|
+
const [engine, setEngine] = useState15("manifold");
|
|
29187
|
+
const containerRef = useRef9(null);
|
|
29188
|
+
const [autoRotate, setAutoRotate] = useState15(true);
|
|
29189
|
+
const [autoRotateUserToggled, setAutoRotateUserToggled] = useState15(false);
|
|
29239
29190
|
const {
|
|
29240
29191
|
menuVisible,
|
|
29241
29192
|
menuPos,
|
|
@@ -29243,21 +29194,7 @@ var CadViewer = forwardRef5((props, ref) => {
|
|
|
29243
29194
|
contextMenuEventHandlers,
|
|
29244
29195
|
setMenuVisible
|
|
29245
29196
|
} = useContextMenu({ containerRef });
|
|
29246
|
-
const
|
|
29247
|
-
function useCombinedRefs(...refs) {
|
|
29248
|
-
return useCallback8(
|
|
29249
|
-
(value) => {
|
|
29250
|
-
refs.forEach((ref2) => {
|
|
29251
|
-
if (!ref2) return;
|
|
29252
|
-
if (typeof ref2 === "function") ref2(value);
|
|
29253
|
-
else ref2.current = value;
|
|
29254
|
-
});
|
|
29255
|
-
},
|
|
29256
|
-
[refs]
|
|
29257
|
-
);
|
|
29258
|
-
}
|
|
29259
|
-
const mergedRef = useCombinedRefs(ref, sceneRef);
|
|
29260
|
-
const autoRotateUserToggledRef = useRef10(autoRotateUserToggled);
|
|
29197
|
+
const autoRotateUserToggledRef = useRef9(autoRotateUserToggled);
|
|
29261
29198
|
autoRotateUserToggledRef.current = autoRotateUserToggled;
|
|
29262
29199
|
const handleUserInteraction = useCallback8(() => {
|
|
29263
29200
|
if (!autoRotateUserToggledRef.current) {
|
|
@@ -29268,21 +29205,18 @@ var CadViewer = forwardRef5((props, ref) => {
|
|
|
29268
29205
|
setAutoRotate((prev) => !prev);
|
|
29269
29206
|
setAutoRotateUserToggled(true);
|
|
29270
29207
|
}, []);
|
|
29208
|
+
const downloadGltf = useGlobalDownloadGltf();
|
|
29271
29209
|
const handleMenuClick = (newEngine) => {
|
|
29272
29210
|
setEngine(newEngine);
|
|
29273
29211
|
setMenuVisible(false);
|
|
29274
29212
|
};
|
|
29275
|
-
|
|
29276
|
-
saveGltfAs("pcb.glb");
|
|
29277
|
-
setMenuVisible(false);
|
|
29278
|
-
}, [saveGltfAs, setMenuVisible]);
|
|
29279
|
-
useEffect23(() => {
|
|
29213
|
+
useEffect22(() => {
|
|
29280
29214
|
const stored = window.localStorage.getItem("cadViewerEngine");
|
|
29281
29215
|
if (stored === "jscad" || stored === "manifold") {
|
|
29282
29216
|
setEngine(stored);
|
|
29283
29217
|
}
|
|
29284
29218
|
}, []);
|
|
29285
|
-
|
|
29219
|
+
useEffect22(() => {
|
|
29286
29220
|
window.localStorage.setItem("cadViewerEngine", engine);
|
|
29287
29221
|
}, [engine]);
|
|
29288
29222
|
const viewerKey = props.circuitJson ? JSON.stringify(props.circuitJson) : void 0;
|
|
@@ -29297,19 +29231,15 @@ var CadViewer = forwardRef5((props, ref) => {
|
|
|
29297
29231
|
CadViewerJscad,
|
|
29298
29232
|
{
|
|
29299
29233
|
...props,
|
|
29300
|
-
ref: mergedRef,
|
|
29301
29234
|
autoRotateDisabled: props.autoRotateDisabled || !autoRotate,
|
|
29302
|
-
onUserInteraction: handleUserInteraction
|
|
29303
|
-
children: props.children
|
|
29235
|
+
onUserInteraction: handleUserInteraction
|
|
29304
29236
|
}
|
|
29305
29237
|
) : /* @__PURE__ */ jsx14(
|
|
29306
29238
|
CadViewerManifold_default,
|
|
29307
29239
|
{
|
|
29308
29240
|
...props,
|
|
29309
|
-
ref: mergedRef,
|
|
29310
29241
|
autoRotateDisabled: props.autoRotateDisabled || !autoRotate,
|
|
29311
|
-
onUserInteraction: handleUserInteraction
|
|
29312
|
-
children: props.children
|
|
29242
|
+
onUserInteraction: handleUserInteraction
|
|
29313
29243
|
}
|
|
29314
29244
|
),
|
|
29315
29245
|
/* @__PURE__ */ jsxs8(
|
|
@@ -29430,7 +29360,10 @@ var CadViewer = forwardRef5((props, ref) => {
|
|
|
29430
29360
|
borderRadius: 6,
|
|
29431
29361
|
transition: "background 0.1s"
|
|
29432
29362
|
},
|
|
29433
|
-
onClick:
|
|
29363
|
+
onClick: () => {
|
|
29364
|
+
downloadGltf();
|
|
29365
|
+
setMenuVisible(false);
|
|
29366
|
+
},
|
|
29434
29367
|
onMouseOver: (e) => e.currentTarget.style.background = "#2d313a",
|
|
29435
29368
|
onMouseOut: (e) => e.currentTarget.style.background = "transparent",
|
|
29436
29369
|
children: "Download GLTF"
|
|
@@ -29470,7 +29403,7 @@ var CadViewer = forwardRef5((props, ref) => {
|
|
|
29470
29403
|
},
|
|
29471
29404
|
viewerKey
|
|
29472
29405
|
);
|
|
29473
|
-
}
|
|
29406
|
+
};
|
|
29474
29407
|
|
|
29475
29408
|
// src/convert-circuit-json-to-3d-svg.ts
|
|
29476
29409
|
var import_debug = __toESM(require_browser(), 1);
|
|
@@ -29739,6 +29672,66 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
29739
29672
|
return serialized;
|
|
29740
29673
|
}
|
|
29741
29674
|
|
|
29675
|
+
// src/hooks/exporter/gltf.ts
|
|
29676
|
+
import { GLTFExporter as GLTFExporter2 } from "three-stdlib";
|
|
29677
|
+
import { useEffect as useEffect23, useState as useState16, useMemo as useMemo19, useCallback as useCallback9 } from "react";
|
|
29678
|
+
function useSaveGltfAs(options = {}) {
|
|
29679
|
+
const parse = useParser(options);
|
|
29680
|
+
const link = useMemo19(() => document.createElement("a"), []);
|
|
29681
|
+
const saveAs = async (filename) => {
|
|
29682
|
+
const name = filename ?? options.filename ?? "";
|
|
29683
|
+
if (options.binary == null) options.binary = name.endsWith(".glb");
|
|
29684
|
+
const url = await parse(instance);
|
|
29685
|
+
link.download = name;
|
|
29686
|
+
link.href = url;
|
|
29687
|
+
link.dispatchEvent(new MouseEvent("click"));
|
|
29688
|
+
URL.revokeObjectURL(url);
|
|
29689
|
+
};
|
|
29690
|
+
useEffect23(
|
|
29691
|
+
() => () => {
|
|
29692
|
+
link.remove();
|
|
29693
|
+
instance = null;
|
|
29694
|
+
},
|
|
29695
|
+
[]
|
|
29696
|
+
);
|
|
29697
|
+
let instance;
|
|
29698
|
+
const ref = useCallback9((obj3D) => {
|
|
29699
|
+
instance = obj3D;
|
|
29700
|
+
}, []);
|
|
29701
|
+
return [ref, saveAs];
|
|
29702
|
+
}
|
|
29703
|
+
function useExportGltfUrl(options = {}) {
|
|
29704
|
+
const parse = useParser(options);
|
|
29705
|
+
const [url, setUrl] = useState16();
|
|
29706
|
+
const [error, setError] = useState16();
|
|
29707
|
+
const ref = useCallback9(
|
|
29708
|
+
(instance) => parse(instance).then(setUrl).catch(setError),
|
|
29709
|
+
[]
|
|
29710
|
+
);
|
|
29711
|
+
useEffect23(() => () => URL.revokeObjectURL(url), [url]);
|
|
29712
|
+
return [ref, url, error];
|
|
29713
|
+
}
|
|
29714
|
+
function useParser(options = {}) {
|
|
29715
|
+
const exporter = useMemo19(() => new GLTFExporter2(), []);
|
|
29716
|
+
return (instance) => {
|
|
29717
|
+
const { promise, resolve, reject } = Promise.withResolvers();
|
|
29718
|
+
exporter.parse(
|
|
29719
|
+
instance,
|
|
29720
|
+
(gltf) => {
|
|
29721
|
+
const type = options.binary ? "gltf-binary" : "gltf+json";
|
|
29722
|
+
const blob = new Blob(
|
|
29723
|
+
[gltf instanceof ArrayBuffer ? gltf : JSON.stringify(gltf)],
|
|
29724
|
+
{ type: `model/${type}` }
|
|
29725
|
+
);
|
|
29726
|
+
resolve(URL.createObjectURL(blob));
|
|
29727
|
+
},
|
|
29728
|
+
reject,
|
|
29729
|
+
options
|
|
29730
|
+
);
|
|
29731
|
+
return promise;
|
|
29732
|
+
};
|
|
29733
|
+
}
|
|
29734
|
+
|
|
29742
29735
|
// src/utils/jsdom-shim.ts
|
|
29743
29736
|
function applyJsdomShim(jsdom) {
|
|
29744
29737
|
global.window = jsdom.window;
|