@tscircuit/3d-viewer 0.0.352 → 0.0.354
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 +126 -20
- package/package.json +1 -1
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 useState15, useCallback 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.353",
|
|
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 }) }) });
|
|
@@ -29055,11 +29059,23 @@ var useContextMenu = ({ containerRef }) => {
|
|
|
29055
29059
|
});
|
|
29056
29060
|
const menuRef = useRef8(null);
|
|
29057
29061
|
const interactionOriginPosRef = useRef8(null);
|
|
29062
|
+
const longPressTimeoutRef = useRef8(null);
|
|
29063
|
+
const ignoreNextContextMenuRef = useRef8(false);
|
|
29064
|
+
const clearLongPressTimeout = () => {
|
|
29065
|
+
if (longPressTimeoutRef.current !== null) {
|
|
29066
|
+
clearTimeout(longPressTimeoutRef.current);
|
|
29067
|
+
longPressTimeoutRef.current = null;
|
|
29068
|
+
}
|
|
29069
|
+
};
|
|
29058
29070
|
const handleContextMenu = useCallback6(
|
|
29059
29071
|
(e) => {
|
|
29060
29072
|
e.preventDefault();
|
|
29061
29073
|
const eventX = typeof e.clientX === "number" ? e.clientX : 0;
|
|
29062
29074
|
const eventY = typeof e.clientY === "number" ? e.clientY : 0;
|
|
29075
|
+
if (ignoreNextContextMenuRef.current) {
|
|
29076
|
+
ignoreNextContextMenuRef.current = false;
|
|
29077
|
+
return;
|
|
29078
|
+
}
|
|
29063
29079
|
if (!interactionOriginPosRef.current) {
|
|
29064
29080
|
return;
|
|
29065
29081
|
}
|
|
@@ -29077,18 +29093,39 @@ var useContextMenu = ({ containerRef }) => {
|
|
|
29077
29093
|
},
|
|
29078
29094
|
[setMenuPos, setMenuVisible]
|
|
29079
29095
|
);
|
|
29080
|
-
const handleTouchStart = useCallback6(
|
|
29081
|
-
|
|
29082
|
-
|
|
29083
|
-
|
|
29084
|
-
|
|
29096
|
+
const handleTouchStart = useCallback6(
|
|
29097
|
+
(e) => {
|
|
29098
|
+
if (e.touches.length === 1) {
|
|
29099
|
+
const touch = e.touches[0];
|
|
29100
|
+
if (touch) {
|
|
29101
|
+
interactionOriginPosRef.current = {
|
|
29102
|
+
x: touch.clientX,
|
|
29103
|
+
y: touch.clientY
|
|
29104
|
+
};
|
|
29105
|
+
clearLongPressTimeout();
|
|
29106
|
+
longPressTimeoutRef.current = window.setTimeout(() => {
|
|
29107
|
+
if (!interactionOriginPosRef.current) return;
|
|
29108
|
+
if (containerRef.current) {
|
|
29109
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
29110
|
+
setMenuPos({
|
|
29111
|
+
x: rect.left + rect.width / 2,
|
|
29112
|
+
y: rect.top + rect.height / 2
|
|
29113
|
+
});
|
|
29114
|
+
setMenuVisible(true);
|
|
29115
|
+
ignoreNextContextMenuRef.current = true;
|
|
29116
|
+
}
|
|
29117
|
+
interactionOriginPosRef.current = null;
|
|
29118
|
+
}, 600);
|
|
29119
|
+
} else {
|
|
29120
|
+
interactionOriginPosRef.current = null;
|
|
29121
|
+
}
|
|
29085
29122
|
} else {
|
|
29086
29123
|
interactionOriginPosRef.current = null;
|
|
29124
|
+
clearLongPressTimeout();
|
|
29087
29125
|
}
|
|
29088
|
-
}
|
|
29089
|
-
|
|
29090
|
-
|
|
29091
|
-
}, []);
|
|
29126
|
+
},
|
|
29127
|
+
[containerRef]
|
|
29128
|
+
);
|
|
29092
29129
|
const handleTouchMove = useCallback6((e) => {
|
|
29093
29130
|
if (!interactionOriginPosRef.current || e.touches.length !== 1) {
|
|
29094
29131
|
return;
|
|
@@ -29100,12 +29137,15 @@ var useContextMenu = ({ containerRef }) => {
|
|
|
29100
29137
|
const swipeThreshold = 10;
|
|
29101
29138
|
if (dx > swipeThreshold || dy > swipeThreshold) {
|
|
29102
29139
|
interactionOriginPosRef.current = null;
|
|
29140
|
+
clearLongPressTimeout();
|
|
29103
29141
|
}
|
|
29104
29142
|
} else {
|
|
29105
29143
|
interactionOriginPosRef.current = null;
|
|
29144
|
+
clearLongPressTimeout();
|
|
29106
29145
|
}
|
|
29107
29146
|
}, []);
|
|
29108
29147
|
const handleTouchEnd = useCallback6(() => {
|
|
29148
|
+
clearLongPressTimeout();
|
|
29109
29149
|
setTimeout(() => {
|
|
29110
29150
|
if (interactionOriginPosRef.current) {
|
|
29111
29151
|
interactionOriginPosRef.current = null;
|
|
@@ -29121,7 +29161,11 @@ var useContextMenu = ({ containerRef }) => {
|
|
|
29121
29161
|
useEffect21(() => {
|
|
29122
29162
|
if (menuVisible) {
|
|
29123
29163
|
document.addEventListener("mousedown", handleClickAway);
|
|
29124
|
-
|
|
29164
|
+
document.addEventListener("touchstart", handleClickAway);
|
|
29165
|
+
return () => {
|
|
29166
|
+
document.removeEventListener("mousedown", handleClickAway);
|
|
29167
|
+
document.removeEventListener("touchstart", handleClickAway);
|
|
29168
|
+
};
|
|
29125
29169
|
}
|
|
29126
29170
|
}, [menuVisible, handleClickAway]);
|
|
29127
29171
|
const contextMenuEventHandlers = {
|
|
@@ -29147,6 +29191,35 @@ var useContextMenu = ({ containerRef }) => {
|
|
|
29147
29191
|
};
|
|
29148
29192
|
};
|
|
29149
29193
|
|
|
29194
|
+
// src/hooks/useGlobalDownloadGltf.ts
|
|
29195
|
+
import { useCallback as useCallback7 } from "react";
|
|
29196
|
+
import { GLTFExporter } from "three-stdlib";
|
|
29197
|
+
var useGlobalDownloadGltf = () => {
|
|
29198
|
+
return useCallback7(() => {
|
|
29199
|
+
const root = window.__TSCIRCUIT_THREE_OBJECT;
|
|
29200
|
+
if (!root) return;
|
|
29201
|
+
const exporter = new GLTFExporter();
|
|
29202
|
+
exporter.parse(
|
|
29203
|
+
root,
|
|
29204
|
+
(gltf) => {
|
|
29205
|
+
const blob = new Blob(
|
|
29206
|
+
[gltf instanceof ArrayBuffer ? gltf : JSON.stringify(gltf)],
|
|
29207
|
+
{ type: "model/gltf+json" }
|
|
29208
|
+
);
|
|
29209
|
+
const url = URL.createObjectURL(blob);
|
|
29210
|
+
const link = document.createElement("a");
|
|
29211
|
+
link.href = url;
|
|
29212
|
+
link.download = "scene.gltf";
|
|
29213
|
+
link.click();
|
|
29214
|
+
URL.revokeObjectURL(url);
|
|
29215
|
+
},
|
|
29216
|
+
(err) => {
|
|
29217
|
+
console.error("Failed to export GLTF", err);
|
|
29218
|
+
}
|
|
29219
|
+
);
|
|
29220
|
+
}, []);
|
|
29221
|
+
};
|
|
29222
|
+
|
|
29150
29223
|
// src/CadViewer.tsx
|
|
29151
29224
|
import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
29152
29225
|
var CadViewer = (props) => {
|
|
@@ -29163,15 +29236,16 @@ var CadViewer = (props) => {
|
|
|
29163
29236
|
} = useContextMenu({ containerRef });
|
|
29164
29237
|
const autoRotateUserToggledRef = useRef9(autoRotateUserToggled);
|
|
29165
29238
|
autoRotateUserToggledRef.current = autoRotateUserToggled;
|
|
29166
|
-
const handleUserInteraction =
|
|
29239
|
+
const handleUserInteraction = useCallback8(() => {
|
|
29167
29240
|
if (!autoRotateUserToggledRef.current) {
|
|
29168
29241
|
setAutoRotate(false);
|
|
29169
29242
|
}
|
|
29170
29243
|
}, []);
|
|
29171
|
-
const toggleAutoRotate =
|
|
29244
|
+
const toggleAutoRotate = useCallback8(() => {
|
|
29172
29245
|
setAutoRotate((prev) => !prev);
|
|
29173
29246
|
setAutoRotateUserToggled(true);
|
|
29174
29247
|
}, []);
|
|
29248
|
+
const downloadGltf = useGlobalDownloadGltf();
|
|
29175
29249
|
const handleMenuClick = (newEngine) => {
|
|
29176
29250
|
setEngine(newEngine);
|
|
29177
29251
|
setMenuVisible(false);
|
|
@@ -29190,7 +29264,16 @@ var CadViewer = (props) => {
|
|
|
29190
29264
|
"div",
|
|
29191
29265
|
{
|
|
29192
29266
|
ref: containerRef,
|
|
29193
|
-
style: {
|
|
29267
|
+
style: {
|
|
29268
|
+
width: "100%",
|
|
29269
|
+
height: "100%",
|
|
29270
|
+
position: "relative",
|
|
29271
|
+
userSelect: "none",
|
|
29272
|
+
MozUserSelect: "none",
|
|
29273
|
+
msUserSelect: "none",
|
|
29274
|
+
WebkitUserSelect: "none",
|
|
29275
|
+
WebkitTouchCallout: "none"
|
|
29276
|
+
},
|
|
29194
29277
|
...contextMenuEventHandlers,
|
|
29195
29278
|
children: [
|
|
29196
29279
|
engine === "jscad" ? /* @__PURE__ */ jsx14(
|
|
@@ -29312,6 +29395,29 @@ var CadViewer = (props) => {
|
|
|
29312
29395
|
]
|
|
29313
29396
|
}
|
|
29314
29397
|
),
|
|
29398
|
+
/* @__PURE__ */ jsx14(
|
|
29399
|
+
"div",
|
|
29400
|
+
{
|
|
29401
|
+
style: {
|
|
29402
|
+
padding: "12px 18px",
|
|
29403
|
+
cursor: "pointer",
|
|
29404
|
+
display: "flex",
|
|
29405
|
+
alignItems: "center",
|
|
29406
|
+
gap: 10,
|
|
29407
|
+
color: "#f5f6fa",
|
|
29408
|
+
fontWeight: 500,
|
|
29409
|
+
borderRadius: 6,
|
|
29410
|
+
transition: "background 0.1s"
|
|
29411
|
+
},
|
|
29412
|
+
onClick: () => {
|
|
29413
|
+
downloadGltf();
|
|
29414
|
+
setMenuVisible(false);
|
|
29415
|
+
},
|
|
29416
|
+
onMouseOver: (e) => e.currentTarget.style.background = "#2d313a",
|
|
29417
|
+
onMouseOut: (e) => e.currentTarget.style.background = "transparent",
|
|
29418
|
+
children: "Download GLTF"
|
|
29419
|
+
}
|
|
29420
|
+
),
|
|
29315
29421
|
/* @__PURE__ */ jsx14(
|
|
29316
29422
|
"div",
|
|
29317
29423
|
{
|
|
@@ -29616,8 +29722,8 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
29616
29722
|
}
|
|
29617
29723
|
|
|
29618
29724
|
// src/hooks/exporter/gltf.ts
|
|
29619
|
-
import { GLTFExporter } from "three-stdlib";
|
|
29620
|
-
import { useEffect as useEffect23, useState as useState16, useMemo as useMemo19, useCallback as
|
|
29725
|
+
import { GLTFExporter as GLTFExporter2 } from "three-stdlib";
|
|
29726
|
+
import { useEffect as useEffect23, useState as useState16, useMemo as useMemo19, useCallback as useCallback9 } from "react";
|
|
29621
29727
|
function useSaveGltfAs(options = {}) {
|
|
29622
29728
|
const parse = useParser(options);
|
|
29623
29729
|
const link = useMemo19(() => document.createElement("a"), []);
|
|
@@ -29638,7 +29744,7 @@ function useSaveGltfAs(options = {}) {
|
|
|
29638
29744
|
[]
|
|
29639
29745
|
);
|
|
29640
29746
|
let instance;
|
|
29641
|
-
const ref =
|
|
29747
|
+
const ref = useCallback9((obj3D) => {
|
|
29642
29748
|
instance = obj3D;
|
|
29643
29749
|
}, []);
|
|
29644
29750
|
return [ref, saveAs];
|
|
@@ -29647,7 +29753,7 @@ function useExportGltfUrl(options = {}) {
|
|
|
29647
29753
|
const parse = useParser(options);
|
|
29648
29754
|
const [url, setUrl] = useState16();
|
|
29649
29755
|
const [error, setError] = useState16();
|
|
29650
|
-
const ref =
|
|
29756
|
+
const ref = useCallback9(
|
|
29651
29757
|
(instance) => parse(instance).then(setUrl).catch(setError),
|
|
29652
29758
|
[]
|
|
29653
29759
|
);
|
|
@@ -29655,7 +29761,7 @@ function useExportGltfUrl(options = {}) {
|
|
|
29655
29761
|
return [ref, url, error];
|
|
29656
29762
|
}
|
|
29657
29763
|
function useParser(options = {}) {
|
|
29658
|
-
const exporter = useMemo19(() => new
|
|
29764
|
+
const exporter = useMemo19(() => new GLTFExporter2(), []);
|
|
29659
29765
|
return (instance) => {
|
|
29660
29766
|
const { promise, resolve, reject } = Promise.withResolvers();
|
|
29661
29767
|
exporter.parse(
|