@tscircuit/3d-viewer 0.0.351 → 0.0.352
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 +228 -292
- 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 useCallback7, 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.351",
|
|
25587
25587
|
main: "./dist/index.js",
|
|
25588
25588
|
module: "./dist/index.js",
|
|
25589
25589
|
type: "module",
|
|
@@ -25994,14 +25994,9 @@ var OrbitControls = ({
|
|
|
25994
25994
|
]);
|
|
25995
25995
|
useEffect11(() => {
|
|
25996
25996
|
if (!controls || !onStart) return;
|
|
25997
|
-
|
|
25998
|
-
if (event.button !== 2) {
|
|
25999
|
-
onStart();
|
|
26000
|
-
}
|
|
26001
|
-
};
|
|
26002
|
-
controls.addEventListener("start", handleStart);
|
|
25997
|
+
controls.addEventListener("start", onStart);
|
|
26003
25998
|
return () => {
|
|
26004
|
-
controls.removeEventListener("start",
|
|
25999
|
+
controls.removeEventListener("start", onStart);
|
|
26005
26000
|
};
|
|
26006
26001
|
}, [controls, onStart]);
|
|
26007
26002
|
useEffect11(() => {
|
|
@@ -27768,7 +27763,7 @@ var CadViewerJscad = forwardRef3(
|
|
|
27768
27763
|
|
|
27769
27764
|
// src/CadViewerManifold.tsx
|
|
27770
27765
|
import { su as su13 } from "@tscircuit/circuit-json-util";
|
|
27771
|
-
import {
|
|
27766
|
+
import { useEffect as useEffect20, useMemo as useMemo18, useState as useState13 } from "react";
|
|
27772
27767
|
|
|
27773
27768
|
// src/hooks/useManifoldBoardBuilder.ts
|
|
27774
27769
|
import { useState as useState12, useEffect as useEffect19, useMemo as useMemo17, useRef as useRef7 } from "react";
|
|
@@ -28878,51 +28873,50 @@ var BoardMeshes = ({
|
|
|
28878
28873
|
return null;
|
|
28879
28874
|
};
|
|
28880
28875
|
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
|
-
|
|
28876
|
+
var CadViewerManifold = ({
|
|
28877
|
+
circuitJson: circuitJsonProp,
|
|
28878
|
+
autoRotateDisabled,
|
|
28879
|
+
clickToInteractEnabled,
|
|
28880
|
+
onUserInteraction,
|
|
28881
|
+
children
|
|
28882
|
+
}) => {
|
|
28883
|
+
const childrenCircuitJson = useConvertChildrenToSoup(children);
|
|
28884
|
+
const circuitJson = useMemo18(() => {
|
|
28885
|
+
return circuitJsonProp ?? childrenCircuitJson;
|
|
28886
|
+
}, [circuitJsonProp, childrenCircuitJson]);
|
|
28887
|
+
const [manifoldJSModule, setManifoldJSModule] = useState13(null);
|
|
28888
|
+
const [manifoldLoadingError, setManifoldLoadingError] = useState13(null);
|
|
28889
|
+
useEffect20(() => {
|
|
28890
|
+
const initManifold = async (ManifoldModule) => {
|
|
28891
|
+
try {
|
|
28892
|
+
const loadedModule = await ManifoldModule();
|
|
28893
|
+
loadedModule.setup();
|
|
28894
|
+
setManifoldJSModule(loadedModule);
|
|
28895
|
+
} catch (error) {
|
|
28896
|
+
console.error("Failed to initialize Manifold:", error);
|
|
28897
|
+
setManifoldLoadingError(
|
|
28898
|
+
`Failed to initialize Manifold: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
28899
|
+
);
|
|
28900
|
+
}
|
|
28901
|
+
};
|
|
28902
|
+
if (window.ManifoldModule) {
|
|
28903
|
+
initManifold(window.ManifoldModule);
|
|
28904
|
+
return;
|
|
28905
|
+
}
|
|
28906
|
+
const eventName = "manifoldLoaded";
|
|
28907
|
+
const handleLoad = () => {
|
|
28908
28908
|
if (window.ManifoldModule) {
|
|
28909
28909
|
initManifold(window.ManifoldModule);
|
|
28910
|
-
|
|
28910
|
+
} else {
|
|
28911
|
+
const errText = "ManifoldModule not found on window after script load.";
|
|
28912
|
+
console.error(errText);
|
|
28913
|
+
setManifoldLoadingError(errText);
|
|
28911
28914
|
}
|
|
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 = `
|
|
28915
|
+
};
|
|
28916
|
+
window.addEventListener(eventName, handleLoad, { once: true });
|
|
28917
|
+
const script = document.createElement("script");
|
|
28918
|
+
script.type = "module";
|
|
28919
|
+
script.innerHTML = `
|
|
28926
28920
|
try {
|
|
28927
28921
|
const { default: ManifoldModule } = await import('${MANIFOLD_CDN_BASE_URL}/manifold.js');
|
|
28928
28922
|
window.ManifoldModule = ManifoldModule;
|
|
@@ -28932,125 +28926,123 @@ try {
|
|
|
28932
28926
|
window.dispatchEvent(new CustomEvent('${eventName}'));
|
|
28933
28927
|
}
|
|
28934
28928
|
`.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
|
-
|
|
28929
|
+
const scriptError = (err) => {
|
|
28930
|
+
const errText = "Failed to load Manifold loader script.";
|
|
28931
|
+
console.error(errText, err);
|
|
28932
|
+
setManifoldLoadingError(errText);
|
|
28933
|
+
window.removeEventListener(eventName, handleLoad);
|
|
28934
|
+
};
|
|
28935
|
+
script.addEventListener("error", scriptError);
|
|
28936
|
+
document.body.appendChild(script);
|
|
28937
|
+
return () => {
|
|
28938
|
+
window.removeEventListener(eventName, handleLoad);
|
|
28939
|
+
script.removeEventListener("error", scriptError);
|
|
28940
|
+
};
|
|
28941
|
+
}, []);
|
|
28942
|
+
const {
|
|
28943
|
+
geoms,
|
|
28944
|
+
textures,
|
|
28945
|
+
pcbThickness,
|
|
28946
|
+
error: builderError,
|
|
28947
|
+
isLoading: builderIsLoading,
|
|
28948
|
+
boardData
|
|
28949
|
+
} = useManifoldBoardBuilder(manifoldJSModule, circuitJson);
|
|
28950
|
+
const geometryMeshes = useMemo18(() => createGeometryMeshes(geoms), [geoms]);
|
|
28951
|
+
const textureMeshes = useMemo18(
|
|
28952
|
+
() => createTextureMeshes(textures, boardData, pcbThickness),
|
|
28953
|
+
[textures, boardData, pcbThickness]
|
|
28954
|
+
);
|
|
28955
|
+
const cadComponents = useMemo18(
|
|
28956
|
+
() => su13(circuitJson).cad_component.list(),
|
|
28957
|
+
[circuitJson]
|
|
28958
|
+
);
|
|
28959
|
+
const boardDimensions = useMemo18(() => {
|
|
28960
|
+
if (!boardData) return void 0;
|
|
28961
|
+
const { width: width10 = 0, height: height10 = 0 } = boardData;
|
|
28962
|
+
return { width: width10, height: height10 };
|
|
28963
|
+
}, [boardData]);
|
|
28964
|
+
const initialCameraPosition = useMemo18(() => {
|
|
28965
|
+
if (!boardData) return [5, 5, 5];
|
|
28966
|
+
const { width: width10 = 0, height: height10 = 0 } = boardData;
|
|
28967
|
+
const safeWidth = Math.max(width10, 1);
|
|
28968
|
+
const safeHeight = Math.max(height10, 1);
|
|
28969
|
+
const largestDim = Math.max(safeWidth, safeHeight, 5);
|
|
28970
|
+
return [largestDim * 0.75, largestDim * 0.75, largestDim * 0.75];
|
|
28971
|
+
}, [boardData]);
|
|
28972
|
+
if (manifoldLoadingError) {
|
|
28973
|
+
return /* @__PURE__ */ jsxs7(
|
|
28974
|
+
"div",
|
|
28975
|
+
{
|
|
28976
|
+
style: {
|
|
28977
|
+
color: "red",
|
|
28978
|
+
padding: "1em",
|
|
28979
|
+
border: "1px solid red",
|
|
28980
|
+
margin: "1em"
|
|
28981
|
+
},
|
|
28982
|
+
children: [
|
|
28983
|
+
"Error: ",
|
|
28984
|
+
manifoldLoadingError
|
|
28985
|
+
]
|
|
28986
|
+
}
|
|
28964
28987
|
);
|
|
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
|
-
}
|
|
28988
|
+
}
|
|
28989
|
+
if (!manifoldJSModule) {
|
|
28990
|
+
return /* @__PURE__ */ jsx13("div", { style: { padding: "1em" }, children: "Loading Manifold module..." });
|
|
28991
|
+
}
|
|
28992
|
+
if (builderError) {
|
|
29018
28993
|
return /* @__PURE__ */ jsxs7(
|
|
29019
|
-
|
|
28994
|
+
"div",
|
|
29020
28995
|
{
|
|
29021
|
-
|
|
29022
|
-
|
|
29023
|
-
|
|
29024
|
-
|
|
29025
|
-
|
|
29026
|
-
|
|
28996
|
+
style: {
|
|
28997
|
+
color: "red",
|
|
28998
|
+
padding: "1em",
|
|
28999
|
+
border: "1px solid red",
|
|
29000
|
+
margin: "1em"
|
|
29001
|
+
},
|
|
29027
29002
|
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
|
-
))
|
|
29003
|
+
"Error: ",
|
|
29004
|
+
builderError
|
|
29049
29005
|
]
|
|
29050
29006
|
}
|
|
29051
29007
|
);
|
|
29052
29008
|
}
|
|
29053
|
-
)
|
|
29009
|
+
if (builderIsLoading) {
|
|
29010
|
+
return /* @__PURE__ */ jsx13("div", { style: { padding: "1em" }, children: "Processing board geometry..." });
|
|
29011
|
+
}
|
|
29012
|
+
return /* @__PURE__ */ jsxs7(
|
|
29013
|
+
CadViewerContainer,
|
|
29014
|
+
{
|
|
29015
|
+
initialCameraPosition,
|
|
29016
|
+
autoRotateDisabled,
|
|
29017
|
+
clickToInteractEnabled,
|
|
29018
|
+
boardDimensions,
|
|
29019
|
+
onUserInteraction,
|
|
29020
|
+
children: [
|
|
29021
|
+
/* @__PURE__ */ jsx13(
|
|
29022
|
+
BoardMeshes,
|
|
29023
|
+
{
|
|
29024
|
+
geometryMeshes,
|
|
29025
|
+
textureMeshes
|
|
29026
|
+
}
|
|
29027
|
+
),
|
|
29028
|
+
cadComponents.map((cad_component2) => /* @__PURE__ */ jsx13(
|
|
29029
|
+
ThreeErrorBoundary,
|
|
29030
|
+
{
|
|
29031
|
+
fallback: ({ error }) => /* @__PURE__ */ jsx13(Error3d, { cad_component: cad_component2, error }),
|
|
29032
|
+
children: /* @__PURE__ */ jsx13(
|
|
29033
|
+
AnyCadComponent,
|
|
29034
|
+
{
|
|
29035
|
+
cad_component: cad_component2,
|
|
29036
|
+
circuitJson
|
|
29037
|
+
}
|
|
29038
|
+
)
|
|
29039
|
+
},
|
|
29040
|
+
cad_component2.cad_component_id
|
|
29041
|
+
))
|
|
29042
|
+
]
|
|
29043
|
+
}
|
|
29044
|
+
);
|
|
29045
|
+
};
|
|
29054
29046
|
var CadViewerManifold_default = CadViewerManifold;
|
|
29055
29047
|
|
|
29056
29048
|
// src/hooks/useContextMenu.ts
|
|
@@ -29155,87 +29147,13 @@ var useContextMenu = ({ containerRef }) => {
|
|
|
29155
29147
|
};
|
|
29156
29148
|
};
|
|
29157
29149
|
|
|
29158
|
-
// src/hooks/exporter/gltf.ts
|
|
29159
|
-
import { GLTFExporter } from "three-stdlib";
|
|
29160
|
-
import { useEffect as useEffect22, useState as useState15, useMemo as useMemo19, useCallback as useCallback7, useRef as useRef9 } from "react";
|
|
29161
|
-
function useSaveGltfAs(options = {}) {
|
|
29162
|
-
const parse = useParser(options);
|
|
29163
|
-
const link = useMemo19(() => document.createElement("a"), []);
|
|
29164
|
-
const instanceRef = useRef9(null);
|
|
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();
|
|
29215
|
-
exporter.parse(
|
|
29216
|
-
instance,
|
|
29217
|
-
(gltf) => {
|
|
29218
|
-
const type = options.binary ? "gltf-binary" : "gltf+json";
|
|
29219
|
-
const blob = new Blob(
|
|
29220
|
-
[gltf instanceof ArrayBuffer ? gltf : JSON.stringify(gltf)],
|
|
29221
|
-
{ type: `model/${type}` }
|
|
29222
|
-
);
|
|
29223
|
-
resolve(URL.createObjectURL(blob));
|
|
29224
|
-
},
|
|
29225
|
-
reject,
|
|
29226
|
-
options
|
|
29227
|
-
);
|
|
29228
|
-
return promise;
|
|
29229
|
-
};
|
|
29230
|
-
}
|
|
29231
|
-
|
|
29232
29150
|
// src/CadViewer.tsx
|
|
29233
29151
|
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] =
|
|
29152
|
+
var CadViewer = (props) => {
|
|
29153
|
+
const [engine, setEngine] = useState15("manifold");
|
|
29154
|
+
const containerRef = useRef9(null);
|
|
29155
|
+
const [autoRotate, setAutoRotate] = useState15(true);
|
|
29156
|
+
const [autoRotateUserToggled, setAutoRotateUserToggled] = useState15(false);
|
|
29239
29157
|
const {
|
|
29240
29158
|
menuVisible,
|
|
29241
29159
|
menuPos,
|
|
@@ -29243,28 +29161,14 @@ var CadViewer = forwardRef5((props, ref) => {
|
|
|
29243
29161
|
contextMenuEventHandlers,
|
|
29244
29162
|
setMenuVisible
|
|
29245
29163
|
} = 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);
|
|
29164
|
+
const autoRotateUserToggledRef = useRef9(autoRotateUserToggled);
|
|
29261
29165
|
autoRotateUserToggledRef.current = autoRotateUserToggled;
|
|
29262
|
-
const handleUserInteraction =
|
|
29166
|
+
const handleUserInteraction = useCallback7(() => {
|
|
29263
29167
|
if (!autoRotateUserToggledRef.current) {
|
|
29264
29168
|
setAutoRotate(false);
|
|
29265
29169
|
}
|
|
29266
29170
|
}, []);
|
|
29267
|
-
const toggleAutoRotate =
|
|
29171
|
+
const toggleAutoRotate = useCallback7(() => {
|
|
29268
29172
|
setAutoRotate((prev) => !prev);
|
|
29269
29173
|
setAutoRotateUserToggled(true);
|
|
29270
29174
|
}, []);
|
|
@@ -29272,17 +29176,13 @@ var CadViewer = forwardRef5((props, ref) => {
|
|
|
29272
29176
|
setEngine(newEngine);
|
|
29273
29177
|
setMenuVisible(false);
|
|
29274
29178
|
};
|
|
29275
|
-
|
|
29276
|
-
saveGltfAs("pcb.glb");
|
|
29277
|
-
setMenuVisible(false);
|
|
29278
|
-
}, [saveGltfAs, setMenuVisible]);
|
|
29279
|
-
useEffect23(() => {
|
|
29179
|
+
useEffect22(() => {
|
|
29280
29180
|
const stored = window.localStorage.getItem("cadViewerEngine");
|
|
29281
29181
|
if (stored === "jscad" || stored === "manifold") {
|
|
29282
29182
|
setEngine(stored);
|
|
29283
29183
|
}
|
|
29284
29184
|
}, []);
|
|
29285
|
-
|
|
29185
|
+
useEffect22(() => {
|
|
29286
29186
|
window.localStorage.setItem("cadViewerEngine", engine);
|
|
29287
29187
|
}, [engine]);
|
|
29288
29188
|
const viewerKey = props.circuitJson ? JSON.stringify(props.circuitJson) : void 0;
|
|
@@ -29297,19 +29197,15 @@ var CadViewer = forwardRef5((props, ref) => {
|
|
|
29297
29197
|
CadViewerJscad,
|
|
29298
29198
|
{
|
|
29299
29199
|
...props,
|
|
29300
|
-
ref: mergedRef,
|
|
29301
29200
|
autoRotateDisabled: props.autoRotateDisabled || !autoRotate,
|
|
29302
|
-
onUserInteraction: handleUserInteraction
|
|
29303
|
-
children: props.children
|
|
29201
|
+
onUserInteraction: handleUserInteraction
|
|
29304
29202
|
}
|
|
29305
29203
|
) : /* @__PURE__ */ jsx14(
|
|
29306
29204
|
CadViewerManifold_default,
|
|
29307
29205
|
{
|
|
29308
29206
|
...props,
|
|
29309
|
-
ref: mergedRef,
|
|
29310
29207
|
autoRotateDisabled: props.autoRotateDisabled || !autoRotate,
|
|
29311
|
-
onUserInteraction: handleUserInteraction
|
|
29312
|
-
children: props.children
|
|
29208
|
+
onUserInteraction: handleUserInteraction
|
|
29313
29209
|
}
|
|
29314
29210
|
),
|
|
29315
29211
|
/* @__PURE__ */ jsxs8(
|
|
@@ -29416,26 +29312,6 @@ var CadViewer = forwardRef5((props, ref) => {
|
|
|
29416
29312
|
]
|
|
29417
29313
|
}
|
|
29418
29314
|
),
|
|
29419
|
-
/* @__PURE__ */ jsx14(
|
|
29420
|
-
"div",
|
|
29421
|
-
{
|
|
29422
|
-
style: {
|
|
29423
|
-
padding: "12px 18px",
|
|
29424
|
-
cursor: "pointer",
|
|
29425
|
-
display: "flex",
|
|
29426
|
-
alignItems: "center",
|
|
29427
|
-
gap: 10,
|
|
29428
|
-
color: "#f5f6fa",
|
|
29429
|
-
fontWeight: 500,
|
|
29430
|
-
borderRadius: 6,
|
|
29431
|
-
transition: "background 0.1s"
|
|
29432
|
-
},
|
|
29433
|
-
onClick: handleDownloadGltf,
|
|
29434
|
-
onMouseOver: (e) => e.currentTarget.style.background = "#2d313a",
|
|
29435
|
-
onMouseOut: (e) => e.currentTarget.style.background = "transparent",
|
|
29436
|
-
children: "Download GLTF"
|
|
29437
|
-
}
|
|
29438
|
-
),
|
|
29439
29315
|
/* @__PURE__ */ jsx14(
|
|
29440
29316
|
"div",
|
|
29441
29317
|
{
|
|
@@ -29470,7 +29346,7 @@ var CadViewer = forwardRef5((props, ref) => {
|
|
|
29470
29346
|
},
|
|
29471
29347
|
viewerKey
|
|
29472
29348
|
);
|
|
29473
|
-
}
|
|
29349
|
+
};
|
|
29474
29350
|
|
|
29475
29351
|
// src/convert-circuit-json-to-3d-svg.ts
|
|
29476
29352
|
var import_debug = __toESM(require_browser(), 1);
|
|
@@ -29739,6 +29615,66 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
29739
29615
|
return serialized;
|
|
29740
29616
|
}
|
|
29741
29617
|
|
|
29618
|
+
// src/hooks/exporter/gltf.ts
|
|
29619
|
+
import { GLTFExporter } from "three-stdlib";
|
|
29620
|
+
import { useEffect as useEffect23, useState as useState16, useMemo as useMemo19, useCallback as useCallback8 } from "react";
|
|
29621
|
+
function useSaveGltfAs(options = {}) {
|
|
29622
|
+
const parse = useParser(options);
|
|
29623
|
+
const link = useMemo19(() => document.createElement("a"), []);
|
|
29624
|
+
const saveAs = async (filename) => {
|
|
29625
|
+
const name = filename ?? options.filename ?? "";
|
|
29626
|
+
if (options.binary == null) options.binary = name.endsWith(".glb");
|
|
29627
|
+
const url = await parse(instance);
|
|
29628
|
+
link.download = name;
|
|
29629
|
+
link.href = url;
|
|
29630
|
+
link.dispatchEvent(new MouseEvent("click"));
|
|
29631
|
+
URL.revokeObjectURL(url);
|
|
29632
|
+
};
|
|
29633
|
+
useEffect23(
|
|
29634
|
+
() => () => {
|
|
29635
|
+
link.remove();
|
|
29636
|
+
instance = null;
|
|
29637
|
+
},
|
|
29638
|
+
[]
|
|
29639
|
+
);
|
|
29640
|
+
let instance;
|
|
29641
|
+
const ref = useCallback8((obj3D) => {
|
|
29642
|
+
instance = obj3D;
|
|
29643
|
+
}, []);
|
|
29644
|
+
return [ref, saveAs];
|
|
29645
|
+
}
|
|
29646
|
+
function useExportGltfUrl(options = {}) {
|
|
29647
|
+
const parse = useParser(options);
|
|
29648
|
+
const [url, setUrl] = useState16();
|
|
29649
|
+
const [error, setError] = useState16();
|
|
29650
|
+
const ref = useCallback8(
|
|
29651
|
+
(instance) => parse(instance).then(setUrl).catch(setError),
|
|
29652
|
+
[]
|
|
29653
|
+
);
|
|
29654
|
+
useEffect23(() => () => URL.revokeObjectURL(url), [url]);
|
|
29655
|
+
return [ref, url, error];
|
|
29656
|
+
}
|
|
29657
|
+
function useParser(options = {}) {
|
|
29658
|
+
const exporter = useMemo19(() => new GLTFExporter(), []);
|
|
29659
|
+
return (instance) => {
|
|
29660
|
+
const { promise, resolve, reject } = Promise.withResolvers();
|
|
29661
|
+
exporter.parse(
|
|
29662
|
+
instance,
|
|
29663
|
+
(gltf) => {
|
|
29664
|
+
const type = options.binary ? "gltf-binary" : "gltf+json";
|
|
29665
|
+
const blob = new Blob(
|
|
29666
|
+
[gltf instanceof ArrayBuffer ? gltf : JSON.stringify(gltf)],
|
|
29667
|
+
{ type: `model/${type}` }
|
|
29668
|
+
);
|
|
29669
|
+
resolve(URL.createObjectURL(blob));
|
|
29670
|
+
},
|
|
29671
|
+
reject,
|
|
29672
|
+
options
|
|
29673
|
+
);
|
|
29674
|
+
return promise;
|
|
29675
|
+
};
|
|
29676
|
+
}
|
|
29677
|
+
|
|
29742
29678
|
// src/utils/jsdom-shim.ts
|
|
29743
29679
|
function applyJsdomShim(jsdom) {
|
|
29744
29680
|
global.window = jsdom.window;
|