@tscircuit/3d-viewer 0.0.233 → 0.0.234
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 +113 -32
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -13980,7 +13980,7 @@ var require_browser = __commonJS({
|
|
|
13980
13980
|
});
|
|
13981
13981
|
|
|
13982
13982
|
// src/CadViewer.tsx
|
|
13983
|
-
import { useState as
|
|
13983
|
+
import { useState as useState10, useRef as useRef8, useEffect as useEffect8 } from "react";
|
|
13984
13984
|
|
|
13985
13985
|
// src/hooks/use-convert-children-to-soup.ts
|
|
13986
13986
|
import { Circuit } from "@tscircuit/core";
|
|
@@ -16985,7 +16985,7 @@ import { Canvas, useFrame as useFrame2 } from "@react-three/fiber";
|
|
|
16985
16985
|
// package.json
|
|
16986
16986
|
var package_default = {
|
|
16987
16987
|
name: "@tscircuit/3d-viewer",
|
|
16988
|
-
version: "0.0.
|
|
16988
|
+
version: "0.0.233",
|
|
16989
16989
|
main: "./dist/index.js",
|
|
16990
16990
|
module: "./dist/index.js",
|
|
16991
16991
|
type: "module",
|
|
@@ -17313,7 +17313,7 @@ var colors = {
|
|
|
17313
17313
|
var MANIFOLD_Z_OFFSET = 1e-3;
|
|
17314
17314
|
var SMOOTH_CIRCLE_SEGMENTS = 32;
|
|
17315
17315
|
var DEFAULT_SMT_PAD_THICKNESS = 0.035;
|
|
17316
|
-
var TRACE_TEXTURE_RESOLUTION =
|
|
17316
|
+
var TRACE_TEXTURE_RESOLUTION = 50;
|
|
17317
17317
|
var boardMaterialColors = {
|
|
17318
17318
|
fr1: colors.fr1Copper,
|
|
17319
17319
|
fr4: colors.fr4Green
|
|
@@ -19905,29 +19905,76 @@ var CadViewerManifold = ({
|
|
|
19905
19905
|
};
|
|
19906
19906
|
var CadViewerManifold_default = CadViewerManifold;
|
|
19907
19907
|
|
|
19908
|
-
// src/
|
|
19909
|
-
import {
|
|
19910
|
-
var
|
|
19911
|
-
const [engine, setEngine] = useState9("jscad");
|
|
19908
|
+
// src/hooks/useContextMenu.ts
|
|
19909
|
+
import { useState as useState9, useCallback as useCallback4, useRef as useRef7, useEffect as useEffect7 } from "react";
|
|
19910
|
+
var useContextMenu = ({ containerRef }) => {
|
|
19912
19911
|
const [menuVisible, setMenuVisible] = useState9(false);
|
|
19913
19912
|
const [menuPos, setMenuPos] = useState9({
|
|
19914
19913
|
x: 0,
|
|
19915
19914
|
y: 0
|
|
19916
19915
|
});
|
|
19917
|
-
const containerRef = useRef7(null);
|
|
19918
19916
|
const menuRef = useRef7(null);
|
|
19919
|
-
const
|
|
19920
|
-
|
|
19921
|
-
|
|
19922
|
-
|
|
19917
|
+
const interactionOriginPosRef = useRef7(null);
|
|
19918
|
+
const handleContextMenu = useCallback4(
|
|
19919
|
+
(e) => {
|
|
19920
|
+
e.preventDefault();
|
|
19921
|
+
const eventX = typeof e.clientX === "number" ? e.clientX : 0;
|
|
19922
|
+
const eventY = typeof e.clientY === "number" ? e.clientY : 0;
|
|
19923
|
+
if (!interactionOriginPosRef.current) {
|
|
19924
|
+
return;
|
|
19925
|
+
}
|
|
19926
|
+
const { x: originX, y: originY } = interactionOriginPosRef.current;
|
|
19927
|
+
const dx = Math.abs(eventX - originX);
|
|
19928
|
+
const dy = Math.abs(eventY - originY);
|
|
19929
|
+
const swipeThreshold = 10;
|
|
19930
|
+
if (dx > swipeThreshold || dy > swipeThreshold) {
|
|
19931
|
+
interactionOriginPosRef.current = null;
|
|
19932
|
+
return;
|
|
19933
|
+
}
|
|
19934
|
+
setMenuPos({ x: eventX, y: eventY });
|
|
19935
|
+
setMenuVisible(true);
|
|
19936
|
+
interactionOriginPosRef.current = null;
|
|
19937
|
+
},
|
|
19938
|
+
[setMenuPos, setMenuVisible]
|
|
19939
|
+
);
|
|
19940
|
+
const handleTouchStart = useCallback4((e) => {
|
|
19941
|
+
if (e.touches.length === 1) {
|
|
19942
|
+
const touch = e.touches[0];
|
|
19943
|
+
if (touch) {
|
|
19944
|
+
interactionOriginPosRef.current = { x: touch.clientX, y: touch.clientY };
|
|
19945
|
+
} else {
|
|
19946
|
+
interactionOriginPosRef.current = null;
|
|
19947
|
+
}
|
|
19948
|
+
} else {
|
|
19949
|
+
interactionOriginPosRef.current = null;
|
|
19950
|
+
}
|
|
19951
|
+
}, []);
|
|
19952
|
+
const handleTouchMove = useCallback4((e) => {
|
|
19953
|
+
if (!interactionOriginPosRef.current || e.touches.length !== 1) {
|
|
19954
|
+
return;
|
|
19955
|
+
}
|
|
19956
|
+
const touch = e.touches[0];
|
|
19957
|
+
if (touch) {
|
|
19958
|
+
const dx = Math.abs(touch.clientX - interactionOriginPosRef.current.x);
|
|
19959
|
+
const dy = Math.abs(touch.clientY - interactionOriginPosRef.current.y);
|
|
19960
|
+
const swipeThreshold = 10;
|
|
19961
|
+
if (dx > swipeThreshold || dy > swipeThreshold) {
|
|
19962
|
+
interactionOriginPosRef.current = null;
|
|
19963
|
+
}
|
|
19964
|
+
} else {
|
|
19965
|
+
interactionOriginPosRef.current = null;
|
|
19966
|
+
}
|
|
19967
|
+
}, []);
|
|
19968
|
+
const handleTouchEnd = useCallback4(() => {
|
|
19969
|
+
setTimeout(() => {
|
|
19970
|
+
if (interactionOriginPosRef.current) {
|
|
19971
|
+
interactionOriginPosRef.current = null;
|
|
19972
|
+
}
|
|
19973
|
+
}, 0);
|
|
19923
19974
|
}, []);
|
|
19924
|
-
const handleMenuClick = (newEngine) => {
|
|
19925
|
-
setEngine(newEngine);
|
|
19926
|
-
setMenuVisible(false);
|
|
19927
|
-
};
|
|
19928
19975
|
const handleClickAway = useCallback4((e) => {
|
|
19929
19976
|
const target = e.target;
|
|
19930
|
-
if (
|
|
19977
|
+
if (menuRef.current && !menuRef.current.contains(target)) {
|
|
19931
19978
|
setMenuVisible(false);
|
|
19932
19979
|
}
|
|
19933
19980
|
}, []);
|
|
@@ -19937,13 +19984,52 @@ var CadViewer = (props) => {
|
|
|
19937
19984
|
return () => document.removeEventListener("mousedown", handleClickAway);
|
|
19938
19985
|
}
|
|
19939
19986
|
}, [menuVisible, handleClickAway]);
|
|
19940
|
-
|
|
19987
|
+
const contextMenuEventHandlers = {
|
|
19988
|
+
onMouseDown: (e) => {
|
|
19989
|
+
if (e.button === 2) {
|
|
19990
|
+
interactionOriginPosRef.current = { x: e.clientX, y: e.clientY };
|
|
19991
|
+
} else {
|
|
19992
|
+
interactionOriginPosRef.current = null;
|
|
19993
|
+
}
|
|
19994
|
+
},
|
|
19995
|
+
onContextMenu: handleContextMenu,
|
|
19996
|
+
onTouchStart: handleTouchStart,
|
|
19997
|
+
onTouchMove: handleTouchMove,
|
|
19998
|
+
onTouchEnd: handleTouchEnd
|
|
19999
|
+
};
|
|
20000
|
+
return {
|
|
20001
|
+
menuVisible,
|
|
20002
|
+
menuPos,
|
|
20003
|
+
menuRef,
|
|
20004
|
+
contextMenuEventHandlers,
|
|
20005
|
+
setMenuVisible
|
|
20006
|
+
// Expose setMenuVisible for direct control if needed
|
|
20007
|
+
};
|
|
20008
|
+
};
|
|
20009
|
+
|
|
20010
|
+
// src/CadViewer.tsx
|
|
20011
|
+
import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
20012
|
+
var CadViewer = (props) => {
|
|
20013
|
+
const [engine, setEngine] = useState10("jscad");
|
|
20014
|
+
const containerRef = useRef8(null);
|
|
20015
|
+
const {
|
|
20016
|
+
menuVisible,
|
|
20017
|
+
menuPos,
|
|
20018
|
+
menuRef,
|
|
20019
|
+
contextMenuEventHandlers,
|
|
20020
|
+
setMenuVisible
|
|
20021
|
+
} = useContextMenu({ containerRef });
|
|
20022
|
+
const handleMenuClick = (newEngine) => {
|
|
20023
|
+
setEngine(newEngine);
|
|
20024
|
+
setMenuVisible(false);
|
|
20025
|
+
};
|
|
20026
|
+
useEffect8(() => {
|
|
19941
20027
|
const stored = window.localStorage.getItem("cadViewerEngine");
|
|
19942
20028
|
if (stored === "jscad" || stored === "manifold") {
|
|
19943
20029
|
setEngine(stored);
|
|
19944
20030
|
}
|
|
19945
20031
|
}, []);
|
|
19946
|
-
|
|
20032
|
+
useEffect8(() => {
|
|
19947
20033
|
window.localStorage.setItem("cadViewerEngine", engine);
|
|
19948
20034
|
}, [engine]);
|
|
19949
20035
|
const viewerKey = props.circuitJson ? JSON.stringify(props.circuitJson) : void 0;
|
|
@@ -19952,7 +20038,7 @@ var CadViewer = (props) => {
|
|
|
19952
20038
|
{
|
|
19953
20039
|
ref: containerRef,
|
|
19954
20040
|
style: { width: "100%", height: "100%", position: "relative" },
|
|
19955
|
-
|
|
20041
|
+
...contextMenuEventHandlers,
|
|
19956
20042
|
children: [
|
|
19957
20043
|
engine === "jscad" ? /* @__PURE__ */ jsx12(CadViewerJscad, { ...props }) : /* @__PURE__ */ jsx12(CadViewerManifold_default, { ...props }),
|
|
19958
20044
|
/* @__PURE__ */ jsxs9(
|
|
@@ -19970,11 +20056,6 @@ var CadViewer = (props) => {
|
|
|
19970
20056
|
opacity: 0.7,
|
|
19971
20057
|
userSelect: "none"
|
|
19972
20058
|
},
|
|
19973
|
-
onClick: () => {
|
|
19974
|
-
if ("ontouchstart" in window) {
|
|
19975
|
-
setEngine(engine === "jscad" ? "manifold" : "jscad");
|
|
19976
|
-
}
|
|
19977
|
-
},
|
|
19978
20059
|
children: [
|
|
19979
20060
|
"Engine: ",
|
|
19980
20061
|
/* @__PURE__ */ jsx12("b", { children: engine === "jscad" ? "JSCAD" : "Manifold" })
|
|
@@ -20308,7 +20389,7 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
20308
20389
|
}
|
|
20309
20390
|
|
|
20310
20391
|
// src/hooks/exporter/gltf.ts
|
|
20311
|
-
import { useEffect as
|
|
20392
|
+
import { useEffect as useEffect9, useState as useState11, useMemo as useMemo8, useCallback as useCallback6 } from "react";
|
|
20312
20393
|
function useSaveGltfAs(options = {}) {
|
|
20313
20394
|
const parse = useParser(options);
|
|
20314
20395
|
const link = useMemo8(() => document.createElement("a"), []);
|
|
@@ -20321,7 +20402,7 @@ function useSaveGltfAs(options = {}) {
|
|
|
20321
20402
|
link.dispatchEvent(new MouseEvent("click"));
|
|
20322
20403
|
URL.revokeObjectURL(url);
|
|
20323
20404
|
};
|
|
20324
|
-
|
|
20405
|
+
useEffect9(
|
|
20325
20406
|
() => () => {
|
|
20326
20407
|
link.remove();
|
|
20327
20408
|
instance = null;
|
|
@@ -20329,20 +20410,20 @@ function useSaveGltfAs(options = {}) {
|
|
|
20329
20410
|
[]
|
|
20330
20411
|
);
|
|
20331
20412
|
let instance;
|
|
20332
|
-
const ref =
|
|
20413
|
+
const ref = useCallback6((obj3D) => {
|
|
20333
20414
|
instance = obj3D;
|
|
20334
20415
|
}, []);
|
|
20335
20416
|
return [ref, saveAs];
|
|
20336
20417
|
}
|
|
20337
20418
|
function useExportGltfUrl(options = {}) {
|
|
20338
20419
|
const parse = useParser(options);
|
|
20339
|
-
const [url, setUrl] =
|
|
20340
|
-
const [error, setError] =
|
|
20341
|
-
const ref =
|
|
20420
|
+
const [url, setUrl] = useState11();
|
|
20421
|
+
const [error, setError] = useState11();
|
|
20422
|
+
const ref = useCallback6(
|
|
20342
20423
|
(instance) => parse(instance).then(setUrl).catch(setError),
|
|
20343
20424
|
[]
|
|
20344
20425
|
);
|
|
20345
|
-
|
|
20426
|
+
useEffect9(() => () => URL.revokeObjectURL(url), [url]);
|
|
20346
20427
|
return [ref, url, error];
|
|
20347
20428
|
}
|
|
20348
20429
|
function useParser(options = {}) {
|