react-os-shell 0.1.31 → 0.1.35

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.
Files changed (33) hide show
  1. package/dist/{Calculator-ZZMTB7Y7.js → Calculator-VZM3FSTQ.js} +4 -4
  2. package/dist/{Calculator-ZZMTB7Y7.js.map → Calculator-VZM3FSTQ.js.map} +1 -1
  3. package/dist/{Calendar-RQVSPJAJ.js → Calendar-7DNNMOKO.js} +3 -3
  4. package/dist/{Calendar-RQVSPJAJ.js.map → Calendar-7DNNMOKO.js.map} +1 -1
  5. package/dist/{CurrencyConverter-S37JTKKZ.js → CurrencyConverter-XFIGUZ46.js} +4 -4
  6. package/dist/{CurrencyConverter-S37JTKKZ.js.map → CurrencyConverter-XFIGUZ46.js.map} +1 -1
  7. package/dist/{Documents-3P6JKOLE.js → Documents-PK7QFWGR.js} +3 -3
  8. package/dist/{Documents-3P6JKOLE.js.map → Documents-PK7QFWGR.js.map} +1 -1
  9. package/dist/{Email-UCNJ53MV.js → Email-66BDCI2Q.js} +3 -3
  10. package/dist/{Email-UCNJ53MV.js.map → Email-66BDCI2Q.js.map} +1 -1
  11. package/dist/{Minesweeper-KAOD327F.js → Minesweeper-7OGCUAKF.js} +3 -3
  12. package/dist/{Minesweeper-KAOD327F.js.map → Minesweeper-7OGCUAKF.js.map} +1 -1
  13. package/dist/{Notepad-C453L2M2.js → Notepad-MNDA6AHQ.js} +3 -3
  14. package/dist/{Notepad-C453L2M2.js.map → Notepad-MNDA6AHQ.js.map} +1 -1
  15. package/dist/{PomodoroTimer-ZZUXEFM6.js → PomodoroTimer-6DHC3H6X.js} +4 -4
  16. package/dist/{PomodoroTimer-ZZUXEFM6.js.map → PomodoroTimer-6DHC3H6X.js.map} +1 -1
  17. package/dist/Preview-NK4LOF3L.js +6 -0
  18. package/dist/{Preview-DO7KHVKG.js.map → Preview-NK4LOF3L.js.map} +1 -1
  19. package/dist/{Spreadsheet-SOJL4SQA.js → Spreadsheet-JT4TIKCY.js} +3 -3
  20. package/dist/{Spreadsheet-SOJL4SQA.js.map → Spreadsheet-JT4TIKCY.js.map} +1 -1
  21. package/dist/{Weather-H7R7YVRB.js → Weather-A6MEC4PN.js} +4 -4
  22. package/dist/{Weather-H7R7YVRB.js.map → Weather-A6MEC4PN.js.map} +1 -1
  23. package/dist/apps/index.js +13 -13
  24. package/dist/{chunk-AKZTZLKP.js → chunk-44AH2OXU.js} +3 -3
  25. package/dist/{chunk-AKZTZLKP.js.map → chunk-44AH2OXU.js.map} +1 -1
  26. package/dist/{chunk-RGYSM6P5.js → chunk-MONP6MMC.js} +131 -176
  27. package/dist/chunk-MONP6MMC.js.map +1 -0
  28. package/dist/{chunk-D7UDGZIH.js → chunk-UUJLLTV4.js} +3 -3
  29. package/dist/{chunk-D7UDGZIH.js.map → chunk-UUJLLTV4.js.map} +1 -1
  30. package/dist/index.js +4 -4
  31. package/package.json +1 -1
  32. package/dist/Preview-DO7KHVKG.js +0 -6
  33. package/dist/chunk-RGYSM6P5.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import { toast_default } from './chunk-WIJ45SYD.js';
2
- import { WindowTitle } from './chunk-AKZTZLKP.js';
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
- setPdfPreview({ url, filename: file.name, kind });
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
- setIsDragging(false);
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
- onDragOver: (e) => {
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
- onDragLeave: (e) => {
155
- if (e.currentTarget === e.target) setIsDragging(false);
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,6 @@ 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("#9aa6b3");
608
653
  const sectionRef = useRef(null);
609
654
  useEffect(() => {
610
655
  let cancelled = false;
@@ -691,6 +736,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
691
736
  if (!v?.viewer) return;
692
737
  try {
693
738
  const visit = (mesh) => {
739
+ if (mesh.userData?.__sectionHelper) return;
694
740
  const ud = mesh.userData?.originalMeshInstance ?? mesh.userData;
695
741
  const nodeId = ud?.id?.nodeId ?? ud?.nodeId;
696
742
  if (typeof nodeId === "number") {
@@ -728,108 +774,47 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
728
774
  useEffect(() => {
729
775
  const v = viewerRef.current;
730
776
  if (!v?.viewer || loading) return;
731
- let cancelled = false;
732
- let teardown = null;
733
- (async () => {
734
- const THREE = await import('three');
735
- if (cancelled) return;
736
- const renderer = v.viewer.renderer;
737
- const scene = v.viewer.scene;
738
- if (!renderer || !scene) return;
739
- if (sectionRef.current) {
740
- const s = sectionRef.current;
741
- for (const [mat, prev] of s.materialState.entries()) {
742
- mat.clippingPlanes = prev.clippingPlanes;
743
- mat.clipShadows = prev.clipShadows;
744
- mat.needsUpdate = true;
745
- }
746
- for (const helper of s.helpers) {
747
- helper.parent?.remove(helper);
748
- helper.geometry?.dispose?.();
749
- helper.material?.dispose?.();
750
- }
751
- if (s.capMesh) {
752
- scene.remove(s.capMesh);
753
- s.capMesh.geometry?.dispose?.();
754
- s.capMesh.material?.dispose?.();
755
- }
756
- sectionRef.current = null;
757
- }
758
- if (!sectionEnabled) {
759
- renderer.localClippingEnabled = false;
760
- v.viewer.Render?.();
761
- return;
762
- }
763
- const bbox = v.viewer.GetBoundingBox?.(() => true);
764
- if (!bbox) return;
765
- const plane = new THREE.Plane(new THREE.Vector3(0, 0, -1), 0);
766
- const helpers = [];
767
- const materialState = /* @__PURE__ */ new Map();
768
- const applyToMaterial = (mat) => {
769
- if (!mat || materialState.has(mat)) return;
770
- materialState.set(mat, {
771
- clippingPlanes: mat.clippingPlanes,
772
- clipShadows: mat.clipShadows
773
- });
774
- mat.clippingPlanes = [plane];
775
- mat.clipShadows = true;
777
+ const renderer = v.viewer.renderer;
778
+ if (!renderer) return;
779
+ if (sectionRef.current) {
780
+ const s = sectionRef.current;
781
+ for (const [mat, prev] of s.materialState.entries()) {
782
+ mat.clippingPlanes = prev.clippingPlanes;
783
+ mat.clipShadows = prev.clipShadows;
776
784
  mat.needsUpdate = true;
777
- };
778
- v.viewer.mainModel?.EnumerateMeshes?.((mesh) => {
779
- const mat = mesh.material;
780
- if (Array.isArray(mat)) for (const m of mat) applyToMaterial(m);
781
- else applyToMaterial(mat);
782
- const makeStencil = (side, op) => {
783
- const m = new THREE.MeshBasicMaterial({
784
- depthWrite: false,
785
- depthTest: false,
786
- colorWrite: false,
787
- stencilWrite: true,
788
- stencilFunc: THREE.AlwaysStencilFunc,
789
- stencilFail: op,
790
- stencilZFail: op,
791
- stencilZPass: op,
792
- side,
793
- clippingPlanes: [plane]
794
- });
795
- const helper = new THREE.Mesh(mesh.geometry, m);
796
- helper.matrixAutoUpdate = false;
797
- helper.renderOrder = 1;
798
- helper.userData.__sectionHelper = true;
799
- mesh.add(helper);
800
- helpers.push(helper);
801
- };
802
- makeStencil(THREE.BackSide, THREE.IncrementWrapStencilOp);
803
- makeStencil(THREE.FrontSide, THREE.DecrementWrapStencilOp);
804
- });
805
- const dx = bbox.max.x - bbox.min.x;
806
- const dy = bbox.max.y - bbox.min.y;
807
- const dz = bbox.max.z - bbox.min.z;
808
- const capSize = Math.max(dx, dy, dz) * 2 || 1;
809
- const capGeom = new THREE.PlaneGeometry(capSize, capSize);
810
- const capMat = new THREE.MeshPhongMaterial({
811
- color: 10135219,
812
- side: THREE.DoubleSide,
813
- stencilWrite: true,
814
- stencilRef: 0,
815
- stencilFunc: THREE.NotEqualStencilFunc,
816
- stencilFail: THREE.ReplaceStencilOp,
817
- stencilZFail: THREE.ReplaceStencilOp,
818
- stencilZPass: THREE.ReplaceStencilOp
819
- });
820
- const capMesh = new THREE.Mesh(capGeom, capMat);
821
- capMesh.renderOrder = 2;
822
- scene.add(capMesh);
823
- renderer.localClippingEnabled = true;
824
- sectionRef.current = { plane, capMesh, helpers, materialState, bbox };
785
+ }
786
+ sectionRef.current = null;
787
+ }
788
+ if (!sectionEnabled) {
789
+ renderer.localClippingEnabled = false;
825
790
  v.viewer.Render?.();
826
- teardown = () => {
827
- };
828
- })();
829
- return () => {
830
- cancelled = true;
831
- if (teardown) teardown();
791
+ return;
792
+ }
793
+ const bbox = v.viewer.GetBoundingBox?.(() => true);
794
+ if (!bbox) return;
795
+ const plane = { normal: { x: 0, y: 0, z: -1 }, constant: 0 };
796
+ const materialState = /* @__PURE__ */ new Map();
797
+ const applyToMaterial = (mat) => {
798
+ if (!mat || materialState.has(mat)) return;
799
+ materialState.set(mat, { clippingPlanes: mat.clippingPlanes, clipShadows: mat.clipShadows });
800
+ mat.clippingPlanes = [plane];
801
+ mat.clipShadows = true;
802
+ mat.needsUpdate = true;
832
803
  };
804
+ v.viewer.mainModel?.EnumerateMeshes?.((mesh) => {
805
+ if (mesh.userData?.__sectionHelper) return;
806
+ const mat = mesh.material;
807
+ if (Array.isArray(mat)) for (const m of mat) applyToMaterial(m);
808
+ else applyToMaterial(mat);
809
+ });
810
+ v.viewer.mainModel?.EnumerateEdges?.((edge) => {
811
+ const mat = edge.material;
812
+ if (Array.isArray(mat)) for (const m of mat) applyToMaterial(m);
813
+ else applyToMaterial(mat);
814
+ });
815
+ renderer.localClippingEnabled = true;
816
+ sectionRef.current = { plane, capMesh: null, helpers: [], materialState, bbox };
817
+ v.viewer.Render?.();
833
818
  }, [sectionEnabled, loading, tree]);
834
819
  useEffect(() => {
835
820
  const v = viewerRef.current;
@@ -842,32 +827,15 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
842
827
  const max = [bbox.max.x, bbox.max.y, bbox.max.z][axisIdx];
843
828
  const value = min + (max - min) * sectionPosition;
844
829
  const dir = sectionFlip ? 1 : -1;
845
- const nx = sectionAxis === "x" ? dir : 0;
846
- const ny = sectionAxis === "y" ? dir : 0;
847
- const nz = sectionAxis === "z" ? dir : 0;
848
- s.plane.normal.set(nx, ny, nz);
830
+ s.plane.normal.x = sectionAxis === "x" ? dir : 0;
831
+ s.plane.normal.y = sectionAxis === "y" ? dir : 0;
832
+ s.plane.normal.z = sectionAxis === "z" ? dir : 0;
849
833
  s.plane.constant = -dir * value;
850
- const cx = (bbox.min.x + bbox.max.x) / 2;
851
- const cy = (bbox.min.y + bbox.max.y) / 2;
852
- const cz = (bbox.min.z + bbox.max.z) / 2;
853
- const center = { x: cx, y: cy, z: cz };
854
- const dist = nx * center.x + ny * center.y + nz * center.z + s.plane.constant;
855
- const px = center.x - nx * dist;
856
- const py = center.y - ny * dist;
857
- const pz = center.z - nz * dist;
858
- s.capMesh.position.set(px, py, pz);
859
- s.capMesh.lookAt(px + nx, py + ny, pz + nz);
860
- try {
861
- const m = /^#?([0-9a-f]{6})$/i.exec(sectionCapColor);
862
- const n = m ? parseInt(m[1], 16) : 10135219;
863
- s.capMesh.material.color.setHex(n);
864
- } catch {
865
- }
866
834
  v.viewer.Render?.();
867
835
  } catch (err) {
868
836
  console.warn("[Preview] section update failed", err);
869
837
  }
870
- }, [sectionEnabled, sectionAxis, sectionFlip, sectionPosition, sectionCapColor]);
838
+ }, [sectionEnabled, sectionAxis, sectionFlip, sectionPosition]);
871
839
  useEffect(() => {
872
840
  if (!showHint || loading) return;
873
841
  const t = setTimeout(() => setShowHint(false), 5e3);
@@ -895,7 +863,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
895
863
  const handleFit = () => {
896
864
  try {
897
865
  const v = viewerRef.current;
898
- const sphere = v?.GetBoundingSphere?.(() => true);
866
+ const sphere = v?.viewer?.GetBoundingSphere?.(() => true);
899
867
  if (sphere) v.viewer.FitSphereToWindow(sphere, true);
900
868
  v?.viewer?.Render?.();
901
869
  } catch {
@@ -906,7 +874,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
906
874
  const v = viewerRef.current;
907
875
  if (!OV || !v?.viewer) return;
908
876
  try {
909
- const sphere = v.GetBoundingSphere?.(() => true);
877
+ const sphere = v.viewer.GetBoundingSphere?.(() => true);
910
878
  if (!sphere) return;
911
879
  const c = sphere.center;
912
880
  const r = sphere.radius || 1;
@@ -964,7 +932,6 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
964
932
  setSectionAxis("z");
965
933
  setSectionFlip(false);
966
934
  setSectionPosition(0.5);
967
- setSectionCapColor("#9aa6b3");
968
935
  };
969
936
  const handleDefaultDownload = () => {
970
937
  const a = document.createElement("a");
@@ -981,24 +948,24 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
981
948
  /* @__PURE__ */ jsxs(
982
949
  "div",
983
950
  {
984
- className: "group flex items-center gap-1 px-1.5 py-1 hover:bg-slate-700/50 cursor-default text-[12px] text-slate-200",
951
+ className: "group flex items-center gap-1 px-1.5 py-1 hover:bg-gray-100 cursor-default text-[12px] text-gray-700",
985
952
  style: { paddingLeft: `${depth * 12 + 6}px` },
986
953
  children: [
987
954
  hasChildren ? /* @__PURE__ */ jsx(
988
955
  "button",
989
956
  {
990
957
  onClick: () => toggleExpanded(node.id),
991
- className: "h-4 w-4 shrink-0 flex items-center justify-center text-slate-400 hover:text-slate-100",
958
+ className: "h-4 w-4 shrink-0 flex items-center justify-center text-gray-500 hover:text-gray-900",
992
959
  title: isExpanded ? "Collapse" : "Expand",
993
960
  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" }) })
994
961
  }
995
- ) : /* @__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-slate-500" }) }),
962
+ ) : /* @__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" }) }),
996
963
  /* @__PURE__ */ jsx("span", { className: `flex-1 truncate ${isVisible ? "" : "opacity-40"}`, title: node.name, children: node.name }),
997
964
  /* @__PURE__ */ jsx(
998
965
  "button",
999
966
  {
1000
967
  onClick: () => fitNode(),
1001
- className: "h-4 w-4 shrink-0 text-slate-500 hover:text-slate-100 opacity-0 group-hover:opacity-100 transition-opacity",
968
+ className: "h-4 w-4 shrink-0 text-gray-400 hover:text-gray-900 opacity-0 group-hover:opacity-100 transition-opacity",
1002
969
  title: "Fit to view",
1003
970
  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" }) })
1004
971
  }
@@ -1007,7 +974,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1007
974
  "button",
1008
975
  {
1009
976
  onClick: () => toggleNodeVisible(node),
1010
- className: "h-4 w-4 shrink-0 text-slate-400 hover:text-slate-100",
977
+ className: "h-4 w-4 shrink-0 text-gray-500 hover:text-gray-900",
1011
978
  title: isVisible ? "Hide" : "Show",
1012
979
  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: [
1013
980
  /* @__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" }),
@@ -1021,12 +988,12 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1021
988
  isExpanded && hasChildren && /* @__PURE__ */ jsx("div", { children: node.children.map((c) => renderTreeNode(c, depth + 1)) })
1022
989
  ] }, node.id);
1023
990
  };
1024
- const tBtn = "h-8 w-8 shrink-0 flex items-center justify-center rounded text-slate-300 hover:bg-slate-700 hover:text-white transition-colors";
1025
- const tBtnActive = "h-8 w-8 shrink-0 flex items-center justify-center rounded bg-slate-700 text-white";
1026
- const tBtnSep = "h-5 w-px bg-slate-700 mx-1";
1027
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full bg-slate-900", children: [
1028
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 px-2 py-1.5 bg-slate-800 border-b border-slate-700 shrink-0", children: [
1029
- /* @__PURE__ */ jsx("span", { className: "text-[11px] font-semibold tracking-wide text-slate-300 px-2 truncate max-w-xs", title: filename, children: filename }),
991
+ 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";
992
+ const tBtnActive = "h-8 w-8 shrink-0 flex items-center justify-center rounded bg-gray-200 text-gray-900";
993
+ const tBtnSep = "h-5 w-px bg-gray-300 mx-1";
994
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full bg-white", children: [
995
+ /* @__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: [
996
+ /* @__PURE__ */ jsx("span", { className: "text-[11px] font-semibold tracking-wide text-gray-700 px-2 truncate max-w-xs", title: filename, children: filename }),
1030
997
  /* @__PURE__ */ jsx("div", { className: tBtnSep }),
1031
998
  /* @__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" }) }) }),
1032
999
  /* @__PURE__ */ jsx("div", { className: tBtnSep }),
@@ -1050,10 +1017,10 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1050
1017
  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" }) }) })
1051
1018
  ] }),
1052
1019
  /* @__PURE__ */ jsxs("div", { className: "flex-1 flex min-h-0", children: [
1053
- showMeshes && /* @__PURE__ */ jsxs("div", { className: "w-60 shrink-0 bg-slate-800 border-r border-slate-700 flex flex-col", children: [
1054
- /* @__PURE__ */ jsx("div", { className: "px-3 py-2 text-[11px] font-semibold uppercase tracking-wide text-slate-400 border-b border-slate-700", children: "Meshes" }),
1055
- /* @__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-slate-500 italic", children: loading ? "Reading model\u2026" : "No structure available" }) }),
1056
- tree && /* @__PURE__ */ jsx("div", { className: "px-3 py-1.5 text-[10px] text-slate-500 border-t border-slate-700", children: hidden.size === 0 ? "All visible" : `${hidden.size} hidden` })
1020
+ showMeshes && /* @__PURE__ */ jsxs("div", { className: "w-60 shrink-0 bg-gray-50 border-r border-gray-200 flex flex-col", children: [
1021
+ /* @__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" }),
1022
+ /* @__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" }) }),
1023
+ 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` })
1057
1024
  ] }),
1058
1025
  /* @__PURE__ */ jsxs("div", { className: "relative flex-1 min-w-0", style: { background: bgColor }, children: [
1059
1026
  /* @__PURE__ */ jsx("div", { ref: containerRef, style: { width: "100%", height: "100%" } }),
@@ -1074,12 +1041,12 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1074
1041
  ] }),
1075
1042
  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 })
1076
1043
  ] }),
1077
- showSettings && /* @__PURE__ */ jsxs("div", { className: "w-60 shrink-0 bg-slate-800 border-l border-slate-700 flex flex-col", children: [
1078
- /* @__PURE__ */ jsx("div", { className: "px-3 py-2 text-[11px] font-semibold uppercase tracking-wide text-slate-400 border-b border-slate-700", children: "Model Display" }),
1079
- /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto px-3 py-3 space-y-3 text-[12px] text-slate-200", children: [
1044
+ showSettings && /* @__PURE__ */ jsxs("div", { className: "w-60 shrink-0 bg-gray-50 border-l border-gray-200 flex flex-col", children: [
1045
+ /* @__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" }),
1046
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto px-3 py-3 space-y-3 text-[12px] text-gray-700", children: [
1080
1047
  /* @__PURE__ */ jsxs("label", { className: "flex items-center justify-between gap-2", children: [
1081
1048
  /* @__PURE__ */ jsx("span", { children: "Background Color" }),
1082
- /* @__PURE__ */ jsx("input", { type: "color", value: bgColor, onChange: (e) => setBgColor(e.target.value), className: "h-6 w-10 rounded border border-slate-600 bg-transparent" })
1049
+ /* @__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" })
1083
1050
  ] }),
1084
1051
  /* @__PURE__ */ jsxs("label", { className: "flex items-center justify-between gap-2", children: [
1085
1052
  /* @__PURE__ */ jsx("span", { children: "Show Edges" }),
@@ -1087,7 +1054,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1087
1054
  "button",
1088
1055
  {
1089
1056
  onClick: () => setShowEdges((s) => !s),
1090
- className: `relative h-5 w-9 rounded-full transition-colors ${showEdges ? "bg-blue-500" : "bg-slate-600"}`,
1057
+ className: `relative h-5 w-9 rounded-full transition-colors ${showEdges ? "bg-blue-500" : "bg-gray-300"}`,
1091
1058
  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"}` })
1092
1059
  }
1093
1060
  )
@@ -1101,14 +1068,14 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1101
1068
  value: edgeColor,
1102
1069
  onChange: (e) => setEdgeColor(e.target.value),
1103
1070
  disabled: !showEdges,
1104
- className: "h-6 w-10 rounded border border-slate-600 bg-transparent disabled:opacity-40"
1071
+ className: "h-6 w-10 rounded border border-gray-300 bg-white disabled:opacity-40"
1105
1072
  }
1106
1073
  )
1107
1074
  ] }),
1108
1075
  /* @__PURE__ */ jsxs("div", { className: showEdges ? "" : "opacity-40 pointer-events-none", children: [
1109
1076
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 mb-1", children: [
1110
1077
  /* @__PURE__ */ jsx("span", { children: "Edge Threshold" }),
1111
- /* @__PURE__ */ jsxs("span", { className: "text-slate-400 tabular-nums", children: [
1078
+ /* @__PURE__ */ jsxs("span", { className: "text-gray-500 tabular-nums", children: [
1112
1079
  edgeThreshold,
1113
1080
  "\xB0"
1114
1081
  ] })
@@ -1126,14 +1093,14 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1126
1093
  }
1127
1094
  )
1128
1095
  ] }),
1129
- /* @__PURE__ */ jsxs("div", { className: "border-t border-slate-700 -mx-3 px-3 pt-3 mt-1", children: [
1096
+ /* @__PURE__ */ jsxs("div", { className: "border-t border-gray-200 -mx-3 px-3 pt-3 mt-1", children: [
1130
1097
  /* @__PURE__ */ jsxs("label", { className: "flex items-center justify-between gap-2", children: [
1131
1098
  /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Section View" }),
1132
1099
  /* @__PURE__ */ jsx(
1133
1100
  "button",
1134
1101
  {
1135
1102
  onClick: () => setSectionEnabled((s) => !s),
1136
- className: `relative h-5 w-9 rounded-full transition-colors ${sectionEnabled ? "bg-blue-500" : "bg-slate-600"}`,
1103
+ className: `relative h-5 w-9 rounded-full transition-colors ${sectionEnabled ? "bg-blue-500" : "bg-gray-300"}`,
1137
1104
  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"}` })
1138
1105
  }
1139
1106
  )
@@ -1146,7 +1113,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1146
1113
  "button",
1147
1114
  {
1148
1115
  onClick: () => setSectionFlip((f) => !f),
1149
- className: "text-[10px] text-slate-300 hover:text-white px-1.5 py-0.5 rounded bg-slate-700 hover:bg-slate-600",
1116
+ className: "text-[10px] text-gray-600 hover:text-gray-900 px-1.5 py-0.5 rounded bg-gray-100 hover:bg-gray-200",
1150
1117
  title: "Flip section direction",
1151
1118
  children: sectionFlip ? "\u2190 flipped" : "flip \u2192"
1152
1119
  }
@@ -1156,7 +1123,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1156
1123
  "button",
1157
1124
  {
1158
1125
  onClick: () => setSectionAxis(ax),
1159
- className: `py-1 rounded text-[11px] font-semibold ${sectionAxis === ax ? "bg-blue-500 text-white" : "bg-slate-700 text-slate-300 hover:bg-slate-600"}`,
1126
+ 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"}`,
1160
1127
  children: ax.toUpperCase()
1161
1128
  },
1162
1129
  ax
@@ -1165,7 +1132,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1165
1132
  /* @__PURE__ */ jsxs("div", { children: [
1166
1133
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 mb-1", children: [
1167
1134
  /* @__PURE__ */ jsx("span", { children: "Position" }),
1168
- /* @__PURE__ */ jsxs("span", { className: "text-slate-400 tabular-nums", children: [
1135
+ /* @__PURE__ */ jsxs("span", { className: "text-gray-500 tabular-nums", children: [
1169
1136
  Math.round(sectionPosition * 100),
1170
1137
  "%"
1171
1138
  ] })
@@ -1182,27 +1149,15 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1182
1149
  className: "w-full accent-blue-500"
1183
1150
  }
1184
1151
  )
1185
- ] }),
1186
- /* @__PURE__ */ jsxs("label", { className: "flex items-center justify-between gap-2", children: [
1187
- /* @__PURE__ */ jsx("span", { children: "Cap Color" }),
1188
- /* @__PURE__ */ jsx(
1189
- "input",
1190
- {
1191
- type: "color",
1192
- value: sectionCapColor,
1193
- onChange: (e) => setSectionCapColor(e.target.value),
1194
- className: "h-6 w-10 rounded border border-slate-600 bg-transparent"
1195
- }
1196
- )
1197
1152
  ] })
1198
1153
  ] })
1199
1154
  ] })
1200
1155
  ] }),
1201
- /* @__PURE__ */ jsx("div", { className: "px-3 py-2 border-t border-slate-700", children: /* @__PURE__ */ jsx(
1156
+ /* @__PURE__ */ jsx("div", { className: "px-3 py-2 border-t border-gray-200", children: /* @__PURE__ */ jsx(
1202
1157
  "button",
1203
1158
  {
1204
1159
  onClick: handleResetDisplay,
1205
- className: "w-full text-[11px] text-slate-300 bg-slate-700 hover:bg-slate-600 rounded py-1.5 transition-colors",
1160
+ className: "w-full text-[11px] text-gray-700 bg-gray-100 hover:bg-gray-200 rounded py-1.5 transition-colors",
1206
1161
  children: "Reset to Default"
1207
1162
  }
1208
1163
  ) })
@@ -1260,5 +1215,5 @@ function ImagePanel({ url, filename, onDownload, onEmail }) {
1260
1215
  }
1261
1216
 
1262
1217
  export { Preview, setPdfPreview };
1263
- //# sourceMappingURL=chunk-RGYSM6P5.js.map
1264
- //# sourceMappingURL=chunk-RGYSM6P5.js.map
1218
+ //# sourceMappingURL=chunk-MONP6MMC.js.map
1219
+ //# sourceMappingURL=chunk-MONP6MMC.js.map