react-os-shell 0.1.32 → 0.1.36
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/{Calculator-ZZMTB7Y7.js → Calculator-VZM3FSTQ.js} +4 -4
- package/dist/{Calculator-ZZMTB7Y7.js.map → Calculator-VZM3FSTQ.js.map} +1 -1
- package/dist/{Calendar-RQVSPJAJ.js → Calendar-7DNNMOKO.js} +3 -3
- package/dist/{Calendar-RQVSPJAJ.js.map → Calendar-7DNNMOKO.js.map} +1 -1
- package/dist/{CurrencyConverter-S37JTKKZ.js → CurrencyConverter-XFIGUZ46.js} +4 -4
- package/dist/{CurrencyConverter-S37JTKKZ.js.map → CurrencyConverter-XFIGUZ46.js.map} +1 -1
- package/dist/{Documents-3P6JKOLE.js → Documents-PK7QFWGR.js} +3 -3
- package/dist/{Documents-3P6JKOLE.js.map → Documents-PK7QFWGR.js.map} +1 -1
- package/dist/{Email-UCNJ53MV.js → Email-66BDCI2Q.js} +3 -3
- package/dist/{Email-UCNJ53MV.js.map → Email-66BDCI2Q.js.map} +1 -1
- package/dist/{Minesweeper-KAOD327F.js → Minesweeper-7OGCUAKF.js} +3 -3
- package/dist/{Minesweeper-KAOD327F.js.map → Minesweeper-7OGCUAKF.js.map} +1 -1
- package/dist/{Notepad-C453L2M2.js → Notepad-MNDA6AHQ.js} +3 -3
- package/dist/{Notepad-C453L2M2.js.map → Notepad-MNDA6AHQ.js.map} +1 -1
- package/dist/{PomodoroTimer-ZZUXEFM6.js → PomodoroTimer-6DHC3H6X.js} +4 -4
- package/dist/{PomodoroTimer-ZZUXEFM6.js.map → PomodoroTimer-6DHC3H6X.js.map} +1 -1
- package/dist/Preview-WIXANNFW.js +6 -0
- package/dist/{Preview-X2TQ32VM.js.map → Preview-WIXANNFW.js.map} +1 -1
- package/dist/{Spreadsheet-SOJL4SQA.js → Spreadsheet-JT4TIKCY.js} +3 -3
- package/dist/{Spreadsheet-SOJL4SQA.js.map → Spreadsheet-JT4TIKCY.js.map} +1 -1
- package/dist/{Weather-H7R7YVRB.js → Weather-A6MEC4PN.js} +4 -4
- package/dist/{Weather-H7R7YVRB.js.map → Weather-A6MEC4PN.js.map} +1 -1
- package/dist/apps/index.js +13 -13
- package/dist/{chunk-AKZTZLKP.js → chunk-44AH2OXU.js} +3 -3
- package/dist/{chunk-AKZTZLKP.js.map → chunk-44AH2OXU.js.map} +1 -1
- package/dist/{chunk-CZKAKVP6.js → chunk-IQWRDQHW.js} +242 -155
- package/dist/chunk-IQWRDQHW.js.map +1 -0
- package/dist/{chunk-D7UDGZIH.js → chunk-UUJLLTV4.js} +3 -3
- package/dist/{chunk-D7UDGZIH.js.map → chunk-UUJLLTV4.js.map} +1 -1
- package/dist/index.js +4 -4
- package/package.json +1 -1
- package/dist/Preview-X2TQ32VM.js +0 -6
- package/dist/chunk-CZKAKVP6.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { toast_default } from './chunk-WIJ45SYD.js';
|
|
2
|
-
import { WindowTitle } from './chunk-
|
|
2
|
+
import { WindowTitle, getActiveModalId } from './chunk-44AH2OXU.js';
|
|
3
3
|
import { useState, useEffect, useRef } from 'react';
|
|
4
4
|
import * as pdfjsLib from 'pdfjs-dist';
|
|
5
5
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
@@ -43,19 +43,49 @@ function Preview() {
|
|
|
43
43
|
}, []);
|
|
44
44
|
const titleName = data?.filename ? truncateForTitle(data.filename) : "Untitled";
|
|
45
45
|
const fileRef = useRef(null);
|
|
46
|
+
const rootRef = useRef(null);
|
|
46
47
|
const [isDragging, setIsDragging] = useState(false);
|
|
48
|
+
const dragDepthRef = useRef(0);
|
|
47
49
|
const handlePick = () => fileRef.current?.click();
|
|
50
|
+
const resetDrag = () => {
|
|
51
|
+
dragDepthRef.current = 0;
|
|
52
|
+
setIsDragging(false);
|
|
53
|
+
};
|
|
54
|
+
const isActiveWindow = (el) => {
|
|
55
|
+
const myModal = el.closest("[data-modal-id]");
|
|
56
|
+
if (!myModal) return true;
|
|
57
|
+
return getActiveModalId() === myModal.dataset.modalId;
|
|
58
|
+
};
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
const onWindowDragEnd = () => resetDrag();
|
|
61
|
+
const onWindowDrop = () => resetDrag();
|
|
62
|
+
const onKey = (e) => {
|
|
63
|
+
if (e.key === "Escape") resetDrag();
|
|
64
|
+
};
|
|
65
|
+
window.addEventListener("dragend", onWindowDragEnd);
|
|
66
|
+
window.addEventListener("drop", onWindowDrop);
|
|
67
|
+
window.addEventListener("keydown", onKey);
|
|
68
|
+
return () => {
|
|
69
|
+
window.removeEventListener("dragend", onWindowDragEnd);
|
|
70
|
+
window.removeEventListener("drop", onWindowDrop);
|
|
71
|
+
window.removeEventListener("keydown", onKey);
|
|
72
|
+
};
|
|
73
|
+
}, []);
|
|
48
74
|
const ingestFile = (file) => {
|
|
49
|
-
const url = URL.createObjectURL(file);
|
|
50
75
|
const ext = (file.name.split(".").pop() || "").toLowerCase();
|
|
51
76
|
const kind = ext === "pdf" ? "pdf" : ext === "dxf" ? "dxf" : ["jpg", "jpeg", "png", "gif", "webp", "svg", "avif", "bmp"].includes(ext) ? "image" : ["stp", "step", "stl", "obj", "gltf", "glb", "3mf", "iges", "igs", "ply", "fbx"].includes(ext) ? "3d" : void 0;
|
|
52
77
|
if (!kind) {
|
|
53
|
-
URL.revokeObjectURL(url);
|
|
54
78
|
if (ext === "dwg") toast_default.error("DWG files need server-side conversion. Convert to PDF or DXF first.");
|
|
55
79
|
else toast_default.error(`Unsupported file type: .${ext || "unknown"}`);
|
|
56
80
|
return;
|
|
57
81
|
}
|
|
58
|
-
|
|
82
|
+
const url = URL.createObjectURL(file);
|
|
83
|
+
setData((prev) => {
|
|
84
|
+
if (prev?.url?.startsWith("blob:") && prev.url !== url) {
|
|
85
|
+
URL.revokeObjectURL(prev.url);
|
|
86
|
+
}
|
|
87
|
+
return { url, filename: file.name, kind };
|
|
88
|
+
});
|
|
59
89
|
};
|
|
60
90
|
const handleFile = (e) => {
|
|
61
91
|
const file = e.target.files?.[0];
|
|
@@ -64,7 +94,7 @@ function Preview() {
|
|
|
64
94
|
};
|
|
65
95
|
const handleDrop = (e) => {
|
|
66
96
|
e.preventDefault();
|
|
67
|
-
|
|
97
|
+
resetDrag();
|
|
68
98
|
const file = e.dataTransfer.files?.[0];
|
|
69
99
|
if (file) ingestFile(file);
|
|
70
100
|
};
|
|
@@ -147,14 +177,30 @@ function Preview() {
|
|
|
147
177
|
"div",
|
|
148
178
|
{
|
|
149
179
|
className: "relative flex flex-col h-full",
|
|
150
|
-
|
|
180
|
+
ref: rootRef,
|
|
181
|
+
onDragEnter: (e) => {
|
|
182
|
+
if (!e.dataTransfer?.types?.includes?.("Files")) return;
|
|
183
|
+
if (!isActiveWindow(e.currentTarget)) return;
|
|
151
184
|
e.preventDefault();
|
|
185
|
+
dragDepthRef.current++;
|
|
152
186
|
if (!isDragging) setIsDragging(true);
|
|
153
187
|
},
|
|
154
|
-
|
|
155
|
-
if (e.
|
|
188
|
+
onDragOver: (e) => {
|
|
189
|
+
if (!e.dataTransfer?.types?.includes?.("Files")) return;
|
|
190
|
+
if (!isActiveWindow(e.currentTarget)) return;
|
|
191
|
+
e.preventDefault();
|
|
192
|
+
},
|
|
193
|
+
onDragLeave: () => {
|
|
194
|
+
if (dragDepthRef.current > 0) dragDepthRef.current--;
|
|
195
|
+
if (dragDepthRef.current === 0) setIsDragging(false);
|
|
196
|
+
},
|
|
197
|
+
onDrop: (e) => {
|
|
198
|
+
if (!isActiveWindow(e.currentTarget)) {
|
|
199
|
+
resetDrag();
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
handleDrop(e);
|
|
156
203
|
},
|
|
157
|
-
onDrop: handleDrop,
|
|
158
204
|
children: [
|
|
159
205
|
/* @__PURE__ */ jsx(WindowTitle, { title: `${titleName} - Preview` }),
|
|
160
206
|
Toolbar,
|
|
@@ -604,7 +650,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
|
|
|
604
650
|
const [sectionAxis, setSectionAxis] = useState("z");
|
|
605
651
|
const [sectionFlip, setSectionFlip] = useState(false);
|
|
606
652
|
const [sectionPosition, setSectionPosition] = useState(0.5);
|
|
607
|
-
const [sectionCapColor, setSectionCapColor] = useState("#
|
|
653
|
+
const [sectionCapColor, setSectionCapColor] = useState("#c8ccd1");
|
|
608
654
|
const sectionRef = useRef(null);
|
|
609
655
|
useEffect(() => {
|
|
610
656
|
let cancelled = false;
|
|
@@ -729,115 +775,159 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
|
|
|
729
775
|
useEffect(() => {
|
|
730
776
|
const v = viewerRef.current;
|
|
731
777
|
if (!v?.viewer || loading) return;
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
(
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
const
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
const s = sectionRef.current;
|
|
742
|
-
for (const [mat, prev] of s.materialState.entries()) {
|
|
743
|
-
mat.clippingPlanes = prev.clippingPlanes;
|
|
744
|
-
mat.clipShadows = prev.clipShadows;
|
|
745
|
-
mat.needsUpdate = true;
|
|
746
|
-
}
|
|
747
|
-
for (const helper of s.helpers) {
|
|
748
|
-
helper.parent?.remove(helper);
|
|
749
|
-
helper.geometry?.dispose?.();
|
|
750
|
-
helper.material?.dispose?.();
|
|
751
|
-
}
|
|
752
|
-
if (s.capMesh) {
|
|
753
|
-
scene.remove(s.capMesh);
|
|
754
|
-
s.capMesh.geometry?.dispose?.();
|
|
755
|
-
s.capMesh.material?.dispose?.();
|
|
756
|
-
}
|
|
757
|
-
sectionRef.current = null;
|
|
778
|
+
const renderer = v.viewer.renderer;
|
|
779
|
+
const scene = v.viewer.scene;
|
|
780
|
+
if (!renderer || !scene) return;
|
|
781
|
+
if (sectionRef.current) {
|
|
782
|
+
const s = sectionRef.current;
|
|
783
|
+
for (const [mat, prev] of s.materialState.entries()) {
|
|
784
|
+
mat.clippingPlanes = prev.clippingPlanes;
|
|
785
|
+
mat.clipShadows = prev.clipShadows;
|
|
786
|
+
mat.needsUpdate = true;
|
|
758
787
|
}
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
return;
|
|
788
|
+
for (const helper of s.helpers) {
|
|
789
|
+
helper.parent?.remove(helper);
|
|
790
|
+
helper.material?.dispose?.();
|
|
763
791
|
}
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
792
|
+
if (s.capMesh) {
|
|
793
|
+
scene.remove(s.capMesh);
|
|
794
|
+
s.capMesh.geometry?.dispose?.();
|
|
795
|
+
s.capMesh.material?.dispose?.();
|
|
796
|
+
}
|
|
797
|
+
sectionRef.current = null;
|
|
798
|
+
}
|
|
799
|
+
if (!sectionEnabled) {
|
|
800
|
+
renderer.localClippingEnabled = false;
|
|
801
|
+
v.viewer.Render?.();
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
804
|
+
const bbox = v.viewer.GetBoundingBox?.(() => true);
|
|
805
|
+
if (!bbox) return;
|
|
806
|
+
const targets = [];
|
|
807
|
+
v.viewer.mainModel?.EnumerateMeshes?.((mesh) => {
|
|
808
|
+
if (!mesh.userData?.__sectionHelper) targets.push(mesh);
|
|
809
|
+
});
|
|
810
|
+
if (!targets.length) {
|
|
811
|
+
renderer.localClippingEnabled = false;
|
|
812
|
+
v.viewer.Render?.();
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
815
|
+
const sample = targets[0];
|
|
816
|
+
const Mesh = sample.constructor;
|
|
817
|
+
const Material = sample.material?.constructor;
|
|
818
|
+
const Geometry = sample.geometry?.constructor;
|
|
819
|
+
const BufferAttr = sample.geometry?.attributes?.position?.constructor;
|
|
820
|
+
if (!Mesh || !Material || !Geometry || !BufferAttr) {
|
|
821
|
+
console.warn("[Preview] section: missing THREE constructors, falling back to no cap");
|
|
822
|
+
}
|
|
823
|
+
const FrontSide = 0, BackSide = 1, DoubleSide = 2;
|
|
824
|
+
const AlwaysStencilFunc = 519, NotEqualStencilFunc = 517;
|
|
825
|
+
const IncrementWrapStencilOp = 7682, DecrementWrapStencilOp = 7683;
|
|
826
|
+
const ReplaceStencilOp = 7681;
|
|
827
|
+
const plane = { normal: { x: 0, y: 0, z: -1 }, constant: 0 };
|
|
828
|
+
const helpers = [];
|
|
829
|
+
const materialState = /* @__PURE__ */ new Map();
|
|
830
|
+
const applyToMaterial = (mat) => {
|
|
831
|
+
if (!mat || materialState.has(mat)) return;
|
|
832
|
+
materialState.set(mat, { clippingPlanes: mat.clippingPlanes, clipShadows: mat.clipShadows });
|
|
833
|
+
mat.clippingPlanes = [plane];
|
|
834
|
+
mat.clipShadows = true;
|
|
835
|
+
mat.needsUpdate = true;
|
|
836
|
+
};
|
|
837
|
+
for (const mesh of targets) {
|
|
838
|
+
const mat = mesh.material;
|
|
839
|
+
if (Array.isArray(mat)) for (const m of mat) applyToMaterial(m);
|
|
840
|
+
else applyToMaterial(mat);
|
|
841
|
+
if (Mesh && Material) {
|
|
788
842
|
const makeStencil = (side, op) => {
|
|
789
|
-
const m = new
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
const helper = new
|
|
843
|
+
const m = new Material();
|
|
844
|
+
m.depthWrite = false;
|
|
845
|
+
m.depthTest = false;
|
|
846
|
+
m.colorWrite = false;
|
|
847
|
+
m.stencilWrite = true;
|
|
848
|
+
m.stencilFunc = AlwaysStencilFunc;
|
|
849
|
+
m.stencilFail = op;
|
|
850
|
+
m.stencilZFail = op;
|
|
851
|
+
m.stencilZPass = op;
|
|
852
|
+
m.side = side;
|
|
853
|
+
m.clippingPlanes = [plane];
|
|
854
|
+
m.clipShadows = true;
|
|
855
|
+
const helper = new Mesh(mesh.geometry, m);
|
|
802
856
|
helper.matrixAutoUpdate = false;
|
|
803
857
|
helper.renderOrder = 1;
|
|
804
858
|
helper.userData.__sectionHelper = true;
|
|
805
859
|
mesh.add(helper);
|
|
806
860
|
helpers.push(helper);
|
|
807
861
|
};
|
|
808
|
-
makeStencil(
|
|
809
|
-
makeStencil(
|
|
862
|
+
makeStencil(BackSide, IncrementWrapStencilOp);
|
|
863
|
+
makeStencil(FrontSide, DecrementWrapStencilOp);
|
|
810
864
|
}
|
|
865
|
+
}
|
|
866
|
+
v.viewer.mainModel?.EnumerateEdges?.((edge) => {
|
|
867
|
+
const mat = edge.material;
|
|
868
|
+
if (Array.isArray(mat)) for (const m of mat) applyToMaterial(m);
|
|
869
|
+
else applyToMaterial(mat);
|
|
870
|
+
});
|
|
871
|
+
let capMesh = null;
|
|
872
|
+
if (Mesh && Material && Geometry && BufferAttr) {
|
|
811
873
|
const dx = bbox.max.x - bbox.min.x;
|
|
812
874
|
const dy = bbox.max.y - bbox.min.y;
|
|
813
875
|
const dz = bbox.max.z - bbox.min.z;
|
|
814
|
-
const capSize = Math.max(dx, dy, dz) * 2
|
|
815
|
-
const
|
|
816
|
-
const
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
876
|
+
const capSize = Math.max(dx, dy, dz, 1) * 2;
|
|
877
|
+
const half = capSize / 2;
|
|
878
|
+
const capGeom = new Geometry();
|
|
879
|
+
const positions = new Float32Array([
|
|
880
|
+
-half,
|
|
881
|
+
-half,
|
|
882
|
+
0,
|
|
883
|
+
half,
|
|
884
|
+
-half,
|
|
885
|
+
0,
|
|
886
|
+
half,
|
|
887
|
+
half,
|
|
888
|
+
0,
|
|
889
|
+
-half,
|
|
890
|
+
half,
|
|
891
|
+
0
|
|
892
|
+
]);
|
|
893
|
+
const normals = new Float32Array([
|
|
894
|
+
0,
|
|
895
|
+
0,
|
|
896
|
+
1,
|
|
897
|
+
0,
|
|
898
|
+
0,
|
|
899
|
+
1,
|
|
900
|
+
0,
|
|
901
|
+
0,
|
|
902
|
+
1,
|
|
903
|
+
0,
|
|
904
|
+
0,
|
|
905
|
+
1
|
|
906
|
+
]);
|
|
907
|
+
capGeom.setAttribute("position", new BufferAttr(positions, 3));
|
|
908
|
+
capGeom.setAttribute("normal", new BufferAttr(normals, 3));
|
|
909
|
+
capGeom.setIndex([0, 1, 2, 0, 2, 3]);
|
|
910
|
+
const capMat = new Material();
|
|
911
|
+
const m = /^#?([0-9a-f]{6})$/i.exec(sectionCapColor);
|
|
912
|
+
const colorHex = m ? parseInt(m[1], 16) : 13159633;
|
|
913
|
+
capMat.color?.setHex?.(colorHex);
|
|
914
|
+
capMat.side = DoubleSide;
|
|
915
|
+
capMat.stencilWrite = true;
|
|
916
|
+
capMat.stencilRef = 0;
|
|
917
|
+
capMat.stencilFunc = NotEqualStencilFunc;
|
|
918
|
+
capMat.stencilFail = ReplaceStencilOp;
|
|
919
|
+
capMat.stencilZFail = ReplaceStencilOp;
|
|
920
|
+
capMat.stencilZPass = ReplaceStencilOp;
|
|
921
|
+
capMat.clippingPlanes = [];
|
|
922
|
+
capMesh = new Mesh(capGeom, capMat);
|
|
827
923
|
capMesh.renderOrder = 2;
|
|
828
924
|
capMesh.userData.__sectionHelper = true;
|
|
829
925
|
scene.add(capMesh);
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
})();
|
|
836
|
-
return () => {
|
|
837
|
-
cancelled = true;
|
|
838
|
-
if (teardown) teardown();
|
|
839
|
-
};
|
|
840
|
-
}, [sectionEnabled, loading, tree]);
|
|
926
|
+
}
|
|
927
|
+
renderer.localClippingEnabled = true;
|
|
928
|
+
sectionRef.current = { plane, capMesh, helpers, materialState, bbox };
|
|
929
|
+
v.viewer.Render?.();
|
|
930
|
+
}, [sectionEnabled, loading, tree, sectionCapColor]);
|
|
841
931
|
useEffect(() => {
|
|
842
932
|
const v = viewerRef.current;
|
|
843
933
|
const s = sectionRef.current;
|
|
@@ -852,29 +942,26 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
|
|
|
852
942
|
const nx = sectionAxis === "x" ? dir : 0;
|
|
853
943
|
const ny = sectionAxis === "y" ? dir : 0;
|
|
854
944
|
const nz = sectionAxis === "z" ? dir : 0;
|
|
855
|
-
s.plane.normal.
|
|
945
|
+
s.plane.normal.x = nx;
|
|
946
|
+
s.plane.normal.y = ny;
|
|
947
|
+
s.plane.normal.z = nz;
|
|
856
948
|
s.plane.constant = -dir * value;
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
try {
|
|
868
|
-
const m = /^#?([0-9a-f]{6})$/i.exec(sectionCapColor);
|
|
869
|
-
const n = m ? parseInt(m[1], 16) : 10135219;
|
|
870
|
-
s.capMesh.material.color.setHex(n);
|
|
871
|
-
} catch {
|
|
949
|
+
if (s.capMesh) {
|
|
950
|
+
const cx = (bbox.min.x + bbox.max.x) / 2;
|
|
951
|
+
const cy = (bbox.min.y + bbox.max.y) / 2;
|
|
952
|
+
const cz = (bbox.min.z + bbox.max.z) / 2;
|
|
953
|
+
const dist = nx * cx + ny * cy + nz * cz + s.plane.constant;
|
|
954
|
+
const px = cx - nx * dist;
|
|
955
|
+
const py = cy - ny * dist;
|
|
956
|
+
const pz = cz - nz * dist;
|
|
957
|
+
s.capMesh.position.set(px, py, pz);
|
|
958
|
+
s.capMesh.lookAt?.(px + nx, py + ny, pz + nz);
|
|
872
959
|
}
|
|
873
960
|
v.viewer.Render?.();
|
|
874
961
|
} catch (err) {
|
|
875
962
|
console.warn("[Preview] section update failed", err);
|
|
876
963
|
}
|
|
877
|
-
}, [sectionEnabled, sectionAxis, sectionFlip, sectionPosition
|
|
964
|
+
}, [sectionEnabled, sectionAxis, sectionFlip, sectionPosition]);
|
|
878
965
|
useEffect(() => {
|
|
879
966
|
if (!showHint || loading) return;
|
|
880
967
|
const t = setTimeout(() => setShowHint(false), 5e3);
|
|
@@ -902,7 +989,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
|
|
|
902
989
|
const handleFit = () => {
|
|
903
990
|
try {
|
|
904
991
|
const v = viewerRef.current;
|
|
905
|
-
const sphere = v?.GetBoundingSphere?.(() => true);
|
|
992
|
+
const sphere = v?.viewer?.GetBoundingSphere?.(() => true);
|
|
906
993
|
if (sphere) v.viewer.FitSphereToWindow(sphere, true);
|
|
907
994
|
v?.viewer?.Render?.();
|
|
908
995
|
} catch {
|
|
@@ -913,7 +1000,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
|
|
|
913
1000
|
const v = viewerRef.current;
|
|
914
1001
|
if (!OV || !v?.viewer) return;
|
|
915
1002
|
try {
|
|
916
|
-
const sphere = v.GetBoundingSphere?.(() => true);
|
|
1003
|
+
const sphere = v.viewer.GetBoundingSphere?.(() => true);
|
|
917
1004
|
if (!sphere) return;
|
|
918
1005
|
const c = sphere.center;
|
|
919
1006
|
const r = sphere.radius || 1;
|
|
@@ -971,7 +1058,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
|
|
|
971
1058
|
setSectionAxis("z");
|
|
972
1059
|
setSectionFlip(false);
|
|
973
1060
|
setSectionPosition(0.5);
|
|
974
|
-
setSectionCapColor("#
|
|
1061
|
+
setSectionCapColor("#c8ccd1");
|
|
975
1062
|
};
|
|
976
1063
|
const handleDefaultDownload = () => {
|
|
977
1064
|
const a = document.createElement("a");
|
|
@@ -988,24 +1075,24 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
|
|
|
988
1075
|
/* @__PURE__ */ jsxs(
|
|
989
1076
|
"div",
|
|
990
1077
|
{
|
|
991
|
-
className: "group flex items-center gap-1 px-1.5 py-1 hover:bg-
|
|
1078
|
+
className: "group flex items-center gap-1 px-1.5 py-1 hover:bg-gray-100 cursor-default text-[12px] text-gray-700",
|
|
992
1079
|
style: { paddingLeft: `${depth * 12 + 6}px` },
|
|
993
1080
|
children: [
|
|
994
1081
|
hasChildren ? /* @__PURE__ */ jsx(
|
|
995
1082
|
"button",
|
|
996
1083
|
{
|
|
997
1084
|
onClick: () => toggleExpanded(node.id),
|
|
998
|
-
className: "h-4 w-4 shrink-0 flex items-center justify-center text-
|
|
1085
|
+
className: "h-4 w-4 shrink-0 flex items-center justify-center text-gray-500 hover:text-gray-900",
|
|
999
1086
|
title: isExpanded ? "Collapse" : "Expand",
|
|
1000
1087
|
children: /* @__PURE__ */ jsx("svg", { className: "h-3 w-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: isExpanded ? "M19.5 8.25l-7.5 7.5-7.5-7.5" : "M8.25 4.5l7.5 7.5-7.5 7.5" }) })
|
|
1001
1088
|
}
|
|
1002
|
-
) : /* @__PURE__ */ jsx("span", { className: "h-4 w-4 shrink-0 flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "h-1 w-1 rounded-full bg-
|
|
1089
|
+
) : /* @__PURE__ */ jsx("span", { className: "h-4 w-4 shrink-0 flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "h-1 w-1 rounded-full bg-gray-400" }) }),
|
|
1003
1090
|
/* @__PURE__ */ jsx("span", { className: `flex-1 truncate ${isVisible ? "" : "opacity-40"}`, title: node.name, children: node.name }),
|
|
1004
1091
|
/* @__PURE__ */ jsx(
|
|
1005
1092
|
"button",
|
|
1006
1093
|
{
|
|
1007
1094
|
onClick: () => fitNode(),
|
|
1008
|
-
className: "h-4 w-4 shrink-0 text-
|
|
1095
|
+
className: "h-4 w-4 shrink-0 text-gray-400 hover:text-gray-900 opacity-0 group-hover:opacity-100 transition-opacity",
|
|
1009
1096
|
title: "Fit to view",
|
|
1010
1097
|
children: /* @__PURE__ */ jsx("svg", { className: "h-3.5 w-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15" }) })
|
|
1011
1098
|
}
|
|
@@ -1014,7 +1101,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
|
|
|
1014
1101
|
"button",
|
|
1015
1102
|
{
|
|
1016
1103
|
onClick: () => toggleNodeVisible(node),
|
|
1017
|
-
className: "h-4 w-4 shrink-0 text-
|
|
1104
|
+
className: "h-4 w-4 shrink-0 text-gray-500 hover:text-gray-900",
|
|
1018
1105
|
title: isVisible ? "Hide" : "Show",
|
|
1019
1106
|
children: isVisible ? /* @__PURE__ */ jsxs("svg", { className: "h-3.5 w-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: [
|
|
1020
1107
|
/* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z" }),
|
|
@@ -1028,12 +1115,12 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
|
|
|
1028
1115
|
isExpanded && hasChildren && /* @__PURE__ */ jsx("div", { children: node.children.map((c) => renderTreeNode(c, depth + 1)) })
|
|
1029
1116
|
] }, node.id);
|
|
1030
1117
|
};
|
|
1031
|
-
const tBtn = "h-8 w-8 shrink-0 flex items-center justify-center rounded text-
|
|
1032
|
-
const tBtnActive = "h-8 w-8 shrink-0 flex items-center justify-center rounded bg-
|
|
1033
|
-
const tBtnSep = "h-5 w-px bg-
|
|
1034
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full bg-
|
|
1035
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 px-2 py-1.5 bg-
|
|
1036
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-semibold tracking-wide text-
|
|
1118
|
+
const tBtn = "h-8 w-8 shrink-0 flex items-center justify-center rounded text-gray-600 hover:bg-gray-200 hover:text-gray-900 transition-colors";
|
|
1119
|
+
const tBtnActive = "h-8 w-8 shrink-0 flex items-center justify-center rounded bg-gray-200 text-gray-900";
|
|
1120
|
+
const tBtnSep = "h-5 w-px bg-gray-300 mx-1";
|
|
1121
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full bg-white", children: [
|
|
1122
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 px-2 py-1.5 bg-gray-50 border-b border-gray-200 shrink-0", children: [
|
|
1123
|
+
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-semibold tracking-wide text-gray-700 px-2 truncate max-w-xs", title: filename, children: filename }),
|
|
1037
1124
|
/* @__PURE__ */ jsx("div", { className: tBtnSep }),
|
|
1038
1125
|
/* @__PURE__ */ jsx("button", { onClick: handleFit, className: tBtn, title: "Fit to view", children: /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15" }) }) }),
|
|
1039
1126
|
/* @__PURE__ */ jsx("div", { className: tBtnSep }),
|
|
@@ -1057,10 +1144,10 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
|
|
|
1057
1144
|
onEmail && /* @__PURE__ */ jsx("button", { onClick: onEmail, className: tBtn, title: "Email", children: /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0 01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25 2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75" }) }) })
|
|
1058
1145
|
] }),
|
|
1059
1146
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 flex min-h-0", children: [
|
|
1060
|
-
showMeshes && /* @__PURE__ */ jsxs("div", { className: "w-60 shrink-0 bg-
|
|
1061
|
-
/* @__PURE__ */ jsx("div", { className: "px-3 py-2 text-[11px] font-semibold uppercase tracking-wide text-
|
|
1062
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto py-1", children: tree ? renderTreeNode(tree) : /* @__PURE__ */ jsx("div", { className: "px-3 py-3 text-[11px] text-
|
|
1063
|
-
tree && /* @__PURE__ */ jsx("div", { className: "px-3 py-1.5 text-[10px] text-
|
|
1147
|
+
showMeshes && /* @__PURE__ */ jsxs("div", { className: "w-60 shrink-0 bg-gray-50 border-r border-gray-200 flex flex-col", children: [
|
|
1148
|
+
/* @__PURE__ */ jsx("div", { className: "px-3 py-2 text-[11px] font-semibold uppercase tracking-wide text-gray-500 border-b border-gray-200", children: "Meshes" }),
|
|
1149
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto py-1", children: tree ? renderTreeNode(tree) : /* @__PURE__ */ jsx("div", { className: "px-3 py-3 text-[11px] text-gray-500 italic", children: loading ? "Reading model\u2026" : "No structure available" }) }),
|
|
1150
|
+
tree && /* @__PURE__ */ jsx("div", { className: "px-3 py-1.5 text-[10px] text-gray-500 border-t border-gray-200", children: hidden.size === 0 ? "All visible" : `${hidden.size} hidden` })
|
|
1064
1151
|
] }),
|
|
1065
1152
|
/* @__PURE__ */ jsxs("div", { className: "relative flex-1 min-w-0", style: { background: bgColor }, children: [
|
|
1066
1153
|
/* @__PURE__ */ jsx("div", { ref: containerRef, style: { width: "100%", height: "100%" } }),
|
|
@@ -1081,12 +1168,12 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
|
|
|
1081
1168
|
] }),
|
|
1082
1169
|
error && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center text-sm text-red-600 px-6 text-center bg-white/85", children: error })
|
|
1083
1170
|
] }),
|
|
1084
|
-
showSettings && /* @__PURE__ */ jsxs("div", { className: "w-60 shrink-0 bg-
|
|
1085
|
-
/* @__PURE__ */ jsx("div", { className: "px-3 py-2 text-[11px] font-semibold uppercase tracking-wide text-
|
|
1086
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto px-3 py-3 space-y-3 text-[12px] text-
|
|
1171
|
+
showSettings && /* @__PURE__ */ jsxs("div", { className: "w-60 shrink-0 bg-gray-50 border-l border-gray-200 flex flex-col", children: [
|
|
1172
|
+
/* @__PURE__ */ jsx("div", { className: "px-3 py-2 text-[11px] font-semibold uppercase tracking-wide text-gray-500 border-b border-gray-200", children: "Model Display" }),
|
|
1173
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto px-3 py-3 space-y-3 text-[12px] text-gray-700", children: [
|
|
1087
1174
|
/* @__PURE__ */ jsxs("label", { className: "flex items-center justify-between gap-2", children: [
|
|
1088
1175
|
/* @__PURE__ */ jsx("span", { children: "Background Color" }),
|
|
1089
|
-
/* @__PURE__ */ jsx("input", { type: "color", value: bgColor, onChange: (e) => setBgColor(e.target.value), className: "h-6 w-10 rounded border border-
|
|
1176
|
+
/* @__PURE__ */ jsx("input", { type: "color", value: bgColor, onChange: (e) => setBgColor(e.target.value), className: "h-6 w-10 rounded border border-gray-300 bg-white" })
|
|
1090
1177
|
] }),
|
|
1091
1178
|
/* @__PURE__ */ jsxs("label", { className: "flex items-center justify-between gap-2", children: [
|
|
1092
1179
|
/* @__PURE__ */ jsx("span", { children: "Show Edges" }),
|
|
@@ -1094,7 +1181,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
|
|
|
1094
1181
|
"button",
|
|
1095
1182
|
{
|
|
1096
1183
|
onClick: () => setShowEdges((s) => !s),
|
|
1097
|
-
className: `relative h-5 w-9 rounded-full transition-colors ${showEdges ? "bg-blue-500" : "bg-
|
|
1184
|
+
className: `relative h-5 w-9 rounded-full transition-colors ${showEdges ? "bg-blue-500" : "bg-gray-300"}`,
|
|
1098
1185
|
children: /* @__PURE__ */ jsx("span", { className: `absolute top-0.5 h-4 w-4 rounded-full bg-white transition-transform ${showEdges ? "translate-x-4" : "translate-x-0.5"}` })
|
|
1099
1186
|
}
|
|
1100
1187
|
)
|
|
@@ -1108,14 +1195,14 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
|
|
|
1108
1195
|
value: edgeColor,
|
|
1109
1196
|
onChange: (e) => setEdgeColor(e.target.value),
|
|
1110
1197
|
disabled: !showEdges,
|
|
1111
|
-
className: "h-6 w-10 rounded border border-
|
|
1198
|
+
className: "h-6 w-10 rounded border border-gray-300 bg-white disabled:opacity-40"
|
|
1112
1199
|
}
|
|
1113
1200
|
)
|
|
1114
1201
|
] }),
|
|
1115
1202
|
/* @__PURE__ */ jsxs("div", { className: showEdges ? "" : "opacity-40 pointer-events-none", children: [
|
|
1116
1203
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 mb-1", children: [
|
|
1117
1204
|
/* @__PURE__ */ jsx("span", { children: "Edge Threshold" }),
|
|
1118
|
-
/* @__PURE__ */ jsxs("span", { className: "text-
|
|
1205
|
+
/* @__PURE__ */ jsxs("span", { className: "text-gray-500 tabular-nums", children: [
|
|
1119
1206
|
edgeThreshold,
|
|
1120
1207
|
"\xB0"
|
|
1121
1208
|
] })
|
|
@@ -1133,14 +1220,14 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
|
|
|
1133
1220
|
}
|
|
1134
1221
|
)
|
|
1135
1222
|
] }),
|
|
1136
|
-
/* @__PURE__ */ jsxs("div", { className: "border-t border-
|
|
1223
|
+
/* @__PURE__ */ jsxs("div", { className: "border-t border-gray-200 -mx-3 px-3 pt-3 mt-1", children: [
|
|
1137
1224
|
/* @__PURE__ */ jsxs("label", { className: "flex items-center justify-between gap-2", children: [
|
|
1138
1225
|
/* @__PURE__ */ jsx("span", { className: "font-medium", children: "Section View" }),
|
|
1139
1226
|
/* @__PURE__ */ jsx(
|
|
1140
1227
|
"button",
|
|
1141
1228
|
{
|
|
1142
1229
|
onClick: () => setSectionEnabled((s) => !s),
|
|
1143
|
-
className: `relative h-5 w-9 rounded-full transition-colors ${sectionEnabled ? "bg-blue-500" : "bg-
|
|
1230
|
+
className: `relative h-5 w-9 rounded-full transition-colors ${sectionEnabled ? "bg-blue-500" : "bg-gray-300"}`,
|
|
1144
1231
|
children: /* @__PURE__ */ jsx("span", { className: `absolute top-0.5 h-4 w-4 rounded-full bg-white transition-transform ${sectionEnabled ? "translate-x-4" : "translate-x-0.5"}` })
|
|
1145
1232
|
}
|
|
1146
1233
|
)
|
|
@@ -1153,7 +1240,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
|
|
|
1153
1240
|
"button",
|
|
1154
1241
|
{
|
|
1155
1242
|
onClick: () => setSectionFlip((f) => !f),
|
|
1156
|
-
className: "text-[10px] text-
|
|
1243
|
+
className: "text-[10px] text-gray-600 hover:text-gray-900 px-1.5 py-0.5 rounded bg-gray-100 hover:bg-gray-200",
|
|
1157
1244
|
title: "Flip section direction",
|
|
1158
1245
|
children: sectionFlip ? "\u2190 flipped" : "flip \u2192"
|
|
1159
1246
|
}
|
|
@@ -1163,7 +1250,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
|
|
|
1163
1250
|
"button",
|
|
1164
1251
|
{
|
|
1165
1252
|
onClick: () => setSectionAxis(ax),
|
|
1166
|
-
className: `py-1 rounded text-[11px] font-semibold ${sectionAxis === ax ? "bg-blue-500 text-white" : "bg-
|
|
1253
|
+
className: `py-1 rounded text-[11px] font-semibold ${sectionAxis === ax ? "bg-blue-500 text-white" : "bg-gray-100 text-gray-700 hover:bg-gray-200"}`,
|
|
1167
1254
|
children: ax.toUpperCase()
|
|
1168
1255
|
},
|
|
1169
1256
|
ax
|
|
@@ -1172,7 +1259,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
|
|
|
1172
1259
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
1173
1260
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 mb-1", children: [
|
|
1174
1261
|
/* @__PURE__ */ jsx("span", { children: "Position" }),
|
|
1175
|
-
/* @__PURE__ */ jsxs("span", { className: "text-
|
|
1262
|
+
/* @__PURE__ */ jsxs("span", { className: "text-gray-500 tabular-nums", children: [
|
|
1176
1263
|
Math.round(sectionPosition * 100),
|
|
1177
1264
|
"%"
|
|
1178
1265
|
] })
|
|
@@ -1198,18 +1285,18 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
|
|
|
1198
1285
|
type: "color",
|
|
1199
1286
|
value: sectionCapColor,
|
|
1200
1287
|
onChange: (e) => setSectionCapColor(e.target.value),
|
|
1201
|
-
className: "h-6 w-10 rounded border border-
|
|
1288
|
+
className: "h-6 w-10 rounded border border-gray-300 bg-white"
|
|
1202
1289
|
}
|
|
1203
1290
|
)
|
|
1204
1291
|
] })
|
|
1205
1292
|
] })
|
|
1206
1293
|
] })
|
|
1207
1294
|
] }),
|
|
1208
|
-
/* @__PURE__ */ jsx("div", { className: "px-3 py-2 border-t border-
|
|
1295
|
+
/* @__PURE__ */ jsx("div", { className: "px-3 py-2 border-t border-gray-200", children: /* @__PURE__ */ jsx(
|
|
1209
1296
|
"button",
|
|
1210
1297
|
{
|
|
1211
1298
|
onClick: handleResetDisplay,
|
|
1212
|
-
className: "w-full text-[11px] text-
|
|
1299
|
+
className: "w-full text-[11px] text-gray-700 bg-gray-100 hover:bg-gray-200 rounded py-1.5 transition-colors",
|
|
1213
1300
|
children: "Reset to Default"
|
|
1214
1301
|
}
|
|
1215
1302
|
) })
|
|
@@ -1267,5 +1354,5 @@ function ImagePanel({ url, filename, onDownload, onEmail }) {
|
|
|
1267
1354
|
}
|
|
1268
1355
|
|
|
1269
1356
|
export { Preview, setPdfPreview };
|
|
1270
|
-
//# sourceMappingURL=chunk-
|
|
1271
|
-
//# sourceMappingURL=chunk-
|
|
1357
|
+
//# sourceMappingURL=chunk-IQWRDQHW.js.map
|
|
1358
|
+
//# sourceMappingURL=chunk-IQWRDQHW.js.map
|