@tscircuit/3d-viewer 0.0.439 → 0.0.441
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 +402 -60
- 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
|
|
14231
|
+
import { useState as useState36, useCallback as useCallback22, useRef as useRef26, useEffect as useEffect42, useMemo as useMemo28 } from "react";
|
|
14232
14232
|
import * as THREE29 from "three";
|
|
14233
14233
|
|
|
14234
14234
|
// src/CadViewerJscad.tsx
|
|
@@ -28113,12 +28113,6 @@ var defaultVisibility = {
|
|
|
28113
28113
|
var LayerVisibilityContext = createContext3(void 0);
|
|
28114
28114
|
var LayerVisibilityProvider = ({ children }) => {
|
|
28115
28115
|
const [visibility, setVisibility] = useState5(defaultVisibility);
|
|
28116
|
-
const toggleLayer = useCallback2((layer) => {
|
|
28117
|
-
setVisibility((prev) => ({
|
|
28118
|
-
...prev,
|
|
28119
|
-
[layer]: !prev[layer]
|
|
28120
|
-
}));
|
|
28121
|
-
}, []);
|
|
28122
28116
|
const setLayerVisibility = useCallback2(
|
|
28123
28117
|
(layer, visible) => {
|
|
28124
28118
|
setVisibility((prev) => ({
|
|
@@ -28134,11 +28128,10 @@ var LayerVisibilityProvider = ({ children }) => {
|
|
|
28134
28128
|
const value = useMemo6(
|
|
28135
28129
|
() => ({
|
|
28136
28130
|
visibility,
|
|
28137
|
-
toggleLayer,
|
|
28138
28131
|
setLayerVisibility,
|
|
28139
28132
|
resetToDefaults
|
|
28140
28133
|
}),
|
|
28141
|
-
[visibility,
|
|
28134
|
+
[visibility, setLayerVisibility, resetToDefaults]
|
|
28142
28135
|
);
|
|
28143
28136
|
return /* @__PURE__ */ jsx8(LayerVisibilityContext.Provider, { value, children });
|
|
28144
28137
|
};
|
|
@@ -28288,7 +28281,7 @@ import * as THREE15 from "three";
|
|
|
28288
28281
|
// package.json
|
|
28289
28282
|
var package_default = {
|
|
28290
28283
|
name: "@tscircuit/3d-viewer",
|
|
28291
|
-
version: "0.0.
|
|
28284
|
+
version: "0.0.440",
|
|
28292
28285
|
main: "./dist/index.js",
|
|
28293
28286
|
module: "./dist/index.js",
|
|
28294
28287
|
type: "module",
|
|
@@ -34503,8 +34496,112 @@ var useGlobalDownloadGltf = () => {
|
|
|
34503
34496
|
}, []);
|
|
34504
34497
|
};
|
|
34505
34498
|
|
|
34499
|
+
// src/hooks/useRegisteredHotkey.ts
|
|
34500
|
+
import { useEffect as useEffect25, useMemo as useMemo21, useRef as useRef11, useState as useState18 } from "react";
|
|
34501
|
+
var hotkeyRegistry = /* @__PURE__ */ new Map();
|
|
34502
|
+
var subscribers = /* @__PURE__ */ new Set();
|
|
34503
|
+
var isListenerAttached = false;
|
|
34504
|
+
var parseShortcut = (shortcut) => {
|
|
34505
|
+
const parts = shortcut.toLowerCase().split("+");
|
|
34506
|
+
const key = parts[parts.length - 1];
|
|
34507
|
+
const modifierParts = parts.slice(0, -1);
|
|
34508
|
+
return {
|
|
34509
|
+
key,
|
|
34510
|
+
ctrl: modifierParts.includes("ctrl"),
|
|
34511
|
+
cmd: modifierParts.includes("cmd"),
|
|
34512
|
+
shift: modifierParts.includes("shift"),
|
|
34513
|
+
alt: modifierParts.includes("alt")
|
|
34514
|
+
};
|
|
34515
|
+
};
|
|
34516
|
+
var matchesShortcut = (event, shortcut) => {
|
|
34517
|
+
const parsed = parseShortcut(shortcut);
|
|
34518
|
+
const keyMatches = event.key.toLowerCase() === parsed.key;
|
|
34519
|
+
const ctrlMatches = parsed.ctrl === event.ctrlKey;
|
|
34520
|
+
const cmdMatches = parsed.cmd === event.metaKey;
|
|
34521
|
+
const shiftMatches = parsed.shift === event.shiftKey;
|
|
34522
|
+
const altMatches = parsed.alt === event.altKey;
|
|
34523
|
+
return keyMatches && ctrlMatches && cmdMatches && shiftMatches && altMatches;
|
|
34524
|
+
};
|
|
34525
|
+
var isEditableTarget = (target) => {
|
|
34526
|
+
if (!target || typeof target !== "object") return false;
|
|
34527
|
+
const element = target;
|
|
34528
|
+
const tagName = element.tagName;
|
|
34529
|
+
const editableTags = ["INPUT", "TEXTAREA", "SELECT"];
|
|
34530
|
+
if (editableTags.includes(tagName)) {
|
|
34531
|
+
return true;
|
|
34532
|
+
}
|
|
34533
|
+
return Boolean(element.getAttribute?.("contenteditable"));
|
|
34534
|
+
};
|
|
34535
|
+
var handleKeydown = (event) => {
|
|
34536
|
+
if (isEditableTarget(event.target)) {
|
|
34537
|
+
return;
|
|
34538
|
+
}
|
|
34539
|
+
hotkeyRegistry.forEach((entry) => {
|
|
34540
|
+
if (matchesShortcut(event, entry.shortcut)) {
|
|
34541
|
+
event.preventDefault();
|
|
34542
|
+
entry.invoke();
|
|
34543
|
+
}
|
|
34544
|
+
});
|
|
34545
|
+
};
|
|
34546
|
+
var notifySubscribers = () => {
|
|
34547
|
+
const entries = Array.from(hotkeyRegistry.values());
|
|
34548
|
+
subscribers.forEach((subscriber) => subscriber(entries));
|
|
34549
|
+
};
|
|
34550
|
+
var ensureListener = () => {
|
|
34551
|
+
if (isListenerAttached) return;
|
|
34552
|
+
if (typeof window === "undefined") return;
|
|
34553
|
+
window.addEventListener("keydown", handleKeydown);
|
|
34554
|
+
isListenerAttached = true;
|
|
34555
|
+
};
|
|
34556
|
+
var registerHotkey = (registration) => {
|
|
34557
|
+
hotkeyRegistry.set(registration.id, registration);
|
|
34558
|
+
notifySubscribers();
|
|
34559
|
+
ensureListener();
|
|
34560
|
+
};
|
|
34561
|
+
var unregisterHotkey = (id) => {
|
|
34562
|
+
if (hotkeyRegistry.delete(id)) {
|
|
34563
|
+
notifySubscribers();
|
|
34564
|
+
}
|
|
34565
|
+
};
|
|
34566
|
+
var subscribeToRegistry = (subscriber) => {
|
|
34567
|
+
subscribers.add(subscriber);
|
|
34568
|
+
subscriber(Array.from(hotkeyRegistry.values()));
|
|
34569
|
+
return () => {
|
|
34570
|
+
subscribers.delete(subscriber);
|
|
34571
|
+
};
|
|
34572
|
+
};
|
|
34573
|
+
var useRegisteredHotkey = (id, handler, metadata) => {
|
|
34574
|
+
const handlerRef = useRef11(handler);
|
|
34575
|
+
handlerRef.current = handler;
|
|
34576
|
+
const normalizedMetadata = useMemo21(
|
|
34577
|
+
() => ({
|
|
34578
|
+
shortcut: metadata.shortcut,
|
|
34579
|
+
description: metadata.description
|
|
34580
|
+
}),
|
|
34581
|
+
[metadata.shortcut, metadata.description]
|
|
34582
|
+
);
|
|
34583
|
+
useEffect25(() => {
|
|
34584
|
+
const registration = {
|
|
34585
|
+
id,
|
|
34586
|
+
...normalizedMetadata,
|
|
34587
|
+
invoke: () => handlerRef.current()
|
|
34588
|
+
};
|
|
34589
|
+
registerHotkey(registration);
|
|
34590
|
+
return () => {
|
|
34591
|
+
unregisterHotkey(id);
|
|
34592
|
+
};
|
|
34593
|
+
}, [id, normalizedMetadata]);
|
|
34594
|
+
};
|
|
34595
|
+
var useHotkeyRegistry = () => {
|
|
34596
|
+
const [entries, setEntries] = useState18(
|
|
34597
|
+
() => Array.from(hotkeyRegistry.values())
|
|
34598
|
+
);
|
|
34599
|
+
useEffect25(() => subscribeToRegistry(setEntries), []);
|
|
34600
|
+
return entries;
|
|
34601
|
+
};
|
|
34602
|
+
|
|
34506
34603
|
// src/components/ContextMenu.tsx
|
|
34507
|
-
import { useState as
|
|
34604
|
+
import { useState as useState34 } from "react";
|
|
34508
34605
|
|
|
34509
34606
|
// node_modules/@radix-ui/react-dropdown-menu/dist/index.mjs
|
|
34510
34607
|
import * as React43 from "react";
|
|
@@ -38132,9 +38229,9 @@ function assignRef(ref, value) {
|
|
|
38132
38229
|
}
|
|
38133
38230
|
|
|
38134
38231
|
// node_modules/use-callback-ref/dist/es2015/useRef.js
|
|
38135
|
-
import { useState as
|
|
38232
|
+
import { useState as useState29 } from "react";
|
|
38136
38233
|
function useCallbackRef2(initialValue, callback) {
|
|
38137
|
-
var ref =
|
|
38234
|
+
var ref = useState29(function() {
|
|
38138
38235
|
return {
|
|
38139
38236
|
// value
|
|
38140
38237
|
value: initialValue,
|
|
@@ -39858,7 +39955,7 @@ var SubTrigger2 = DropdownMenuSubTrigger;
|
|
|
39858
39955
|
var SubContent2 = DropdownMenuSubContent;
|
|
39859
39956
|
|
|
39860
39957
|
// src/components/AppearanceMenu.tsx
|
|
39861
|
-
import { useState as
|
|
39958
|
+
import { useState as useState33 } from "react";
|
|
39862
39959
|
|
|
39863
39960
|
// src/components/Icons.tsx
|
|
39864
39961
|
import { jsx as jsx32 } from "react/jsx-runtime";
|
|
@@ -39963,9 +40060,9 @@ var iconContainerStyles = {
|
|
|
39963
40060
|
flexShrink: 0
|
|
39964
40061
|
};
|
|
39965
40062
|
var AppearanceMenu = () => {
|
|
39966
|
-
const { visibility,
|
|
39967
|
-
const [appearanceSubOpen, setAppearanceSubOpen] =
|
|
39968
|
-
const [hoveredItem, setHoveredItem] =
|
|
40063
|
+
const { visibility, setLayerVisibility } = useLayerVisibility();
|
|
40064
|
+
const [appearanceSubOpen, setAppearanceSubOpen] = useState33(false);
|
|
40065
|
+
const [hoveredItem, setHoveredItem] = useState33(null);
|
|
39969
40066
|
return /* @__PURE__ */ jsxs7(Fragment9, { children: [
|
|
39970
40067
|
/* @__PURE__ */ jsx33(Separator2, { style: separatorStyles }),
|
|
39971
40068
|
/* @__PURE__ */ jsxs7(Sub2, { onOpenChange: setAppearanceSubOpen, children: [
|
|
@@ -40014,7 +40111,7 @@ var AppearanceMenu = () => {
|
|
|
40014
40111
|
onSelect: (e) => e.preventDefault(),
|
|
40015
40112
|
onPointerDown: (e) => {
|
|
40016
40113
|
e.preventDefault();
|
|
40017
|
-
|
|
40114
|
+
setLayerVisibility("boardBody", !visibility.boardBody);
|
|
40018
40115
|
},
|
|
40019
40116
|
onMouseEnter: () => setHoveredItem("boardBody"),
|
|
40020
40117
|
onMouseLeave: () => setHoveredItem(null),
|
|
@@ -40035,7 +40132,7 @@ var AppearanceMenu = () => {
|
|
|
40035
40132
|
onSelect: (e) => e.preventDefault(),
|
|
40036
40133
|
onPointerDown: (e) => {
|
|
40037
40134
|
e.preventDefault();
|
|
40038
|
-
|
|
40135
|
+
setLayerVisibility("topCopper", !visibility.topCopper);
|
|
40039
40136
|
},
|
|
40040
40137
|
onMouseEnter: () => setHoveredItem("topCopper"),
|
|
40041
40138
|
onMouseLeave: () => setHoveredItem(null),
|
|
@@ -40056,7 +40153,7 @@ var AppearanceMenu = () => {
|
|
|
40056
40153
|
onSelect: (e) => e.preventDefault(),
|
|
40057
40154
|
onPointerDown: (e) => {
|
|
40058
40155
|
e.preventDefault();
|
|
40059
|
-
|
|
40156
|
+
setLayerVisibility("bottomCopper", !visibility.bottomCopper);
|
|
40060
40157
|
},
|
|
40061
40158
|
onMouseEnter: () => setHoveredItem("bottomCopper"),
|
|
40062
40159
|
onMouseLeave: () => setHoveredItem(null),
|
|
@@ -40077,7 +40174,7 @@ var AppearanceMenu = () => {
|
|
|
40077
40174
|
onSelect: (e) => e.preventDefault(),
|
|
40078
40175
|
onPointerDown: (e) => {
|
|
40079
40176
|
e.preventDefault();
|
|
40080
|
-
|
|
40177
|
+
setLayerVisibility("topSilkscreen", !visibility.topSilkscreen);
|
|
40081
40178
|
},
|
|
40082
40179
|
onMouseEnter: () => setHoveredItem("topSilkscreen"),
|
|
40083
40180
|
onMouseLeave: () => setHoveredItem(null),
|
|
@@ -40098,7 +40195,10 @@ var AppearanceMenu = () => {
|
|
|
40098
40195
|
onSelect: (e) => e.preventDefault(),
|
|
40099
40196
|
onPointerDown: (e) => {
|
|
40100
40197
|
e.preventDefault();
|
|
40101
|
-
|
|
40198
|
+
setLayerVisibility(
|
|
40199
|
+
"bottomSilkscreen",
|
|
40200
|
+
!visibility.bottomSilkscreen
|
|
40201
|
+
);
|
|
40102
40202
|
},
|
|
40103
40203
|
onMouseEnter: () => setHoveredItem("bottomSilkscreen"),
|
|
40104
40204
|
onMouseLeave: () => setHoveredItem(null),
|
|
@@ -40119,7 +40219,7 @@ var AppearanceMenu = () => {
|
|
|
40119
40219
|
onSelect: (e) => e.preventDefault(),
|
|
40120
40220
|
onPointerDown: (e) => {
|
|
40121
40221
|
e.preventDefault();
|
|
40122
|
-
|
|
40222
|
+
setLayerVisibility("smtModels", !visibility.smtModels);
|
|
40123
40223
|
},
|
|
40124
40224
|
onMouseEnter: () => setHoveredItem("smtModels"),
|
|
40125
40225
|
onMouseLeave: () => setHoveredItem(null),
|
|
@@ -40216,11 +40316,12 @@ var ContextMenu = ({
|
|
|
40216
40316
|
onEngineSwitch,
|
|
40217
40317
|
onCameraPresetSelect,
|
|
40218
40318
|
onAutoRotateToggle,
|
|
40219
|
-
onDownloadGltf
|
|
40319
|
+
onDownloadGltf,
|
|
40320
|
+
onOpenKeyboardShortcuts
|
|
40220
40321
|
}) => {
|
|
40221
40322
|
const { cameraType, setCameraType } = useCameraController();
|
|
40222
|
-
const [cameraSubOpen, setCameraSubOpen] =
|
|
40223
|
-
const [hoveredItem, setHoveredItem] =
|
|
40323
|
+
const [cameraSubOpen, setCameraSubOpen] = useState34(false);
|
|
40324
|
+
const [hoveredItem, setHoveredItem] = useState34(null);
|
|
40224
40325
|
return /* @__PURE__ */ jsx34(
|
|
40225
40326
|
"div",
|
|
40226
40327
|
{
|
|
@@ -40413,6 +40514,35 @@ var ContextMenu = ({
|
|
|
40413
40514
|
}
|
|
40414
40515
|
),
|
|
40415
40516
|
/* @__PURE__ */ jsx34(Separator2, { style: separatorStyles2 }),
|
|
40517
|
+
/* @__PURE__ */ jsxs8(
|
|
40518
|
+
Item22,
|
|
40519
|
+
{
|
|
40520
|
+
style: {
|
|
40521
|
+
...itemStyles2,
|
|
40522
|
+
...itemPaddingStyles2,
|
|
40523
|
+
backgroundColor: hoveredItem === "shortcuts" ? "#404040" : "transparent"
|
|
40524
|
+
},
|
|
40525
|
+
onSelect: onOpenKeyboardShortcuts,
|
|
40526
|
+
onMouseEnter: () => setHoveredItem("shortcuts"),
|
|
40527
|
+
onMouseLeave: () => setHoveredItem(null),
|
|
40528
|
+
onTouchStart: () => setHoveredItem("shortcuts"),
|
|
40529
|
+
children: [
|
|
40530
|
+
/* @__PURE__ */ jsx34("span", { style: { flex: 1, display: "flex", alignItems: "center" }, children: "Keyboard Shortcuts" }),
|
|
40531
|
+
/* @__PURE__ */ jsx34(
|
|
40532
|
+
"div",
|
|
40533
|
+
{
|
|
40534
|
+
style: {
|
|
40535
|
+
...badgeStyles,
|
|
40536
|
+
display: "flex",
|
|
40537
|
+
alignItems: "center"
|
|
40538
|
+
},
|
|
40539
|
+
children: "Shift+?"
|
|
40540
|
+
}
|
|
40541
|
+
)
|
|
40542
|
+
]
|
|
40543
|
+
}
|
|
40544
|
+
),
|
|
40545
|
+
/* @__PURE__ */ jsx34(Separator2, { style: separatorStyles2 }),
|
|
40416
40546
|
/* @__PURE__ */ jsx34(
|
|
40417
40547
|
"div",
|
|
40418
40548
|
{
|
|
@@ -40450,23 +40580,214 @@ var ContextMenu = ({
|
|
|
40450
40580
|
);
|
|
40451
40581
|
};
|
|
40452
40582
|
|
|
40453
|
-
// src/
|
|
40583
|
+
// src/components/KeyboardShortcutsDialog.tsx
|
|
40584
|
+
import { useEffect as useEffect41, useMemo as useMemo27, useRef as useRef25, useState as useState35 } from "react";
|
|
40454
40585
|
import { jsx as jsx35, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
40586
|
+
var KeyboardShortcutsDialog = ({
|
|
40587
|
+
open,
|
|
40588
|
+
onClose
|
|
40589
|
+
}) => {
|
|
40590
|
+
const [query, setQuery] = useState35("");
|
|
40591
|
+
const inputRef = useRef25(null);
|
|
40592
|
+
const hotkeys = useHotkeyRegistry();
|
|
40593
|
+
useEffect41(() => {
|
|
40594
|
+
if (!open) return void 0;
|
|
40595
|
+
const handleKeyDown = (event) => {
|
|
40596
|
+
if (event.key === "Escape") {
|
|
40597
|
+
event.preventDefault();
|
|
40598
|
+
onClose();
|
|
40599
|
+
}
|
|
40600
|
+
};
|
|
40601
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
40602
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
40603
|
+
}, [open, onClose]);
|
|
40604
|
+
useEffect41(() => {
|
|
40605
|
+
if (open) {
|
|
40606
|
+
setTimeout(() => {
|
|
40607
|
+
inputRef.current?.focus();
|
|
40608
|
+
}, 0);
|
|
40609
|
+
}
|
|
40610
|
+
}, [open]);
|
|
40611
|
+
const filteredHotkeys = useMemo27(() => {
|
|
40612
|
+
const normalizedQuery = query.trim().toLowerCase();
|
|
40613
|
+
if (!normalizedQuery) {
|
|
40614
|
+
return hotkeys;
|
|
40615
|
+
}
|
|
40616
|
+
return hotkeys.filter((hotkey) => {
|
|
40617
|
+
const haystack = `${hotkey.shortcut} ${hotkey.description}`;
|
|
40618
|
+
return haystack.toLowerCase().includes(normalizedQuery);
|
|
40619
|
+
});
|
|
40620
|
+
}, [hotkeys, query]);
|
|
40621
|
+
if (!open) {
|
|
40622
|
+
return null;
|
|
40623
|
+
}
|
|
40624
|
+
return /* @__PURE__ */ jsx35(
|
|
40625
|
+
"div",
|
|
40626
|
+
{
|
|
40627
|
+
role: "dialog",
|
|
40628
|
+
"aria-modal": "true",
|
|
40629
|
+
style: {
|
|
40630
|
+
position: "fixed",
|
|
40631
|
+
inset: 0,
|
|
40632
|
+
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
40633
|
+
display: "flex",
|
|
40634
|
+
alignItems: "center",
|
|
40635
|
+
justifyContent: "center",
|
|
40636
|
+
zIndex: 9999
|
|
40637
|
+
},
|
|
40638
|
+
onClick: onClose,
|
|
40639
|
+
children: /* @__PURE__ */ jsxs9(
|
|
40640
|
+
"div",
|
|
40641
|
+
{
|
|
40642
|
+
style: {
|
|
40643
|
+
backgroundColor: "#1f1f23",
|
|
40644
|
+
color: "#f8f8ff",
|
|
40645
|
+
borderRadius: 12,
|
|
40646
|
+
width: "min(640px, 90vw)",
|
|
40647
|
+
maxHeight: "80vh",
|
|
40648
|
+
boxShadow: "0 20px 60px rgba(0, 0, 0, 0.45), 0 8px 20px rgba(0, 0, 0, 0.35)",
|
|
40649
|
+
display: "flex",
|
|
40650
|
+
flexDirection: "column",
|
|
40651
|
+
overflow: "hidden"
|
|
40652
|
+
},
|
|
40653
|
+
onClick: (event) => event.stopPropagation(),
|
|
40654
|
+
children: [
|
|
40655
|
+
/* @__PURE__ */ jsxs9(
|
|
40656
|
+
"header",
|
|
40657
|
+
{
|
|
40658
|
+
style: {
|
|
40659
|
+
padding: "20px 24px 12px",
|
|
40660
|
+
borderBottom: "1px solid rgba(255, 255, 255, 0.08)"
|
|
40661
|
+
},
|
|
40662
|
+
children: [
|
|
40663
|
+
/* @__PURE__ */ jsxs9("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
|
|
40664
|
+
/* @__PURE__ */ jsx35(
|
|
40665
|
+
"h2",
|
|
40666
|
+
{
|
|
40667
|
+
style: {
|
|
40668
|
+
margin: 0,
|
|
40669
|
+
fontSize: "1.1rem",
|
|
40670
|
+
fontWeight: 600,
|
|
40671
|
+
letterSpacing: "0.02em"
|
|
40672
|
+
},
|
|
40673
|
+
children: "Keyboard Shortcuts"
|
|
40674
|
+
}
|
|
40675
|
+
),
|
|
40676
|
+
/* @__PURE__ */ jsx35(
|
|
40677
|
+
"button",
|
|
40678
|
+
{
|
|
40679
|
+
type: "button",
|
|
40680
|
+
onClick: onClose,
|
|
40681
|
+
style: {
|
|
40682
|
+
background: "transparent",
|
|
40683
|
+
border: "none",
|
|
40684
|
+
color: "rgba(255, 255, 255, 0.8)",
|
|
40685
|
+
fontSize: "1rem",
|
|
40686
|
+
cursor: "pointer"
|
|
40687
|
+
},
|
|
40688
|
+
children: "\u2715"
|
|
40689
|
+
}
|
|
40690
|
+
)
|
|
40691
|
+
] }),
|
|
40692
|
+
/* @__PURE__ */ jsx35(
|
|
40693
|
+
"input",
|
|
40694
|
+
{
|
|
40695
|
+
ref: inputRef,
|
|
40696
|
+
type: "text",
|
|
40697
|
+
placeholder: "Search shortcuts...",
|
|
40698
|
+
value: query,
|
|
40699
|
+
onChange: (event) => setQuery(event.target.value),
|
|
40700
|
+
style: {
|
|
40701
|
+
marginTop: 12,
|
|
40702
|
+
width: "calc(100% - 24px)",
|
|
40703
|
+
padding: "10px 12px",
|
|
40704
|
+
borderRadius: 8,
|
|
40705
|
+
border: "1px solid rgba(255, 255, 255, 0.1)",
|
|
40706
|
+
backgroundColor: "rgba(255, 255, 255, 0.05)",
|
|
40707
|
+
color: "white",
|
|
40708
|
+
fontSize: "0.95rem"
|
|
40709
|
+
}
|
|
40710
|
+
}
|
|
40711
|
+
)
|
|
40712
|
+
]
|
|
40713
|
+
}
|
|
40714
|
+
),
|
|
40715
|
+
/* @__PURE__ */ jsx35("div", { style: { overflowY: "auto" }, children: /* @__PURE__ */ jsxs9(
|
|
40716
|
+
"table",
|
|
40717
|
+
{
|
|
40718
|
+
style: {
|
|
40719
|
+
width: "100%",
|
|
40720
|
+
borderCollapse: "collapse",
|
|
40721
|
+
fontSize: "0.95rem"
|
|
40722
|
+
},
|
|
40723
|
+
children: [
|
|
40724
|
+
/* @__PURE__ */ jsx35("thead", { children: /* @__PURE__ */ jsxs9("tr", { style: { textAlign: "left", color: "#a1a1b5" }, children: [
|
|
40725
|
+
/* @__PURE__ */ jsx35("th", { style: { padding: "12px 24px", width: "25%" }, children: "Key" }),
|
|
40726
|
+
/* @__PURE__ */ jsx35("th", { style: { padding: "12px 24px" }, children: "Description" })
|
|
40727
|
+
] }) }),
|
|
40728
|
+
/* @__PURE__ */ jsx35("tbody", { children: filteredHotkeys.length === 0 ? /* @__PURE__ */ jsx35("tr", { children: /* @__PURE__ */ jsx35(
|
|
40729
|
+
"td",
|
|
40730
|
+
{
|
|
40731
|
+
colSpan: 2,
|
|
40732
|
+
style: { padding: "24px", textAlign: "center" },
|
|
40733
|
+
children: "No shortcuts found"
|
|
40734
|
+
}
|
|
40735
|
+
) }) : filteredHotkeys.map((hotkey) => /* @__PURE__ */ jsxs9(
|
|
40736
|
+
"tr",
|
|
40737
|
+
{
|
|
40738
|
+
style: { borderTop: "1px solid rgba(255, 255, 255, 0.05)" },
|
|
40739
|
+
children: [
|
|
40740
|
+
/* @__PURE__ */ jsx35("td", { style: { padding: "12px 24px" }, children: /* @__PURE__ */ jsx35(
|
|
40741
|
+
"span",
|
|
40742
|
+
{
|
|
40743
|
+
style: {
|
|
40744
|
+
display: "inline-flex",
|
|
40745
|
+
alignItems: "center",
|
|
40746
|
+
justifyContent: "center",
|
|
40747
|
+
border: "1px solid rgba(255, 255, 255, 0.3)",
|
|
40748
|
+
borderRadius: 6,
|
|
40749
|
+
minWidth: 36,
|
|
40750
|
+
padding: "4px 8px",
|
|
40751
|
+
fontFamily: "monospace",
|
|
40752
|
+
fontSize: "0.95rem",
|
|
40753
|
+
textTransform: "capitalize"
|
|
40754
|
+
},
|
|
40755
|
+
children: hotkey.shortcut
|
|
40756
|
+
}
|
|
40757
|
+
) }),
|
|
40758
|
+
/* @__PURE__ */ jsx35("td", { style: { padding: "12px 24px" }, children: hotkey.description })
|
|
40759
|
+
]
|
|
40760
|
+
},
|
|
40761
|
+
hotkey.id
|
|
40762
|
+
)) })
|
|
40763
|
+
]
|
|
40764
|
+
}
|
|
40765
|
+
) })
|
|
40766
|
+
]
|
|
40767
|
+
}
|
|
40768
|
+
)
|
|
40769
|
+
}
|
|
40770
|
+
);
|
|
40771
|
+
};
|
|
40772
|
+
|
|
40773
|
+
// src/CadViewer.tsx
|
|
40774
|
+
import { jsx as jsx36, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
40455
40775
|
var CadViewerInner = (props) => {
|
|
40456
|
-
const [engine, setEngine] =
|
|
40457
|
-
const containerRef =
|
|
40458
|
-
const [
|
|
40776
|
+
const [engine, setEngine] = useState36("manifold");
|
|
40777
|
+
const containerRef = useRef26(null);
|
|
40778
|
+
const [isKeyboardShortcutsDialogOpen, setIsKeyboardShortcutsDialogOpen] = useState36(false);
|
|
40779
|
+
const [autoRotate, setAutoRotate] = useState36(() => {
|
|
40459
40780
|
const stored = window.localStorage.getItem("cadViewerAutoRotate");
|
|
40460
40781
|
return stored === "false" ? false : true;
|
|
40461
40782
|
});
|
|
40462
|
-
const [autoRotateUserToggled, setAutoRotateUserToggled] =
|
|
40783
|
+
const [autoRotateUserToggled, setAutoRotateUserToggled] = useState36(() => {
|
|
40463
40784
|
const stored = window.localStorage.getItem("cadViewerAutoRotateUserToggled");
|
|
40464
40785
|
return stored === "true";
|
|
40465
40786
|
});
|
|
40466
|
-
const [cameraPreset, setCameraPreset] =
|
|
40787
|
+
const [cameraPreset, setCameraPreset] = useState36("Custom");
|
|
40467
40788
|
const { cameraType, setCameraType } = useCameraController();
|
|
40468
|
-
const { visibility,
|
|
40469
|
-
const cameraControllerRef =
|
|
40789
|
+
const { visibility, setLayerVisibility } = useLayerVisibility();
|
|
40790
|
+
const cameraControllerRef = useRef26(null);
|
|
40470
40791
|
const externalCameraControllerReady = props.onCameraControllerReady;
|
|
40471
40792
|
const {
|
|
40472
40793
|
menuVisible,
|
|
@@ -40475,10 +40796,10 @@ var CadViewerInner = (props) => {
|
|
|
40475
40796
|
contextMenuEventHandlers,
|
|
40476
40797
|
setMenuVisible
|
|
40477
40798
|
} = useContextMenu({ containerRef });
|
|
40478
|
-
const autoRotateUserToggledRef =
|
|
40799
|
+
const autoRotateUserToggledRef = useRef26(autoRotateUserToggled);
|
|
40479
40800
|
autoRotateUserToggledRef.current = autoRotateUserToggled;
|
|
40480
|
-
const isAnimatingRef =
|
|
40481
|
-
const lastPresetSelectTime =
|
|
40801
|
+
const isAnimatingRef = useRef26(false);
|
|
40802
|
+
const lastPresetSelectTime = useRef26(0);
|
|
40482
40803
|
const PRESET_COOLDOWN = 1e3;
|
|
40483
40804
|
const handleUserInteraction = useCallback22(() => {
|
|
40484
40805
|
if (isAnimatingRef.current || Date.now() - lastPresetSelectTime.current < PRESET_COOLDOWN) {
|
|
@@ -40518,35 +40839,45 @@ var CadViewerInner = (props) => {
|
|
|
40518
40839
|
isAnimatingRef,
|
|
40519
40840
|
lastPresetSelectTime
|
|
40520
40841
|
});
|
|
40521
|
-
|
|
40842
|
+
useRegisteredHotkey(
|
|
40843
|
+
"open_keyboard_shortcuts_dialog",
|
|
40844
|
+
() => {
|
|
40845
|
+
setIsKeyboardShortcutsDialogOpen(true);
|
|
40846
|
+
},
|
|
40847
|
+
{
|
|
40848
|
+
shortcut: "shift+?",
|
|
40849
|
+
description: "Open keyboard shortcuts"
|
|
40850
|
+
}
|
|
40851
|
+
);
|
|
40852
|
+
useEffect42(() => {
|
|
40522
40853
|
const stored = window.localStorage.getItem("cadViewerEngine");
|
|
40523
40854
|
if (stored === "jscad" || stored === "manifold") {
|
|
40524
40855
|
setEngine(stored);
|
|
40525
40856
|
}
|
|
40526
40857
|
}, []);
|
|
40527
|
-
|
|
40858
|
+
useEffect42(() => {
|
|
40528
40859
|
window.localStorage.setItem("cadViewerEngine", engine);
|
|
40529
40860
|
}, [engine]);
|
|
40530
|
-
|
|
40861
|
+
useEffect42(() => {
|
|
40531
40862
|
window.localStorage.setItem("cadViewerAutoRotate", String(autoRotate));
|
|
40532
40863
|
}, [autoRotate]);
|
|
40533
|
-
|
|
40864
|
+
useEffect42(() => {
|
|
40534
40865
|
window.localStorage.setItem(
|
|
40535
40866
|
"cadViewerAutoRotateUserToggled",
|
|
40536
40867
|
String(autoRotateUserToggled)
|
|
40537
40868
|
);
|
|
40538
40869
|
}, [autoRotateUserToggled]);
|
|
40539
|
-
|
|
40870
|
+
useEffect42(() => {
|
|
40540
40871
|
const stored = window.localStorage.getItem("cadViewerCameraType");
|
|
40541
40872
|
if (stored === "orthographic" || stored === "perspective") {
|
|
40542
40873
|
setCameraType(stored);
|
|
40543
40874
|
}
|
|
40544
40875
|
}, [setCameraType]);
|
|
40545
|
-
|
|
40876
|
+
useEffect42(() => {
|
|
40546
40877
|
window.localStorage.setItem("cadViewerCameraType", cameraType);
|
|
40547
40878
|
}, [cameraType]);
|
|
40548
40879
|
const viewerKey = props.circuitJson ? JSON.stringify(props.circuitJson) : void 0;
|
|
40549
|
-
return /* @__PURE__ */
|
|
40880
|
+
return /* @__PURE__ */ jsxs10(
|
|
40550
40881
|
"div",
|
|
40551
40882
|
{
|
|
40552
40883
|
ref: containerRef,
|
|
@@ -40562,7 +40893,7 @@ var CadViewerInner = (props) => {
|
|
|
40562
40893
|
},
|
|
40563
40894
|
...contextMenuEventHandlers,
|
|
40564
40895
|
children: [
|
|
40565
|
-
engine === "jscad" ? /* @__PURE__ */
|
|
40896
|
+
engine === "jscad" ? /* @__PURE__ */ jsx36(
|
|
40566
40897
|
CadViewerJscad,
|
|
40567
40898
|
{
|
|
40568
40899
|
...props,
|
|
@@ -40571,7 +40902,7 @@ var CadViewerInner = (props) => {
|
|
|
40571
40902
|
onUserInteraction: handleUserInteraction,
|
|
40572
40903
|
onCameraControllerReady: handleCameraControllerReady
|
|
40573
40904
|
}
|
|
40574
|
-
) : /* @__PURE__ */
|
|
40905
|
+
) : /* @__PURE__ */ jsx36(
|
|
40575
40906
|
CadViewerManifold_default,
|
|
40576
40907
|
{
|
|
40577
40908
|
...props,
|
|
@@ -40581,7 +40912,7 @@ var CadViewerInner = (props) => {
|
|
|
40581
40912
|
onCameraControllerReady: handleCameraControllerReady
|
|
40582
40913
|
}
|
|
40583
40914
|
),
|
|
40584
|
-
/* @__PURE__ */
|
|
40915
|
+
/* @__PURE__ */ jsxs10(
|
|
40585
40916
|
"div",
|
|
40586
40917
|
{
|
|
40587
40918
|
style: {
|
|
@@ -40598,11 +40929,11 @@ var CadViewerInner = (props) => {
|
|
|
40598
40929
|
},
|
|
40599
40930
|
children: [
|
|
40600
40931
|
"Engine: ",
|
|
40601
|
-
/* @__PURE__ */
|
|
40932
|
+
/* @__PURE__ */ jsx36("b", { children: engine === "jscad" ? "JSCAD" : "Manifold" })
|
|
40602
40933
|
]
|
|
40603
40934
|
}
|
|
40604
40935
|
),
|
|
40605
|
-
menuVisible && /* @__PURE__ */
|
|
40936
|
+
menuVisible && /* @__PURE__ */ jsx36(
|
|
40606
40937
|
ContextMenu,
|
|
40607
40938
|
{
|
|
40608
40939
|
menuRef,
|
|
@@ -40622,8 +40953,19 @@ var CadViewerInner = (props) => {
|
|
|
40622
40953
|
onDownloadGltf: () => {
|
|
40623
40954
|
downloadGltf();
|
|
40624
40955
|
closeMenu();
|
|
40956
|
+
},
|
|
40957
|
+
onOpenKeyboardShortcuts: () => {
|
|
40958
|
+
setIsKeyboardShortcutsDialogOpen(true);
|
|
40959
|
+
closeMenu();
|
|
40625
40960
|
}
|
|
40626
40961
|
}
|
|
40962
|
+
),
|
|
40963
|
+
/* @__PURE__ */ jsx36(
|
|
40964
|
+
KeyboardShortcutsDialog,
|
|
40965
|
+
{
|
|
40966
|
+
open: isKeyboardShortcutsDialogOpen,
|
|
40967
|
+
onClose: () => setIsKeyboardShortcutsDialogOpen(false)
|
|
40968
|
+
}
|
|
40627
40969
|
)
|
|
40628
40970
|
]
|
|
40629
40971
|
},
|
|
@@ -40631,17 +40973,17 @@ var CadViewerInner = (props) => {
|
|
|
40631
40973
|
);
|
|
40632
40974
|
};
|
|
40633
40975
|
var CadViewer = (props) => {
|
|
40634
|
-
const defaultTarget =
|
|
40635
|
-
const initialCameraPosition =
|
|
40976
|
+
const defaultTarget = useMemo28(() => new THREE29.Vector3(0, 0, 0), []);
|
|
40977
|
+
const initialCameraPosition = useMemo28(
|
|
40636
40978
|
() => [5, -5, 5],
|
|
40637
40979
|
[]
|
|
40638
40980
|
);
|
|
40639
|
-
return /* @__PURE__ */
|
|
40981
|
+
return /* @__PURE__ */ jsx36(
|
|
40640
40982
|
CameraControllerProvider,
|
|
40641
40983
|
{
|
|
40642
40984
|
defaultTarget,
|
|
40643
40985
|
initialCameraPosition,
|
|
40644
|
-
children: /* @__PURE__ */
|
|
40986
|
+
children: /* @__PURE__ */ jsx36(LayerVisibilityProvider, { children: /* @__PURE__ */ jsx36(CadViewerInner, { ...props }) })
|
|
40645
40987
|
}
|
|
40646
40988
|
);
|
|
40647
40989
|
};
|
|
@@ -40925,10 +41267,10 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
40925
41267
|
|
|
40926
41268
|
// src/hooks/exporter/gltf.ts
|
|
40927
41269
|
import { GLTFExporter as GLTFExporter2 } from "three-stdlib";
|
|
40928
|
-
import { useEffect as
|
|
41270
|
+
import { useEffect as useEffect43, useState as useState37, useMemo as useMemo29, useCallback as useCallback23 } from "react";
|
|
40929
41271
|
function useSaveGltfAs(options = {}) {
|
|
40930
41272
|
const parse2 = useParser(options);
|
|
40931
|
-
const link =
|
|
41273
|
+
const link = useMemo29(() => document.createElement("a"), []);
|
|
40932
41274
|
const saveAs = async (filename) => {
|
|
40933
41275
|
const name = filename ?? options.filename ?? "";
|
|
40934
41276
|
if (options.binary == null) options.binary = name.endsWith(".glb");
|
|
@@ -40938,7 +41280,7 @@ function useSaveGltfAs(options = {}) {
|
|
|
40938
41280
|
link.dispatchEvent(new MouseEvent("click"));
|
|
40939
41281
|
URL.revokeObjectURL(url);
|
|
40940
41282
|
};
|
|
40941
|
-
|
|
41283
|
+
useEffect43(
|
|
40942
41284
|
() => () => {
|
|
40943
41285
|
link.remove();
|
|
40944
41286
|
instance = null;
|
|
@@ -40953,17 +41295,17 @@ function useSaveGltfAs(options = {}) {
|
|
|
40953
41295
|
}
|
|
40954
41296
|
function useExportGltfUrl(options = {}) {
|
|
40955
41297
|
const parse2 = useParser(options);
|
|
40956
|
-
const [url, setUrl] =
|
|
40957
|
-
const [error, setError] =
|
|
41298
|
+
const [url, setUrl] = useState37();
|
|
41299
|
+
const [error, setError] = useState37();
|
|
40958
41300
|
const ref = useCallback23(
|
|
40959
41301
|
(instance) => parse2(instance).then(setUrl).catch(setError),
|
|
40960
41302
|
[]
|
|
40961
41303
|
);
|
|
40962
|
-
|
|
41304
|
+
useEffect43(() => () => URL.revokeObjectURL(url), [url]);
|
|
40963
41305
|
return [ref, url, error];
|
|
40964
41306
|
}
|
|
40965
41307
|
function useParser(options = {}) {
|
|
40966
|
-
const exporter =
|
|
41308
|
+
const exporter = useMemo29(() => new GLTFExporter2(), []);
|
|
40967
41309
|
return (instance) => {
|
|
40968
41310
|
const { promise, resolve, reject } = Promise.withResolvers();
|
|
40969
41311
|
exporter.parse(
|