react-os-shell 0.1.32 → 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-X2TQ32VM.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-CZKAKVP6.js → chunk-MONP6MMC.js} +129 -181
  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-X2TQ32VM.js +0 -6
  33. 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-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;
@@ -729,114 +774,47 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
729
774
  useEffect(() => {
730
775
  const v = viewerRef.current;
731
776
  if (!v?.viewer || loading) return;
732
- let cancelled = false;
733
- let teardown = null;
734
- (async () => {
735
- const THREE = await import('three');
736
- if (cancelled) return;
737
- const renderer = v.viewer.renderer;
738
- const scene = v.viewer.scene;
739
- if (!renderer || !scene) return;
740
- if (sectionRef.current) {
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;
758
- }
759
- if (!sectionEnabled) {
760
- renderer.localClippingEnabled = false;
761
- v.viewer.Render?.();
762
- return;
763
- }
764
- const bbox = v.viewer.GetBoundingBox?.(() => true);
765
- if (!bbox) return;
766
- const plane = new THREE.Plane(new THREE.Vector3(0, 0, -1), 0);
767
- const helpers = [];
768
- const materialState = /* @__PURE__ */ new Map();
769
- const applyToMaterial = (mat) => {
770
- if (!mat || materialState.has(mat)) return;
771
- materialState.set(mat, {
772
- clippingPlanes: mat.clippingPlanes,
773
- clipShadows: mat.clipShadows
774
- });
775
- mat.clippingPlanes = [plane];
776
- 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;
777
784
  mat.needsUpdate = true;
778
- };
779
- const targets = [];
780
- v.viewer.mainModel?.EnumerateMeshes?.((mesh) => {
781
- if (mesh.userData?.__sectionHelper) return;
782
- targets.push(mesh);
783
- });
784
- for (const mesh of targets) {
785
- const mat = mesh.material;
786
- if (Array.isArray(mat)) for (const m of mat) applyToMaterial(m);
787
- else applyToMaterial(mat);
788
- const makeStencil = (side, op) => {
789
- const m = new THREE.MeshBasicMaterial({
790
- depthWrite: false,
791
- depthTest: false,
792
- colorWrite: false,
793
- stencilWrite: true,
794
- stencilFunc: THREE.AlwaysStencilFunc,
795
- stencilFail: op,
796
- stencilZFail: op,
797
- stencilZPass: op,
798
- side,
799
- clippingPlanes: [plane]
800
- });
801
- const helper = new THREE.Mesh(mesh.geometry, m);
802
- helper.matrixAutoUpdate = false;
803
- helper.renderOrder = 1;
804
- helper.userData.__sectionHelper = true;
805
- mesh.add(helper);
806
- helpers.push(helper);
807
- };
808
- makeStencil(THREE.BackSide, THREE.IncrementWrapStencilOp);
809
- makeStencil(THREE.FrontSide, THREE.DecrementWrapStencilOp);
810
785
  }
811
- const dx = bbox.max.x - bbox.min.x;
812
- const dy = bbox.max.y - bbox.min.y;
813
- const dz = bbox.max.z - bbox.min.z;
814
- const capSize = Math.max(dx, dy, dz) * 2 || 1;
815
- const capGeom = new THREE.PlaneGeometry(capSize, capSize);
816
- const capMat = new THREE.MeshPhongMaterial({
817
- color: 10135219,
818
- side: THREE.DoubleSide,
819
- stencilWrite: true,
820
- stencilRef: 0,
821
- stencilFunc: THREE.NotEqualStencilFunc,
822
- stencilFail: THREE.ReplaceStencilOp,
823
- stencilZFail: THREE.ReplaceStencilOp,
824
- stencilZPass: THREE.ReplaceStencilOp
825
- });
826
- const capMesh = new THREE.Mesh(capGeom, capMat);
827
- capMesh.renderOrder = 2;
828
- capMesh.userData.__sectionHelper = true;
829
- scene.add(capMesh);
830
- renderer.localClippingEnabled = true;
831
- sectionRef.current = { plane, capMesh, helpers, materialState, bbox };
786
+ sectionRef.current = null;
787
+ }
788
+ if (!sectionEnabled) {
789
+ renderer.localClippingEnabled = false;
832
790
  v.viewer.Render?.();
833
- teardown = () => {
834
- };
835
- })();
836
- return () => {
837
- cancelled = true;
838
- 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;
839
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?.();
840
818
  }, [sectionEnabled, loading, tree]);
841
819
  useEffect(() => {
842
820
  const v = viewerRef.current;
@@ -849,32 +827,15 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
849
827
  const max = [bbox.max.x, bbox.max.y, bbox.max.z][axisIdx];
850
828
  const value = min + (max - min) * sectionPosition;
851
829
  const dir = sectionFlip ? 1 : -1;
852
- const nx = sectionAxis === "x" ? dir : 0;
853
- const ny = sectionAxis === "y" ? dir : 0;
854
- const nz = sectionAxis === "z" ? dir : 0;
855
- 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;
856
833
  s.plane.constant = -dir * value;
857
- const cx = (bbox.min.x + bbox.max.x) / 2;
858
- const cy = (bbox.min.y + bbox.max.y) / 2;
859
- const cz = (bbox.min.z + bbox.max.z) / 2;
860
- const center = { x: cx, y: cy, z: cz };
861
- const dist = nx * center.x + ny * center.y + nz * center.z + s.plane.constant;
862
- const px = center.x - nx * dist;
863
- const py = center.y - ny * dist;
864
- const pz = center.z - nz * dist;
865
- s.capMesh.position.set(px, py, pz);
866
- s.capMesh.lookAt(px + nx, py + ny, pz + nz);
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 {
872
- }
873
834
  v.viewer.Render?.();
874
835
  } catch (err) {
875
836
  console.warn("[Preview] section update failed", err);
876
837
  }
877
- }, [sectionEnabled, sectionAxis, sectionFlip, sectionPosition, sectionCapColor]);
838
+ }, [sectionEnabled, sectionAxis, sectionFlip, sectionPosition]);
878
839
  useEffect(() => {
879
840
  if (!showHint || loading) return;
880
841
  const t = setTimeout(() => setShowHint(false), 5e3);
@@ -902,7 +863,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
902
863
  const handleFit = () => {
903
864
  try {
904
865
  const v = viewerRef.current;
905
- const sphere = v?.GetBoundingSphere?.(() => true);
866
+ const sphere = v?.viewer?.GetBoundingSphere?.(() => true);
906
867
  if (sphere) v.viewer.FitSphereToWindow(sphere, true);
907
868
  v?.viewer?.Render?.();
908
869
  } catch {
@@ -913,7 +874,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
913
874
  const v = viewerRef.current;
914
875
  if (!OV || !v?.viewer) return;
915
876
  try {
916
- const sphere = v.GetBoundingSphere?.(() => true);
877
+ const sphere = v.viewer.GetBoundingSphere?.(() => true);
917
878
  if (!sphere) return;
918
879
  const c = sphere.center;
919
880
  const r = sphere.radius || 1;
@@ -971,7 +932,6 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
971
932
  setSectionAxis("z");
972
933
  setSectionFlip(false);
973
934
  setSectionPosition(0.5);
974
- setSectionCapColor("#9aa6b3");
975
935
  };
976
936
  const handleDefaultDownload = () => {
977
937
  const a = document.createElement("a");
@@ -988,24 +948,24 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
988
948
  /* @__PURE__ */ jsxs(
989
949
  "div",
990
950
  {
991
- 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",
992
952
  style: { paddingLeft: `${depth * 12 + 6}px` },
993
953
  children: [
994
954
  hasChildren ? /* @__PURE__ */ jsx(
995
955
  "button",
996
956
  {
997
957
  onClick: () => toggleExpanded(node.id),
998
- 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",
999
959
  title: isExpanded ? "Collapse" : "Expand",
1000
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" }) })
1001
961
  }
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-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" }) }),
1003
963
  /* @__PURE__ */ jsx("span", { className: `flex-1 truncate ${isVisible ? "" : "opacity-40"}`, title: node.name, children: node.name }),
1004
964
  /* @__PURE__ */ jsx(
1005
965
  "button",
1006
966
  {
1007
967
  onClick: () => fitNode(),
1008
- 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",
1009
969
  title: "Fit to view",
1010
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" }) })
1011
971
  }
@@ -1014,7 +974,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1014
974
  "button",
1015
975
  {
1016
976
  onClick: () => toggleNodeVisible(node),
1017
- 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",
1018
978
  title: isVisible ? "Hide" : "Show",
1019
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: [
1020
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" }),
@@ -1028,12 +988,12 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1028
988
  isExpanded && hasChildren && /* @__PURE__ */ jsx("div", { children: node.children.map((c) => renderTreeNode(c, depth + 1)) })
1029
989
  ] }, node.id);
1030
990
  };
1031
- 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";
1032
- const tBtnActive = "h-8 w-8 shrink-0 flex items-center justify-center rounded bg-slate-700 text-white";
1033
- const tBtnSep = "h-5 w-px bg-slate-700 mx-1";
1034
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full bg-slate-900", children: [
1035
- /* @__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: [
1036
- /* @__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 }),
1037
997
  /* @__PURE__ */ jsx("div", { className: tBtnSep }),
1038
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" }) }) }),
1039
999
  /* @__PURE__ */ jsx("div", { className: tBtnSep }),
@@ -1057,10 +1017,10 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1057
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" }) }) })
1058
1018
  ] }),
1059
1019
  /* @__PURE__ */ jsxs("div", { className: "flex-1 flex min-h-0", children: [
1060
- showMeshes && /* @__PURE__ */ jsxs("div", { className: "w-60 shrink-0 bg-slate-800 border-r border-slate-700 flex flex-col", children: [
1061
- /* @__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" }),
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-slate-500 italic", children: loading ? "Reading model\u2026" : "No structure available" }) }),
1063
- 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` })
1064
1024
  ] }),
1065
1025
  /* @__PURE__ */ jsxs("div", { className: "relative flex-1 min-w-0", style: { background: bgColor }, children: [
1066
1026
  /* @__PURE__ */ jsx("div", { ref: containerRef, style: { width: "100%", height: "100%" } }),
@@ -1081,12 +1041,12 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1081
1041
  ] }),
1082
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 })
1083
1043
  ] }),
1084
- showSettings && /* @__PURE__ */ jsxs("div", { className: "w-60 shrink-0 bg-slate-800 border-l border-slate-700 flex flex-col", children: [
1085
- /* @__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" }),
1086
- /* @__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: [
1087
1047
  /* @__PURE__ */ jsxs("label", { className: "flex items-center justify-between gap-2", children: [
1088
1048
  /* @__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-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" })
1090
1050
  ] }),
1091
1051
  /* @__PURE__ */ jsxs("label", { className: "flex items-center justify-between gap-2", children: [
1092
1052
  /* @__PURE__ */ jsx("span", { children: "Show Edges" }),
@@ -1094,7 +1054,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1094
1054
  "button",
1095
1055
  {
1096
1056
  onClick: () => setShowEdges((s) => !s),
1097
- 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"}`,
1098
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"}` })
1099
1059
  }
1100
1060
  )
@@ -1108,14 +1068,14 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1108
1068
  value: edgeColor,
1109
1069
  onChange: (e) => setEdgeColor(e.target.value),
1110
1070
  disabled: !showEdges,
1111
- 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"
1112
1072
  }
1113
1073
  )
1114
1074
  ] }),
1115
1075
  /* @__PURE__ */ jsxs("div", { className: showEdges ? "" : "opacity-40 pointer-events-none", children: [
1116
1076
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 mb-1", children: [
1117
1077
  /* @__PURE__ */ jsx("span", { children: "Edge Threshold" }),
1118
- /* @__PURE__ */ jsxs("span", { className: "text-slate-400 tabular-nums", children: [
1078
+ /* @__PURE__ */ jsxs("span", { className: "text-gray-500 tabular-nums", children: [
1119
1079
  edgeThreshold,
1120
1080
  "\xB0"
1121
1081
  ] })
@@ -1133,14 +1093,14 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1133
1093
  }
1134
1094
  )
1135
1095
  ] }),
1136
- /* @__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: [
1137
1097
  /* @__PURE__ */ jsxs("label", { className: "flex items-center justify-between gap-2", children: [
1138
1098
  /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Section View" }),
1139
1099
  /* @__PURE__ */ jsx(
1140
1100
  "button",
1141
1101
  {
1142
1102
  onClick: () => setSectionEnabled((s) => !s),
1143
- 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"}`,
1144
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"}` })
1145
1105
  }
1146
1106
  )
@@ -1153,7 +1113,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1153
1113
  "button",
1154
1114
  {
1155
1115
  onClick: () => setSectionFlip((f) => !f),
1156
- 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",
1157
1117
  title: "Flip section direction",
1158
1118
  children: sectionFlip ? "\u2190 flipped" : "flip \u2192"
1159
1119
  }
@@ -1163,7 +1123,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1163
1123
  "button",
1164
1124
  {
1165
1125
  onClick: () => setSectionAxis(ax),
1166
- 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"}`,
1167
1127
  children: ax.toUpperCase()
1168
1128
  },
1169
1129
  ax
@@ -1172,7 +1132,7 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1172
1132
  /* @__PURE__ */ jsxs("div", { children: [
1173
1133
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 mb-1", children: [
1174
1134
  /* @__PURE__ */ jsx("span", { children: "Position" }),
1175
- /* @__PURE__ */ jsxs("span", { className: "text-slate-400 tabular-nums", children: [
1135
+ /* @__PURE__ */ jsxs("span", { className: "text-gray-500 tabular-nums", children: [
1176
1136
  Math.round(sectionPosition * 100),
1177
1137
  "%"
1178
1138
  ] })
@@ -1189,27 +1149,15 @@ function StepPanel({ url, filename, onDownload, onEmail }) {
1189
1149
  className: "w-full accent-blue-500"
1190
1150
  }
1191
1151
  )
1192
- ] }),
1193
- /* @__PURE__ */ jsxs("label", { className: "flex items-center justify-between gap-2", children: [
1194
- /* @__PURE__ */ jsx("span", { children: "Cap Color" }),
1195
- /* @__PURE__ */ jsx(
1196
- "input",
1197
- {
1198
- type: "color",
1199
- value: sectionCapColor,
1200
- onChange: (e) => setSectionCapColor(e.target.value),
1201
- className: "h-6 w-10 rounded border border-slate-600 bg-transparent"
1202
- }
1203
- )
1204
1152
  ] })
1205
1153
  ] })
1206
1154
  ] })
1207
1155
  ] }),
1208
- /* @__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(
1209
1157
  "button",
1210
1158
  {
1211
1159
  onClick: handleResetDisplay,
1212
- 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",
1213
1161
  children: "Reset to Default"
1214
1162
  }
1215
1163
  ) })
@@ -1267,5 +1215,5 @@ function ImagePanel({ url, filename, onDownload, onEmail }) {
1267
1215
  }
1268
1216
 
1269
1217
  export { Preview, setPdfPreview };
1270
- //# sourceMappingURL=chunk-CZKAKVP6.js.map
1271
- //# sourceMappingURL=chunk-CZKAKVP6.js.map
1218
+ //# sourceMappingURL=chunk-MONP6MMC.js.map
1219
+ //# sourceMappingURL=chunk-MONP6MMC.js.map