react-os-shell 0.2.63 → 0.2.64

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 (49) hide show
  1. package/dist/{Browser-F7TJRHMK.js → Browser-OL4SV34L.js} +3 -3
  2. package/dist/{Browser-F7TJRHMK.js.map → Browser-OL4SV34L.js.map} +1 -1
  3. package/dist/{Calculator-FO3NUVCK.js → Calculator-VALSEOQD.js} +4 -4
  4. package/dist/{Calculator-FO3NUVCK.js.map → Calculator-VALSEOQD.js.map} +1 -1
  5. package/dist/{Calendar-ZGKMZ5TU.js → Calendar-I4OLRGNW.js} +3 -3
  6. package/dist/{Calendar-ZGKMZ5TU.js.map → Calendar-I4OLRGNW.js.map} +1 -1
  7. package/dist/{CurrencyConverter-IMHQD6XV.js → CurrencyConverter-3DLJRL24.js} +4 -4
  8. package/dist/{CurrencyConverter-IMHQD6XV.js.map → CurrencyConverter-3DLJRL24.js.map} +1 -1
  9. package/dist/{Documents-PHVXWN4S.js → Documents-JLIRD3ML.js} +3 -3
  10. package/dist/{Documents-PHVXWN4S.js.map → Documents-JLIRD3ML.js.map} +1 -1
  11. package/dist/{Email-VXTFMSS5.js → Email-PN2CNRLE.js} +3 -3
  12. package/dist/{Email-VXTFMSS5.js.map → Email-PN2CNRLE.js.map} +1 -1
  13. package/dist/Files-VQCZUKNU.js +12 -0
  14. package/dist/{Files-YO5YOKD7.js.map → Files-VQCZUKNU.js.map} +1 -1
  15. package/dist/{Minesweeper-PX4DUPOE.js → Minesweeper-IGIPALMP.js} +3 -3
  16. package/dist/{Minesweeper-PX4DUPOE.js.map → Minesweeper-IGIPALMP.js.map} +1 -1
  17. package/dist/{Notepad-LFCZD2Y3.js → Notepad-Q5SSDZNW.js} +3 -3
  18. package/dist/{Notepad-LFCZD2Y3.js.map → Notepad-Q5SSDZNW.js.map} +1 -1
  19. package/dist/{PomodoroTimer-7Y36AEWF.js → PomodoroTimer-PD2HIZMT.js} +4 -4
  20. package/dist/{PomodoroTimer-7Y36AEWF.js.map → PomodoroTimer-PD2HIZMT.js.map} +1 -1
  21. package/dist/Preview-WFIQOE3T.js +8 -0
  22. package/dist/{Preview-UMGXEYCV.js.map → Preview-WFIQOE3T.js.map} +1 -1
  23. package/dist/{Spreadsheet-L2DOK2JK.js → Spreadsheet-Y5LACQRY.js} +4 -4
  24. package/dist/{Spreadsheet-L2DOK2JK.js.map → Spreadsheet-Y5LACQRY.js.map} +1 -1
  25. package/dist/{Weather-FDL7CFDL.js → Weather-GEA3GBQQ.js} +4 -4
  26. package/dist/{Weather-FDL7CFDL.js.map → Weather-GEA3GBQQ.js.map} +1 -1
  27. package/dist/{WorldClock-4PCYEMLF.js → WorldClock-W2ENBGFS.js} +4 -4
  28. package/dist/{WorldClock-4PCYEMLF.js.map → WorldClock-W2ENBGFS.js.map} +1 -1
  29. package/dist/apps/index.js +19 -18
  30. package/dist/apps/index.js.map +1 -1
  31. package/dist/chunk-2RIRISNW.js +46 -0
  32. package/dist/chunk-2RIRISNW.js.map +1 -0
  33. package/dist/{chunk-ONQJGZCL.js → chunk-4CFEJ4CC.js} +3 -3
  34. package/dist/{chunk-ONQJGZCL.js.map → chunk-4CFEJ4CC.js.map} +1 -1
  35. package/dist/{chunk-TRYZ75AV.js → chunk-BUJKR34D.js} +3 -3
  36. package/dist/{chunk-TRYZ75AV.js.map → chunk-BUJKR34D.js.map} +1 -1
  37. package/dist/{chunk-6JAAM5TA.js → chunk-JDRZX27J.js} +11 -19
  38. package/dist/chunk-JDRZX27J.js.map +1 -0
  39. package/dist/{chunk-FJ6NSPYF.js → chunk-MY5PL6MK.js} +3 -3
  40. package/dist/{chunk-FJ6NSPYF.js.map → chunk-MY5PL6MK.js.map} +1 -1
  41. package/dist/{chunk-E7ZO44KU.js → chunk-VDNTGVGH.js} +3 -3
  42. package/dist/{chunk-E7ZO44KU.js.map → chunk-VDNTGVGH.js.map} +1 -1
  43. package/dist/index.d.ts +4 -0
  44. package/dist/index.js +126 -52
  45. package/dist/index.js.map +1 -1
  46. package/package.json +1 -1
  47. package/dist/Files-YO5YOKD7.js +0 -9
  48. package/dist/Preview-UMGXEYCV.js +0 -8
  49. package/dist/chunk-6JAAM5TA.js.map +0 -1
package/dist/index.js CHANGED
@@ -5,18 +5,20 @@ import { subscribePomo, getPomoSnapshot } from './chunk-MK3HLUO4.js';
5
5
  import { useGoogleAuth } from './chunk-MVWEL34Y.js';
6
6
  import { useShellPrefs } from './chunk-36VM54SC.js';
7
7
  export { ShellPrefsProvider, useLocalStoragePrefs, useShellPrefs } from './chunk-36VM54SC.js';
8
+ import { PREVIEW_OPENED_EVENT, openPreviewFile } from './chunk-2RIRISNW.js';
8
9
  import { playNotification, playStartup, soundsEnabled, getSoundConfig, SOUND_PACK_KEYS, SOUND_PACKS, SOUND_TYPES, SOUND_TYPE_LABELS, playLogout, setSoundForType, previewSound, setAllSounds } from './chunk-D7PYW2QS.js';
9
- import { setPdfPreview } from './chunk-TRYZ75AV.js';
10
+ import { setPdfPreview } from './chunk-BUJKR34D.js';
10
11
  import './chunk-KUIPWCTJ.js';
11
12
  import { toast_default } from './chunk-WIJ45SYD.js';
12
13
  export { toast_default as toast } from './chunk-WIJ45SYD.js';
13
- import { useAuth } from './chunk-ADJ3CERD.js';
14
- export { ShellAuthProvider, setShellAuthBridge, useShellAuth } from './chunk-ADJ3CERD.js';
14
+ import './chunk-MY5PL6MK.js';
15
15
  export { EditableGrid } from './chunk-GP4Y3VCB.js';
16
- import { useWindowManager, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, useIsMobile, ModalActions, useModalActive, WINDOW_REGISTRY, isPageEntry, LoadingSpinner, ThumbCard, activateModal } from './chunk-ONQJGZCL.js';
17
- export { CancelButton, CopyButton, DocFavStar, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, WindowManagerProvider, WindowTitle, commitExposeHighlight, exitExposeMode, getActiveWindowRoute, getExposeHighlight, isEntityEntry, isPageEntry, setExposeHighlight, setShellApiClient, setShellWindowRegistry, setWindowDefaultPosition, subscribeExposeHighlight, toggleExposeMode, useModalActive, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-ONQJGZCL.js';
16
+ import { useWindowManager, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, useIsMobile, ModalActions, useModalActive, WINDOW_REGISTRY, isPageEntry, LoadingSpinner, ThumbCard, activateModal } from './chunk-4CFEJ4CC.js';
17
+ export { CancelButton, CopyButton, DocFavStar, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, WindowManagerProvider, WindowTitle, commitExposeHighlight, exitExposeMode, getActiveWindowRoute, getExposeHighlight, isEntityEntry, isPageEntry, setExposeHighlight, setShellApiClient, setShellWindowRegistry, setWindowDefaultPosition, subscribeExposeHighlight, toggleExposeMode, useModalActive, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-4CFEJ4CC.js';
18
18
  import { confirm } from './chunk-PLGHQ7QW.js';
19
19
  export { ConfirmProvider, confirm, confirmDestructive, prompt } from './chunk-PLGHQ7QW.js';
20
+ import { useAuth } from './chunk-ADJ3CERD.js';
21
+ export { ShellAuthProvider, setShellAuthBridge, useShellAuth } from './chunk-ADJ3CERD.js';
20
22
  import { glassStyle, startMenuCategories, navSections, isSection, GLASS_INPUT_BG, navIcons, sectionIcons } from './chunk-SSA762W5.js';
21
23
  export { GLASS_DIVIDER, GLASS_INPUT_BG, glassStyle, setShellNavIcons } from './chunk-SSA762W5.js';
22
24
  import { createContext, lazy, useState, useRef, useEffect, useCallback, useLayoutEffect, useContext, Suspense, isValidElement, cloneElement, useSyncExternalStore, useMemo } from 'react';
@@ -913,7 +915,7 @@ function StatusBadge({ status }) {
913
915
  }
914
916
 
915
917
  // src/version.ts
916
- var VERSION = "0.2.62" ;
918
+ var VERSION = "0.2.64" ;
917
919
  var APP_VERSION = VERSION;
918
920
 
919
921
  // src/changelog.ts
@@ -1010,6 +1012,22 @@ var ENTITY_ICONS = {
1010
1012
  proposal: "PR",
1011
1013
  folder: "FLD"
1012
1014
  };
1015
+ var PREVIEW_FILE_CODES = {
1016
+ pdf: "PDF",
1017
+ dxf: "DXF",
1018
+ "3d": "STP",
1019
+ image: "IMG",
1020
+ csv: "CSV"
1021
+ };
1022
+ var PREVIEW_FILE_COLORS = {
1023
+ pdf: "text-red-600",
1024
+ dxf: "text-blue-600",
1025
+ "3d": "text-purple-600",
1026
+ image: "text-emerald-600",
1027
+ csv: "text-green-600"
1028
+ };
1029
+ var DOCUMENTS_FOLDER_ID = "documents";
1030
+ var DOCUMENTS_FOLDER_NAME = "Documents";
1013
1031
  var GRID = 90;
1014
1032
  function snapToGrid(x, y) {
1015
1033
  return { x: Math.round(x / GRID) * GRID, y: Math.round(y / GRID) * GRID };
@@ -1175,7 +1193,7 @@ function FolderWindow({ folder, items, onClose, onOpen, onMoveOut, onReorder })
1175
1193
  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: "M9 15L3 9m0 0l6-6M3 9h12a6 6 0 010 12h-3" }) })
1176
1194
  }
1177
1195
  ),
1178
- /* @__PURE__ */ jsx("div", { className: `w-12 h-12 rounded-lg bg-white shadow flex items-center justify-center text-xs font-bold ${ENTITY_ICON_COLORS[item.entityType] || "text-gray-600"}`, children: ENTITY_ICONS[item.entityType] || item.entityType.slice(0, 3).toUpperCase() }),
1196
+ /* @__PURE__ */ jsx("div", { className: `w-12 h-12 rounded-lg bg-white shadow flex items-center justify-center text-xs font-bold ${item.entityType === "preview-file" && item.fileKind ? PREVIEW_FILE_COLORS[item.fileKind] : ENTITY_ICON_COLORS[item.entityType] || "text-gray-600"}`, children: item.entityType === "preview-file" && item.fileKind ? PREVIEW_FILE_CODES[item.fileKind] : ENTITY_ICONS[item.entityType] || item.entityType.slice(0, 3).toUpperCase() }),
1179
1197
  /* @__PURE__ */ jsx("span", { className: `text-[10px] font-medium text-center leading-tight truncate w-full ${isSelected ? "text-blue-900" : "text-gray-700"}`, children: item.label })
1180
1198
  ]
1181
1199
  },
@@ -1321,6 +1339,32 @@ function Desktop({ profile }) {
1321
1339
  if (host.saveSnap) host.saveSnap(v);
1322
1340
  else saveShellPrefs({ desktop_snap: v });
1323
1341
  }, [host, saveShellPrefs]);
1342
+ const previewStateRef = useRef({ folders, favDocs, saveFolders, saveDocs });
1343
+ previewStateRef.current = { folders, favDocs, saveFolders, saveDocs };
1344
+ useEffect(() => {
1345
+ const handler = (e) => {
1346
+ const detail = e.detail;
1347
+ if (!detail?.filePath) return;
1348
+ const { folders: fs, favDocs: docs, saveFolders: sf, saveDocs: sd } = previewStateRef.current;
1349
+ if (!fs.some((f) => f.id === DOCUMENTS_FOLDER_ID)) {
1350
+ sf([...fs, { id: DOCUMENTS_FOLDER_ID, name: DOCUMENTS_FOLDER_NAME }]);
1351
+ }
1352
+ const deduped = docs.filter(
1353
+ (d) => !(d.entityType === "preview-file" && d.filePath === detail.filePath)
1354
+ );
1355
+ const next = {
1356
+ entityType: "preview-file",
1357
+ entityId: detail.filePath,
1358
+ label: detail.filename,
1359
+ filePath: detail.filePath,
1360
+ fileKind: detail.kind,
1361
+ folderId: DOCUMENTS_FOLDER_ID
1362
+ };
1363
+ sd([next, ...deduped]);
1364
+ };
1365
+ window.addEventListener(PREVIEW_OPENED_EVENT, handler);
1366
+ return () => window.removeEventListener(PREVIEW_OPENED_EVENT, handler);
1367
+ }, []);
1324
1368
  const getDefaultPos = (idx) => {
1325
1369
  const col = Math.floor(idx / 8);
1326
1370
  const row = idx % 8;
@@ -1504,6 +1548,25 @@ function Desktop({ profile }) {
1504
1548
  };
1505
1549
  useEffect(() => {
1506
1550
  if (!rubberBand) return;
1551
+ const computeSelection = (minX, maxX, minY, maxY) => {
1552
+ const sel = /* @__PURE__ */ new Set();
1553
+ const cw = containerRef.current?.clientWidth || 800;
1554
+ desktopItems.forEach((item, i) => {
1555
+ const pos = getItemPos(item, i);
1556
+ const leftX = cw - pos.right - 80;
1557
+ if (leftX + 40 > minX && leftX < maxX && pos.top + 40 > minY && pos.top < maxY) {
1558
+ sel.add(`item-${i}`);
1559
+ }
1560
+ });
1561
+ folders.forEach((f, i) => {
1562
+ const pos = getFolderPos(f, i);
1563
+ const leftX = cw - pos.right - 80;
1564
+ if (leftX + 40 > minX && leftX < maxX && pos.top + 40 > minY && pos.top < maxY) {
1565
+ sel.add(`folder-${i}`);
1566
+ }
1567
+ });
1568
+ return sel;
1569
+ };
1507
1570
  const move = (e) => {
1508
1571
  const rect = containerRef.current?.getBoundingClientRect();
1509
1572
  if (!rect) return;
@@ -1513,31 +1576,15 @@ function Desktop({ profile }) {
1513
1576
  const dy = y - rubberBand.startY;
1514
1577
  if (dx * dx + dy * dy > 16) didRubberBandDragRef.current = true;
1515
1578
  setRubberBand((prev) => prev ? { ...prev, endX: x, endY: y } : null);
1579
+ if (didRubberBandDragRef.current) {
1580
+ const minX = Math.min(rubberBand.startX, x);
1581
+ const maxX = Math.max(rubberBand.startX, x);
1582
+ const minY = Math.min(rubberBand.startY, y);
1583
+ const maxY = Math.max(rubberBand.startY, y);
1584
+ setSelected(computeSelection(minX, maxX, minY, maxY));
1585
+ }
1516
1586
  };
1517
1587
  const up = () => {
1518
- if (rubberBand) {
1519
- const minX = Math.min(rubberBand.startX, rubberBand.endX);
1520
- const maxX = Math.max(rubberBand.startX, rubberBand.endX);
1521
- const minY = Math.min(rubberBand.startY, rubberBand.endY);
1522
- const maxY = Math.max(rubberBand.startY, rubberBand.endY);
1523
- const sel = /* @__PURE__ */ new Set();
1524
- const cw = containerRef.current?.clientWidth || 800;
1525
- desktopItems.forEach((item, i) => {
1526
- const pos = getItemPos(item, i);
1527
- const leftX = cw - pos.right - 80;
1528
- if (leftX + 40 > minX && leftX < maxX && pos.top + 40 > minY && pos.top < maxY) {
1529
- sel.add(`item-${i}`);
1530
- }
1531
- });
1532
- folders.forEach((f, i) => {
1533
- const pos = getFolderPos(f, i);
1534
- const leftX = cw - pos.right - 80;
1535
- if (leftX + 40 > minX && leftX < maxX && pos.top + 40 > minY && pos.top < maxY) {
1536
- sel.add(`folder-${i}`);
1537
- }
1538
- });
1539
- setSelected(sel);
1540
- }
1541
1588
  setRubberBand(null);
1542
1589
  };
1543
1590
  window.addEventListener("pointermove", move);
@@ -1724,26 +1771,31 @@ function Desktop({ profile }) {
1724
1771
  purple: "bg-purple-100 border-purple-300",
1725
1772
  orange: "bg-orange-100 border-orange-300"
1726
1773
  };
1727
- const renderIcon = (entityType, label, isSelected, entityId) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1 w-20 p-2", children: [
1728
- entityType === "folder" ? /* @__PURE__ */ jsx("div", { className: `w-12 h-12 flex items-center justify-center ${isSelected ? "rounded-lg bg-blue-400/30 ring-2 ring-blue-500" : ""}`, children: /* @__PURE__ */ jsxs("svg", { className: "h-12 w-12 drop-shadow-[0_2px_3px_rgba(0,0,0,0.3)]", viewBox: "0 0 48 48", children: [
1729
- /* @__PURE__ */ jsx("path", { d: "M6 12a4 4 0 014-4h10l4 4h14a4 4 0 014 4v20a4 4 0 01-4 4H10a4 4 0 01-4-4V12z", fill: "white", stroke: "#eab308", strokeWidth: "2", strokeLinejoin: "round" }),
1730
- /* @__PURE__ */ jsx("path", { d: "M6 18h36", stroke: "#eab308", strokeWidth: "1.5" })
1731
- ] }) }) : entityType === "page" ? /* @__PURE__ */ jsx("div", { className: `w-12 h-12 flex items-center justify-center ${isSelected ? "rounded-lg bg-blue-400/30 ring-2 ring-blue-500" : ""}`, children: (() => {
1732
- const icon = navIcons[label] || (entityId ? navIcons[entityId] : void 0);
1733
- if (icon && isValidElement(icon)) {
1734
- return cloneElement(icon, { className: "h-10 w-10 text-white drop-shadow-[0_2px_3px_rgba(0,0,0,0.4)]" });
1735
- }
1736
- return /* @__PURE__ */ jsx("svg", { className: "h-10 w-10 text-white drop-shadow-[0_2px_3px_rgba(0,0,0,0.4)]", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3.75 6A2.25 2.25 0 016 3.75h2.25A2.25 2.25 0 0110.5 6v2.25a2.25 2.25 0 01-2.25 2.25H6a2.25 2.25 0 01-2.25-2.25V6z" }) });
1737
- })() }) : /* @__PURE__ */ jsxs("div", { className: `w-12 h-12 relative flex items-center justify-center ${isSelected ? "rounded-lg bg-blue-400/30 ring-2 ring-blue-500" : ""}`, children: [
1738
- /* @__PURE__ */ jsxs("svg", { className: `w-10 h-12 drop-shadow-[0_2px_3px_rgba(0,0,0,0.3)] ${ENTITY_ICON_COLORS[entityType] || "text-gray-500"}`, viewBox: "0 0 40 48", fill: "none", children: [
1739
- /* @__PURE__ */ jsx("path", { d: "M4 0h22l10 10v34a4 4 0 01-4 4H4a4 4 0 01-4-4V4a4 4 0 014-4z", fill: "white", fillOpacity: "0.92" }),
1740
- /* @__PURE__ */ jsx("path", { d: "M26 0l10 10H30a4 4 0 01-4-4V0z", fill: "currentColor", fillOpacity: "0.2" }),
1741
- /* @__PURE__ */ jsx("path", { d: "M4 0h22l10 10v34a4 4 0 01-4 4H4a4 4 0 01-4-4V4a4 4 0 014-4z", stroke: "currentColor", strokeWidth: "1.5", strokeOpacity: "0.5" })
1774
+ const renderIcon = (entityType, label, isSelected, entityId, fileKind) => {
1775
+ const isPreviewFile = entityType === "preview-file" && fileKind;
1776
+ const previewColor2 = isPreviewFile ? PREVIEW_FILE_COLORS[fileKind] : null;
1777
+ const previewCode = isPreviewFile ? PREVIEW_FILE_CODES[fileKind] : null;
1778
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1 w-20 p-2", children: [
1779
+ entityType === "folder" ? /* @__PURE__ */ jsx("div", { className: `w-12 h-12 flex items-center justify-center ${isSelected ? "rounded-lg bg-blue-400/30 ring-2 ring-blue-500" : ""}`, children: /* @__PURE__ */ jsxs("svg", { className: "h-12 w-12 drop-shadow-[0_2px_3px_rgba(0,0,0,0.3)]", viewBox: "0 0 48 48", children: [
1780
+ /* @__PURE__ */ jsx("path", { d: "M6 12a4 4 0 014-4h10l4 4h14a4 4 0 014 4v20a4 4 0 01-4 4H10a4 4 0 01-4-4V12z", fill: "white", stroke: "#eab308", strokeWidth: "2", strokeLinejoin: "round" }),
1781
+ /* @__PURE__ */ jsx("path", { d: "M6 18h36", stroke: "#eab308", strokeWidth: "1.5" })
1782
+ ] }) }) : entityType === "page" ? /* @__PURE__ */ jsx("div", { className: `w-12 h-12 flex items-center justify-center ${isSelected ? "rounded-lg bg-blue-400/30 ring-2 ring-blue-500" : ""}`, children: (() => {
1783
+ const icon = navIcons[label] || (entityId ? navIcons[entityId] : void 0);
1784
+ if (icon && isValidElement(icon)) {
1785
+ return cloneElement(icon, { className: "h-10 w-10 text-white drop-shadow-[0_2px_3px_rgba(0,0,0,0.4)]" });
1786
+ }
1787
+ return /* @__PURE__ */ jsx("svg", { className: "h-10 w-10 text-white drop-shadow-[0_2px_3px_rgba(0,0,0,0.4)]", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3.75 6A2.25 2.25 0 016 3.75h2.25A2.25 2.25 0 0110.5 6v2.25a2.25 2.25 0 01-2.25 2.25H6a2.25 2.25 0 01-2.25-2.25V6z" }) });
1788
+ })() }) : /* @__PURE__ */ jsxs("div", { className: `w-12 h-12 relative flex items-center justify-center ${isSelected ? "rounded-lg bg-blue-400/30 ring-2 ring-blue-500" : ""}`, children: [
1789
+ /* @__PURE__ */ jsxs("svg", { className: `w-10 h-12 drop-shadow-[0_2px_3px_rgba(0,0,0,0.3)] ${previewColor2 ?? ENTITY_ICON_COLORS[entityType] ?? "text-gray-500"}`, viewBox: "0 0 40 48", fill: "none", children: [
1790
+ /* @__PURE__ */ jsx("path", { d: "M4 0h22l10 10v34a4 4 0 01-4 4H4a4 4 0 01-4-4V4a4 4 0 014-4z", fill: "white", fillOpacity: "0.92" }),
1791
+ /* @__PURE__ */ jsx("path", { d: "M26 0l10 10H30a4 4 0 01-4-4V0z", fill: "currentColor", fillOpacity: "0.2" }),
1792
+ /* @__PURE__ */ jsx("path", { d: "M4 0h22l10 10v34a4 4 0 01-4 4H4a4 4 0 01-4-4V4a4 4 0 014-4z", stroke: "currentColor", strokeWidth: "1.5", strokeOpacity: "0.5" })
1793
+ ] }),
1794
+ /* @__PURE__ */ jsx("span", { className: `absolute inset-0 flex items-center justify-center text-[9px] font-bold pt-2 ${previewColor2 ?? ENTITY_ICON_COLORS[entityType] ?? "text-gray-600"}`, children: previewCode ?? ENTITY_ICONS[entityType] ?? entityType.slice(0, 3).toUpperCase() })
1742
1795
  ] }),
1743
- /* @__PURE__ */ jsx("span", { className: `absolute inset-0 flex items-center justify-center text-[9px] font-bold pt-2 ${ENTITY_ICON_COLORS[entityType] || "text-gray-600"}`, children: ENTITY_ICONS[entityType] || entityType.slice(0, 3).toUpperCase() })
1744
- ] }),
1745
- /* @__PURE__ */ jsx("span", { className: `text-[10px] font-medium text-center leading-tight w-full drop-shadow-[0_1px_2px_rgba(0,0,0,0.8)] ${isSelected ? "text-blue-200 bg-blue-600/60 rounded px-1" : "text-white"}`, children: label })
1746
- ] });
1796
+ /* @__PURE__ */ jsx("span", { className: `text-[10px] font-medium text-center leading-tight w-full drop-shadow-[0_1px_2px_rgba(0,0,0,0.8)] ${isSelected ? "text-blue-200 bg-blue-600/60 rounded px-1" : "text-white"}`, children: label })
1797
+ ] });
1798
+ };
1747
1799
  const menuStyle = (x, y) => ({
1748
1800
  ...x + 180 > window.innerWidth ? { right: window.innerWidth - x } : { left: x },
1749
1801
  ...y + 250 > window.innerHeight ? { bottom: window.innerHeight - y } : { top: y }
@@ -1866,10 +1918,21 @@ function Desktop({ profile }) {
1866
1918
  onContextMenu: (e) => handleItemContextMenu(e, i),
1867
1919
  onDoubleClick: (e) => {
1868
1920
  e.stopPropagation();
1869
- doc.entityType === "page" ? openPage(doc.entityId) : openEntity(doc.entityType, doc.entityId, null, doc.label);
1921
+ if (doc.entityType === "preview-file" && doc.filePath && doc.fileKind) {
1922
+ openPreviewFile({
1923
+ filePath: doc.filePath,
1924
+ filename: doc.label,
1925
+ kind: doc.fileKind,
1926
+ onStaged: (route) => openPage(route)
1927
+ });
1928
+ } else if (doc.entityType === "page") {
1929
+ openPage(doc.entityId);
1930
+ } else {
1931
+ openEntity(doc.entityType, doc.entityId, null, doc.label);
1932
+ }
1870
1933
  },
1871
1934
  className: "cursor-default select-none",
1872
- children: renderIcon(doc.entityType, doc.label, isSelected, doc.entityId)
1935
+ children: renderIcon(doc.entityType, doc.label, isSelected, doc.entityId, doc.fileKind)
1873
1936
  },
1874
1937
  `item-${doc.entityType}-${doc.entityId}-${i}`
1875
1938
  );
@@ -2161,7 +2224,18 @@ function Desktop({ profile }) {
2161
2224
  folder,
2162
2225
  items: folderItems(openFolder),
2163
2226
  onClose: () => setOpenFolder(null),
2164
- onOpen: (item) => openEntity(item.entityType, item.entityId, null, item.label),
2227
+ onOpen: (item) => {
2228
+ if (item.entityType === "preview-file" && item.filePath && item.fileKind) {
2229
+ openPreviewFile({
2230
+ filePath: item.filePath,
2231
+ filename: item.label,
2232
+ kind: item.fileKind,
2233
+ onStaged: (route) => openPage(route)
2234
+ });
2235
+ } else {
2236
+ openEntity(item.entityType, item.entityId, null, item.label);
2237
+ }
2238
+ },
2165
2239
  onMoveOut: (toMove) => {
2166
2240
  const ids = new Set(toMove.map((t) => `${t.entityType}|${t.entityId}`));
2167
2241
  const updated = favDocs.map(