react-os-shell 0.5.0 → 0.6.2

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 (54) hide show
  1. package/dist/{Browser-PIKJVKWD.js → Browser-XZEAEJLW.js} +4 -4
  2. package/dist/{Browser-PIKJVKWD.js.map → Browser-XZEAEJLW.js.map} +1 -1
  3. package/dist/{Calculator-3RMMEJOR.js → Calculator-Y7TKDGFS.js} +5 -5
  4. package/dist/{Calculator-3RMMEJOR.js.map → Calculator-Y7TKDGFS.js.map} +1 -1
  5. package/dist/{Calendar-YI2OPWBN.js → Calendar-LUQWUGFY.js} +4 -4
  6. package/dist/{Calendar-YI2OPWBN.js.map → Calendar-LUQWUGFY.js.map} +1 -1
  7. package/dist/{CurrencyConverter-QW6RYH3K.js → CurrencyConverter-GZFBW5PE.js} +5 -5
  8. package/dist/{CurrencyConverter-QW6RYH3K.js.map → CurrencyConverter-GZFBW5PE.js.map} +1 -1
  9. package/dist/{Documents-U3SM3I5H.js → Documents-IT4EQ5CF.js} +4 -4
  10. package/dist/{Documents-U3SM3I5H.js.map → Documents-IT4EQ5CF.js.map} +1 -1
  11. package/dist/{Email-F7P3EDVG.js → Email-SNA6KIKR.js} +4 -4
  12. package/dist/{Email-F7P3EDVG.js.map → Email-SNA6KIKR.js.map} +1 -1
  13. package/dist/Files-E4XEDYAP.js +11 -0
  14. package/dist/{Files-NR2ZZRGK.js.map → Files-E4XEDYAP.js.map} +1 -1
  15. package/dist/{Minesweeper-GG66GIOY.js → Minesweeper-6GUVR7CV.js} +4 -4
  16. package/dist/{Minesweeper-GG66GIOY.js.map → Minesweeper-6GUVR7CV.js.map} +1 -1
  17. package/dist/{Notepad-OSHH77DS.js → Notepad-PQHDQH2L.js} +4 -4
  18. package/dist/{Notepad-OSHH77DS.js.map → Notepad-PQHDQH2L.js.map} +1 -1
  19. package/dist/{PomodoroTimer-LTXRM4QE.js → PomodoroTimer-3W7AYUDV.js} +5 -5
  20. package/dist/{PomodoroTimer-LTXRM4QE.js.map → PomodoroTimer-3W7AYUDV.js.map} +1 -1
  21. package/dist/Preview-BUVU7RTT.js +8 -0
  22. package/dist/{Preview-Z2ANAYNJ.js.map → Preview-BUVU7RTT.js.map} +1 -1
  23. package/dist/{Sidebar-SHNDADVO.js → Sidebar-Q3PRJ2FP.js} +20 -11
  24. package/dist/Sidebar-Q3PRJ2FP.js.map +1 -0
  25. package/dist/Spreadsheet-G4HT4C7B.js +6 -0
  26. package/dist/{Spreadsheet-MYOVKLI2.js.map → Spreadsheet-G4HT4C7B.js.map} +1 -1
  27. package/dist/{Weather-5HJCLITK.js → Weather-CXK57AZW.js} +5 -5
  28. package/dist/{Weather-5HJCLITK.js.map → Weather-CXK57AZW.js.map} +1 -1
  29. package/dist/{WorldClock-IJLE7IOF.js → WorldClock-LBWQKKOA.js} +5 -5
  30. package/dist/{WorldClock-IJLE7IOF.js.map → WorldClock-LBWQKKOA.js.map} +1 -1
  31. package/dist/apps/index.js +20 -20
  32. package/dist/{chunk-2TNV3ODP.js → chunk-3RQ5TVEL.js} +3 -3
  33. package/dist/{chunk-2TNV3ODP.js.map → chunk-3RQ5TVEL.js.map} +1 -1
  34. package/dist/{chunk-BRWWUKPE.js → chunk-HG3O6XHN.js} +3 -3
  35. package/dist/{chunk-BRWWUKPE.js.map → chunk-HG3O6XHN.js.map} +1 -1
  36. package/dist/{chunk-JKPSKZGZ.js → chunk-KSRZU3GT.js} +3 -3
  37. package/dist/{chunk-JKPSKZGZ.js.map → chunk-KSRZU3GT.js.map} +1 -1
  38. package/dist/{chunk-YSMCY46G.js → chunk-MGPY5446.js} +4 -4
  39. package/dist/{chunk-YSMCY46G.js.map → chunk-MGPY5446.js.map} +1 -1
  40. package/dist/{chunk-6FNC3APL.js → chunk-NVAWKCAI.js} +3 -3
  41. package/dist/{chunk-6FNC3APL.js.map → chunk-NVAWKCAI.js.map} +1 -1
  42. package/dist/{chunk-K5ZMTKZC.js → chunk-XNXIIGHP.js} +4 -4
  43. package/dist/{chunk-K5ZMTKZC.js.map → chunk-XNXIIGHP.js.map} +1 -1
  44. package/dist/{chunk-YJONGQLG.js → chunk-ZF6AYO4G.js} +3 -3
  45. package/dist/chunk-ZF6AYO4G.js.map +1 -0
  46. package/dist/index.d.ts +13 -1
  47. package/dist/index.js +58 -22
  48. package/dist/index.js.map +1 -1
  49. package/package.json +1 -1
  50. package/dist/Files-NR2ZZRGK.js +0 -11
  51. package/dist/Preview-Z2ANAYNJ.js +0 -8
  52. package/dist/Sidebar-SHNDADVO.js.map +0 -1
  53. package/dist/Spreadsheet-MYOVKLI2.js +0 -6
  54. package/dist/chunk-YJONGQLG.js.map +0 -1
@@ -1,6 +1,6 @@
1
- import { setPdfPreview } from './chunk-BRWWUKPE.js';
1
+ import { setPdfPreview } from './chunk-HG3O6XHN.js';
2
2
  import { toast_default } from './chunk-WIJ45SYD.js';
3
- import { setSpreadsheetPreview } from './chunk-6FNC3APL.js';
3
+ import { setSpreadsheetPreview } from './chunk-NVAWKCAI.js';
4
4
 
5
5
  // src/utils/openPreviewFile.ts
6
6
  var PREVIEW_OPENED_EVENT = "react-os-shell:preview-opened";
@@ -42,5 +42,5 @@ async function openPreviewFile(opts) {
42
42
  }
43
43
 
44
44
  export { PREVIEW_OPENED_EVENT, openPreviewFile };
45
- //# sourceMappingURL=chunk-K5ZMTKZC.js.map
46
- //# sourceMappingURL=chunk-K5ZMTKZC.js.map
45
+ //# sourceMappingURL=chunk-XNXIIGHP.js.map
46
+ //# sourceMappingURL=chunk-XNXIIGHP.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/openPreviewFile.ts"],"names":[],"mappings":";;;;;AA6BO,IAAM,oBAAA,GAAuB;AAQpC,SAAS,SAAA,GAAY;AACnB,EAAA,MAAM,QAAA,GAAY,OAAO,MAAA,KAAW,WAAA,IAAgB,MAAA,CAAe,8BAAA;AACnE,EAAA,OAAA,CAAQ,QAAA,IAAY,uBAAA,EAAyB,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAChE;AAEA,eAAsB,gBAAgB,IAAA,EAA6C;AACjF,EAAA,MAAM,EAAE,QAAA,EAAU,QAAA,EAAU,IAAA,EAAM,UAAS,GAAI,IAAA;AAC/C,EAAA,IAAI;AACF,IAAA,MAAM,MAAM,MAAM,KAAA;AAAA,MAChB,GAAG,SAAA,EAAW,CAAA,eAAA,EAAkB,kBAAA,CAAmB,QAAQ,CAAC,CAAA,CAAA;AAAA,MAC5D,EAAE,aAAa,SAAA;AAAU,KAC3B;AACA,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,aAAA,CAAM,KAAA,CAAM,CAAA,iBAAA,EAAoB,GAAA,CAAI,MAAM,CAAA,CAAA,CAAG,CAAA;AAC7C,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,IAAA,IAAI,SAAS,KAAA,EAAO;AAClB,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,EAAK;AAC7B,MAAA,qBAAA,CAAsB,EAAE,GAAA,EAAK,IAAA,EAAM,QAAA,EAAU,CAAA;AAC7C,MAAA,QAAA,GAAW,cAAc,CAAA;AAAA,IAC3B,CAAA,MAAO;AACL,MAAA,MAAM,GAAA,GAAM,GAAA,CAAI,eAAA,CAAgB,IAAI,CAAA;AACpC,MAAA,aAAA,CAAc,EAAE,GAAA,EAAK,QAAA,EAAU,IAAA,EAAM,CAAA;AACrC,MAAA,QAAA,GAAW,UAAU,CAAA;AAAA,IACvB;AACA,IAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACjC,MAAA,MAAA,CAAO,aAAA,CAAc,IAAI,WAAA,CAAiC,oBAAA,EAAsB;AAAA,QAC9E,MAAA,EAAQ,EAAE,QAAA,EAAU,QAAA,EAAU,IAAA;AAAK,OACpC,CAAC,CAAA;AAAA,IACJ;AACA,IAAA,OAAO,IAAA;AAAA,EACT,SAAS,CAAA,EAAQ;AACf,IAAA,aAAA,CAAM,KAAA,CAAM,CAAA,EAAG,OAAA,IAAW,aAAa,CAAA;AACvC,IAAA,OAAO,KAAA;AAAA,EACT;AACF","file":"chunk-K5ZMTKZC.js","sourcesContent":["/**\n * Fetch a file from the user's file-server and route it into the right\n * preview window. Shared by the Files app and the desktop Documents\n * folder's shortcut click-through.\n *\n * On success, dispatches `react-os-shell:preview-opened` so Desktop can\n * record the file as a shortcut without this util needing access to the\n * prefs adapter.\n */\nimport toast from '../shell/toast';\nimport { setPdfPreview } from '../apps/Preview';\nimport { setSpreadsheetPreview } from '../apps/Spreadsheet';\n\nexport type PreviewFileKind = 'pdf' | 'dxf' | '3d' | 'image' | 'csv';\n\nexport interface OpenPreviewFileOpts {\n /** Server-relative path, e.g. \"/reports/Q1.pdf\". */\n filePath: string;\n /** Display name (also used as the download filename). */\n filename: string;\n /** Which viewer to route into. CSV opens in Spreadsheet; the rest open in Preview. */\n kind: PreviewFileKind;\n /** Optional callback invoked after staging the preview, with the route to\n * open (e.g. '/preview' or '/spreadsheet'). The caller is responsible\n * for actually opening the page since the window manager hook is\n * React-scoped. */\n onStaged?: (route: '/preview' | '/spreadsheet') => void;\n}\n\nexport const PREVIEW_OPENED_EVENT = 'react-os-shell:preview-opened';\n\nexport interface PreviewOpenedDetail {\n filePath: string;\n filename: string;\n kind: PreviewFileKind;\n}\n\nfunction getServer() {\n const override = (typeof window !== 'undefined' && (window as any).__REACT_OS_SHELL_FILE_SERVER__) as string | undefined;\n return (override || 'http://localhost:4000').replace(/\\/$/, '');\n}\n\nexport async function openPreviewFile(opts: OpenPreviewFileOpts): Promise<boolean> {\n const { filePath, filename, kind, onStaged } = opts;\n try {\n const res = await fetch(\n `${getServer()}/api/file?path=${encodeURIComponent(filePath)}`,\n { credentials: 'include' },\n );\n if (!res.ok) {\n toast.error(`Download failed (${res.status})`);\n return false;\n }\n const blob = await res.blob();\n if (kind === 'csv') {\n const text = await blob.text();\n setSpreadsheetPreview({ csv: text, filename });\n onStaged?.('/spreadsheet');\n } else {\n const url = URL.createObjectURL(blob);\n setPdfPreview({ url, filename, kind });\n onStaged?.('/preview');\n }\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new CustomEvent<PreviewOpenedDetail>(PREVIEW_OPENED_EVENT, {\n detail: { filePath, filename, kind },\n }));\n }\n return true;\n } catch (e: any) {\n toast.error(e?.message || 'Open failed');\n return false;\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/utils/openPreviewFile.ts"],"names":[],"mappings":";;;;;AA6BO,IAAM,oBAAA,GAAuB;AAQpC,SAAS,SAAA,GAAY;AACnB,EAAA,MAAM,QAAA,GAAY,OAAO,MAAA,KAAW,WAAA,IAAgB,MAAA,CAAe,8BAAA;AACnE,EAAA,OAAA,CAAQ,QAAA,IAAY,uBAAA,EAAyB,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAChE;AAEA,eAAsB,gBAAgB,IAAA,EAA6C;AACjF,EAAA,MAAM,EAAE,QAAA,EAAU,QAAA,EAAU,IAAA,EAAM,UAAS,GAAI,IAAA;AAC/C,EAAA,IAAI;AACF,IAAA,MAAM,MAAM,MAAM,KAAA;AAAA,MAChB,GAAG,SAAA,EAAW,CAAA,eAAA,EAAkB,kBAAA,CAAmB,QAAQ,CAAC,CAAA,CAAA;AAAA,MAC5D,EAAE,aAAa,SAAA;AAAU,KAC3B;AACA,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,aAAA,CAAM,KAAA,CAAM,CAAA,iBAAA,EAAoB,GAAA,CAAI,MAAM,CAAA,CAAA,CAAG,CAAA;AAC7C,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,IAAA,IAAI,SAAS,KAAA,EAAO;AAClB,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,EAAK;AAC7B,MAAA,qBAAA,CAAsB,EAAE,GAAA,EAAK,IAAA,EAAM,QAAA,EAAU,CAAA;AAC7C,MAAA,QAAA,GAAW,cAAc,CAAA;AAAA,IAC3B,CAAA,MAAO;AACL,MAAA,MAAM,GAAA,GAAM,GAAA,CAAI,eAAA,CAAgB,IAAI,CAAA;AACpC,MAAA,aAAA,CAAc,EAAE,GAAA,EAAK,QAAA,EAAU,IAAA,EAAM,CAAA;AACrC,MAAA,QAAA,GAAW,UAAU,CAAA;AAAA,IACvB;AACA,IAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACjC,MAAA,MAAA,CAAO,aAAA,CAAc,IAAI,WAAA,CAAiC,oBAAA,EAAsB;AAAA,QAC9E,MAAA,EAAQ,EAAE,QAAA,EAAU,QAAA,EAAU,IAAA;AAAK,OACpC,CAAC,CAAA;AAAA,IACJ;AACA,IAAA,OAAO,IAAA;AAAA,EACT,SAAS,CAAA,EAAQ;AACf,IAAA,aAAA,CAAM,KAAA,CAAM,CAAA,EAAG,OAAA,IAAW,aAAa,CAAA;AACvC,IAAA,OAAO,KAAA;AAAA,EACT;AACF","file":"chunk-XNXIIGHP.js","sourcesContent":["/**\n * Fetch a file from the user's file-server and route it into the right\n * preview window. Shared by the Files app and the desktop Documents\n * folder's shortcut click-through.\n *\n * On success, dispatches `react-os-shell:preview-opened` so Desktop can\n * record the file as a shortcut without this util needing access to the\n * prefs adapter.\n */\nimport toast from '../shell/toast';\nimport { setPdfPreview } from '../apps/Preview';\nimport { setSpreadsheetPreview } from '../apps/Spreadsheet';\n\nexport type PreviewFileKind = 'pdf' | 'dxf' | '3d' | 'image' | 'csv';\n\nexport interface OpenPreviewFileOpts {\n /** Server-relative path, e.g. \"/reports/Q1.pdf\". */\n filePath: string;\n /** Display name (also used as the download filename). */\n filename: string;\n /** Which viewer to route into. CSV opens in Spreadsheet; the rest open in Preview. */\n kind: PreviewFileKind;\n /** Optional callback invoked after staging the preview, with the route to\n * open (e.g. '/preview' or '/spreadsheet'). The caller is responsible\n * for actually opening the page since the window manager hook is\n * React-scoped. */\n onStaged?: (route: '/preview' | '/spreadsheet') => void;\n}\n\nexport const PREVIEW_OPENED_EVENT = 'react-os-shell:preview-opened';\n\nexport interface PreviewOpenedDetail {\n filePath: string;\n filename: string;\n kind: PreviewFileKind;\n}\n\nfunction getServer() {\n const override = (typeof window !== 'undefined' && (window as any).__REACT_OS_SHELL_FILE_SERVER__) as string | undefined;\n return (override || 'http://localhost:4000').replace(/\\/$/, '');\n}\n\nexport async function openPreviewFile(opts: OpenPreviewFileOpts): Promise<boolean> {\n const { filePath, filename, kind, onStaged } = opts;\n try {\n const res = await fetch(\n `${getServer()}/api/file?path=${encodeURIComponent(filePath)}`,\n { credentials: 'include' },\n );\n if (!res.ok) {\n toast.error(`Download failed (${res.status})`);\n return false;\n }\n const blob = await res.blob();\n if (kind === 'csv') {\n const text = await blob.text();\n setSpreadsheetPreview({ csv: text, filename });\n onStaged?.('/spreadsheet');\n } else {\n const url = URL.createObjectURL(blob);\n setPdfPreview({ url, filename, kind });\n onStaged?.('/preview');\n }\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new CustomEvent<PreviewOpenedDetail>(PREVIEW_OPENED_EVENT, {\n detail: { filePath, filename, kind },\n }));\n }\n return true;\n } catch (e: any) {\n toast.error(e?.message || 'Open failed');\n return false;\n }\n}\n"]}
@@ -26,7 +26,7 @@ function setShellNavIcons(icons) {
26
26
  }
27
27
  var sectionIcons = {};
28
28
  var navSections = [];
29
- var startMenuCategories = { erp: [], system: [], virtual: [] };
29
+ var startMenuCategories = { erp: [], system: [], virtual: [], footer: [] };
30
30
 
31
31
  // src/utils/glass.ts
32
32
  function getMenuOpacity() {
@@ -67,5 +67,5 @@ var GLASS_DIVIDER = "border-white/20";
67
67
  var GLASS_INPUT_BG = "glass-input-bg";
68
68
 
69
69
  export { GLASS_DIVIDER, GLASS_INPUT_BG, glassStyle, isSection, navIcons, navSections, sectionIcons, setShellNavIcons, startMenuCategories };
70
- //# sourceMappingURL=chunk-YJONGQLG.js.map
71
- //# sourceMappingURL=chunk-YJONGQLG.js.map
70
+ //# sourceMappingURL=chunk-ZF6AYO4G.js.map
71
+ //# sourceMappingURL=chunk-ZF6AYO4G.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shell/nav-types.ts","../src/shell-config/nav.tsx","../src/utils/glass.ts"],"names":[],"mappings":";AAkDO,SAAS,UAAU,IAAA,EAAgD;AACxE,EAAA,OAAO,OAAA,IAAW,IAAA;AACpB;;;ACpCA,IAAM,YAAuC,EAAC;AACvC,IAAM,QAAA,GAAsC,IAAI,KAAA,CAAM,SAAA,EAAW;AAAA,EACtE,GAAA,CAAI,IAAI,CAAA,EAAW;AAAE,IAAA,OAAO,UAAU,CAAC,CAAA;AAAA,EAAG,CAAA;AAAA,EAC1C,GAAA,CAAI,IAAI,CAAA,EAAW;AAAE,IAAA,OAAO,CAAA,IAAK,SAAA;AAAA,EAAW,CAAA;AAAA,EAC5C,OAAA,GAAU;AAAE,IAAA,OAAO,MAAA,CAAO,KAAK,SAAS,CAAA;AAAA,EAAG,CAAA;AAAA,EAC3C,wBAAA,CAAyB,IAAI,CAAA,EAAW;AACtC,IAAA,IAAI,CAAA,IAAK,SAAA,EAAW,OAAO,EAAE,YAAA,EAAc,IAAA,EAAM,UAAA,EAAY,IAAA,EAAM,KAAA,EAAO,SAAA,CAAU,CAAC,CAAA,EAAE;AACvF,IAAA,OAAO,MAAA;AAAA,EACT;AACF,CAAC;AACM,SAAS,iBAAiB,KAAA,EAAwC;AACvE,EAAA,KAAA,MAAW,KAAK,MAAA,CAAO,IAAA,CAAK,SAAS,CAAA,EAAG,OAAO,UAAU,CAAC,CAAA;AAC1D,EAAA,MAAA,CAAO,MAAA,CAAO,WAAW,KAAK,CAAA;AAChC;AAEO,IAAM,eAA0C;AAChD,IAAM,cAAwC;AAC9C,IAAM,mBAAA,GAA2C,EAAE,GAAA,EAAK,EAAC,EAAG,MAAA,EAAQ,EAAC,EAAG,OAAA,EAAS,EAAC,EAAG,MAAA,EAAQ,EAAC;;;AC9BrG,SAAS,cAAA,GAAyB;AAChC,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,iBAAiB,QAAA,CAAS,eAAe,EAAE,gBAAA,CAAiB,gBAAgB,GAAG,IAAA,EAAK;AAChG,IAAA,IAAI,GAAA,EAAK,OAAO,UAAA,CAAW,GAAG,CAAA;AAAA,EAChC,CAAA,CAAA,MAAQ;AAAA,EAAC;AACT,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,WAAA,GAAuB;AAC9B,EAAA,IAAI;AACF,IAAA,OAAO,QAAA,CAAS,eAAA,CAAgB,YAAA,CAAa,YAAY,CAAA,KAAM,MAAA;AAAA,EACjE,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAKO,SAAS,WAAW,OAAA,EAAiC;AAC1D,EAAA,MAAM,CAAA,GAAI,WAAW,cAAA,EAAe;AACpC,EAAA,IAAI,aAAY,EAAG;AAGjB,IAAA,OAAO;AAAA,MACL,UAAA,EAAY,yCAAyC,CAAA,GAAI,IAAI,uBAAuB,CAAA,GAAI,IAAI,CAAA,qBAAA,EAAwB,CAAA,GAAI,IAAI,CAAA,OAAA,CAAA;AAAA,MAC5H,cAAA,EAAgB,0BAAA;AAAA,MAChB,oBAAA,EAAsB,0BAAA;AAAA,MACtB,MAAA,EAAQ,kCAAA;AAAA,MACR,SAAA,EAAW;AAAA,KACb;AAAA,EACF;AACA,EAAA,OAAO;AAAA,IACL,UAAA,EAAY,4CAA4C,CAAA,GAAI,IAAI,0BAA0B,CAAA,GAAI,IAAI,CAAA,wBAAA,EAA2B,CAAA,GAAI,IAAI,CAAA,OAAA,CAAA;AAAA,IACrI,cAAA,EAAgB,0BAAA;AAAA,IAChB,oBAAA,EAAsB,0BAAA;AAAA,IACtB,MAAA,EAAQ,kCAAA;AAAA,IACR,SAAA,EAAW;AAAA,GACb;AACF;AAGO,IAAM,aAAA,GAAgB;AAKtB,IAAM,cAAA,GAAiB","file":"chunk-ZF6AYO4G.js","sourcesContent":["/**\n * Nav data types used by <Layout> + <StartMenu>. The actual sections, icons,\n * and categories are consumer-supplied via Layout props — the package never\n * ships nav DATA, only the shape it expects.\n */\nimport type { ReactNode } from 'react';\n\nexport interface NavItem {\n to: string;\n label: string;\n perms?: string[];\n dividerAfter?: boolean;\n /** Optional 3rd-level sub-items. Hovering the parent in <StartMenu> opens\n * a nested flyout; in <Sidebar> the parent becomes an inline sub-accordion. */\n children?: NavItem[];\n}\n\nexport interface NavSection {\n label: string;\n items: NavItem[];\n perms?: string[];\n /** Optional landing route for clicks on the section title itself\n * (e.g. R&D's `/rd` dashboard). */\n to?: string;\n}\n\nexport interface VirtualSection {\n label: string;\n items: NavItem[];\n icon?: ReactNode;\n}\n\nexport interface StartMenuCategories {\n /** Section labels rendered in the \"ERP\" group (bold, with section icon). */\n erp: string[];\n /** Section labels rendered in the \"system\" group. */\n system: string[];\n /** Optional virtual flyouts (e.g. a \"Utilities\" tray). */\n virtual?: VirtualSection[];\n /** Optional section labels pinned to the bottom of the menu, next to the user\n * profile, separated from the ERP group by a divider. */\n footer?: string[];\n /** Optional flat top-level items pinned to the bottom of the menu, next to\n * the user profile, separated from the ERP group by a divider. Unlike\n * `footer` (section labels rendered as flyouts), these render as direct\n * clickable rows — use for standalone destinations like System Preferences\n * or a bug-report link. */\n footerItems?: NavItem[];\n}\n\nexport function isSection(item: NavSection | NavItem): item is NavSection {\n return 'items' in item;\n}\n","/**\n * INTERNAL stub — package-side compatibility for files that legacy-imported\n * default nav data from `shell-config/nav`. The package never ships nav\n * DATA; consumers always supply `navSections` / `navIcons` / `sectionIcons` /\n * `categories` as Layout props.\n *\n * Empty defaults exported here so the copied files compile during the\n * extraction transition. Each consumer-facing field is also re-exported as\n * a TYPE alias for code that only needed the shape.\n */\nimport type { ReactNode } from 'react';\nimport type { NavItem, NavSection, StartMenuCategories, VirtualSection } from '../shell/nav-types';\n\n// Live proxy: WindowManager reads window-title icons from this module-level\n// map. Consumers register their full icon set once at app startup so the\n// title bars show the same glyphs as the start menu.\nconst _navIcons: Record<string, ReactNode> = {};\nexport const navIcons: Record<string, ReactNode> = new Proxy(_navIcons, {\n get(_t, k: string) { return _navIcons[k]; },\n has(_t, k: string) { return k in _navIcons; },\n ownKeys() { return Object.keys(_navIcons); },\n getOwnPropertyDescriptor(_t, k: string) {\n if (k in _navIcons) return { configurable: true, enumerable: true, value: _navIcons[k] };\n return undefined;\n },\n});\nexport function setShellNavIcons(icons: Record<string, ReactNode>): void {\n for (const k of Object.keys(_navIcons)) delete _navIcons[k];\n Object.assign(_navIcons, icons);\n}\n\nexport const sectionIcons: Record<string, ReactNode> = {};\nexport const navSections: (NavSection | NavItem)[] = [];\nexport const startMenuCategories: StartMenuCategories = { erp: [], system: [], virtual: [], footer: [] };\n\nexport { isSection } from '../shell/nav-types';\nexport type { NavItem, NavSection, StartMenuCategories, VirtualSection };\n","import type { CSSProperties } from 'react';\n\n/** Read the system menu opacity from CSS custom property set by Layout */\nfunction getMenuOpacity(): number {\n try {\n const val = getComputedStyle(document.documentElement).getPropertyValue('--menu-opacity')?.trim();\n if (val) return parseFloat(val);\n } catch {}\n return 0.95;\n}\n\nfunction isDarkTheme(): boolean {\n try {\n return document.documentElement.getAttribute('data-theme') === 'dark';\n } catch {\n return false;\n }\n}\n\n/** Frosted glass style — shared across all menus, popups, and glass UI elements.\n * Reads --menu-opacity CSS variable set by the theme system, and adapts the\n * base tint to dark mode so menus don't stay light-cream when text is light. */\nexport function glassStyle(opacity?: number): CSSProperties {\n const o = opacity ?? getMenuOpacity();\n if (isDarkTheme()) {\n // Dark frosted glass — Catppuccin-aligned base (#1e1e2e / 30,30,46) with\n // a subtle gradient and lighter inner highlight.\n return {\n background: `linear-gradient(135deg, rgba(30,30,46,${o * 0.85}) 0%, rgba(24,24,37,${o * 0.75}) 50%, rgba(30,30,46,${o * 0.85}) 100%)`,\n backdropFilter: 'blur(40px) saturate(1.6)',\n WebkitBackdropFilter: 'blur(40px) saturate(1.6)',\n border: '1px solid rgba(255,255,255,0.08)',\n boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.06), inset 0 -1px 0 rgba(0,0,0,0.4), 0 8px 32px rgba(0,0,0,0.5), 0 2px 8px rgba(0,0,0,0.3)',\n };\n }\n return {\n background: `linear-gradient(135deg, rgba(255,255,255,${o * 0.85}) 0%, rgba(255,255,255,${o * 0.65}) 50%, rgba(255,255,255,${o * 0.75}) 100%)`,\n backdropFilter: 'blur(40px) saturate(1.8)',\n WebkitBackdropFilter: 'blur(40px) saturate(1.8)',\n border: '1px solid rgba(255,255,255,0.35)',\n boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.4), inset 0 -1px 0 rgba(255,255,255,0.1), 0 8px 32px rgba(0,0,0,0.15), 0 2px 8px rgba(0,0,0,0.08)',\n };\n}\n\n/** Glass divider border color */\nexport const GLASS_DIVIDER = 'border-white/20';\n\n/** Glass input/search bar background — declared in styles.css so it can adapt\n * to dark mode (a flat `bg-white/15` reads as a too-bright tile on the dark\n * glass gradient). */\nexport const GLASS_INPUT_BG = 'glass-input-bg';\n"]}
package/dist/index.d.ts CHANGED
@@ -57,6 +57,15 @@ interface StartMenuCategories {
57
57
  system: string[];
58
58
  /** Optional virtual flyouts (e.g. a "Utilities" tray). */
59
59
  virtual?: VirtualSection[];
60
+ /** Optional section labels pinned to the bottom of the menu, next to the user
61
+ * profile, separated from the ERP group by a divider. */
62
+ footer?: string[];
63
+ /** Optional flat top-level items pinned to the bottom of the menu, next to
64
+ * the user profile, separated from the ERP group by a divider. Unlike
65
+ * `footer` (section labels rendered as flyouts), these render as direct
66
+ * clickable rows — use for standalone destinations like System Preferences
67
+ * or a bug-report link. */
68
+ footerItems?: NavItem[];
60
69
  }
61
70
 
62
71
  /**
@@ -708,8 +717,11 @@ interface LayoutProps {
708
717
  * the shell. The shell renders the node as-is — keep it small (a
709
718
  * single icon-sized button) so it fits the existing tray rhythm. */
710
719
  taskbarTrayLeft?: ReactNode;
720
+ /** Show the Mail & Calendar connect button in the system tray.
721
+ * Defaults to true. Set false for portals with no mail integration. */
722
+ showMail?: boolean;
711
723
  }
712
- declare function Layout({ productName, productIcon, wallpapers, navSections, navIcons, sectionIcons, categories, notifications, search, taskbarTrayLeft, }?: LayoutProps): react_jsx_runtime.JSX.Element;
724
+ declare function Layout({ productName, productIcon, wallpapers, navSections, navIcons, sectionIcons, categories, notifications, search, taskbarTrayLeft, showMail, }?: LayoutProps): react_jsx_runtime.JSX.Element;
713
725
 
714
726
  interface StartMenuProps {
715
727
  open: boolean;
package/dist/index.js CHANGED
@@ -6,21 +6,21 @@ export { setShellMailServer, useMailAuth } from './chunk-VBFB3ZIN.js';
6
6
  import { subscribePomo, getPomoSnapshot } from './chunk-MK3HLUO4.js';
7
7
  import { useShellPrefs } from './chunk-36VM54SC.js';
8
8
  export { ShellPrefsProvider, useLocalStoragePrefs, useShellPrefs } from './chunk-36VM54SC.js';
9
- import { PREVIEW_OPENED_EVENT, openPreviewFile } from './chunk-K5ZMTKZC.js';
9
+ import { PREVIEW_OPENED_EVENT, openPreviewFile } from './chunk-XNXIIGHP.js';
10
10
  import { playNotification, playStartup, soundsEnabled, getSoundConfig, SOUND_PACK_KEYS, SOUND_PACKS, SOUND_TYPES, SOUND_TYPE_LABELS, setSoundForType, previewSound, setAllSounds, playLogout } from './chunk-D7PYW2QS.js';
11
- import { setPdfPreview } from './chunk-BRWWUKPE.js';
11
+ import { setPdfPreview } from './chunk-HG3O6XHN.js';
12
12
  import './chunk-KUIPWCTJ.js';
13
13
  import { toast_default } from './chunk-WIJ45SYD.js';
14
14
  export { toast_default as toast } from './chunk-WIJ45SYD.js';
15
- export { EditableGrid } from './chunk-6FNC3APL.js';
16
- import { useWindowManager, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, ModalActions, useIsMobile, useModalActive, client_default, LoadingSpinner, WINDOW_REGISTRY, isPageEntry, ThumbCard, activateModal } from './chunk-2TNV3ODP.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-2TNV3ODP.js';
15
+ export { EditableGrid } from './chunk-NVAWKCAI.js';
16
+ import { useWindowManager, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, ModalActions, useIsMobile, useModalActive, client_default, LoadingSpinner, WINDOW_REGISTRY, isPageEntry, ThumbCard, activateModal } from './chunk-3RQ5TVEL.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-3RQ5TVEL.js';
18
18
  import { confirm } from './chunk-PLGHQ7QW.js';
19
19
  export { ConfirmProvider, confirm, confirmDestructive, prompt } from './chunk-PLGHQ7QW.js';
20
20
  import { useAuth, useShellAuth } from './chunk-ADJ3CERD.js';
21
21
  export { ShellAuthProvider, setShellAuthBridge, useShellAuth } from './chunk-ADJ3CERD.js';
22
- import { glassStyle, startMenuCategories, navSections, isSection, GLASS_INPUT_BG, navIcons, sectionIcons } from './chunk-YJONGQLG.js';
23
- export { GLASS_DIVIDER, GLASS_INPUT_BG, glassStyle, setShellNavIcons } from './chunk-YJONGQLG.js';
22
+ import { glassStyle, startMenuCategories, navSections, isSection, GLASS_INPUT_BG, navIcons, sectionIcons } from './chunk-ZF6AYO4G.js';
23
+ export { GLASS_DIVIDER, GLASS_INPUT_BG, glassStyle, setShellNavIcons } from './chunk-ZF6AYO4G.js';
24
24
  import { createContext, lazy, useState, useRef, useEffect, useCallback, useLayoutEffect, useContext, Suspense, isValidElement, cloneElement, useMemo, useSyncExternalStore } from 'react';
25
25
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
26
26
  import { Dialog, DialogBackdrop, DialogPanel, DialogTitle } from '@headlessui/react';
@@ -915,7 +915,7 @@ function StatusBadge({ status }) {
915
915
  }
916
916
 
917
917
  // src/version.ts
918
- var VERSION = "0.5.0" ;
918
+ var VERSION = "0.6.2" ;
919
919
  var APP_VERSION = VERSION;
920
920
 
921
921
  // src/changelog.ts
@@ -2887,11 +2887,13 @@ function StartMenu({
2887
2887
  }) {
2888
2888
  const erpLabels = new Set(categories.erp);
2889
2889
  const systemLabels = new Set(categories.system);
2890
+ const footerLabels = new Set(categories.footer ?? []);
2890
2891
  const virtualSections = categories.virtual ?? [];
2891
2892
  const virtualByLabel = Object.fromEntries(
2892
2893
  virtualSections.map((v) => [v.label, v])
2893
2894
  );
2894
2895
  const { hasAnyPerm } = useAuth();
2896
+ const footerItems = (categories.footerItems ?? []).filter((item) => !item.perms || hasAnyPerm(item.perms));
2895
2897
  const isMobile = useIsMobile();
2896
2898
  const [hoveredSection, setHoveredSection] = useState(null);
2897
2899
  const [hoveredY, setHoveredY] = useState(0);
@@ -2953,6 +2955,7 @@ function StartMenu({
2953
2955
  pushItem(entry);
2954
2956
  }
2955
2957
  }
2958
+ for (const it of footerItems) pushItem(it);
2956
2959
  const filtered = search.length >= 1 ? allItems.filter(({ item }) => item.label.toLowerCase().includes(search.toLowerCase())) : allItems;
2957
2960
  return /* @__PURE__ */ jsxs(
2958
2961
  "div",
@@ -3003,6 +3006,7 @@ function StartMenu({
3003
3006
  const topItems = navSections2.filter((item) => !isSection(item));
3004
3007
  const erpSections = navSections2.filter((item) => isSection(item) && erpLabels.has(item.label));
3005
3008
  const systemSections = navSections2.filter((item) => isSection(item) && systemLabels.has(item.label));
3009
+ const footerSections = navSections2.filter((item) => isSection(item) && footerLabels.has(item.label));
3006
3010
  const getVisibleItems = (section) => section.items.filter((item) => !item.perms || hasAnyPerm(item.perms));
3007
3011
  const matchTree = (it, sectionLabel) => {
3008
3012
  if (it.perms && !hasAnyPerm(it.perms)) return [];
@@ -3015,13 +3019,16 @@ function StartMenu({
3015
3019
  }
3016
3020
  return hits;
3017
3021
  };
3018
- const searchResults = search.length >= 2 ? navSections2.flatMap((item) => {
3019
- if (isSection(item)) {
3020
- const sec = item;
3021
- return sec.items.flatMap((i) => matchTree(i, sec.label));
3022
- }
3023
- return matchTree(item, "");
3024
- }) : [];
3022
+ const searchResults = search.length >= 2 ? [
3023
+ ...navSections2.flatMap((item) => {
3024
+ if (isSection(item)) {
3025
+ const sec = item;
3026
+ return sec.items.flatMap((i) => matchTree(i, sec.label));
3027
+ }
3028
+ return matchTree(item, "");
3029
+ }),
3030
+ ...footerItems.flatMap((item) => matchTree(item, ""))
3031
+ ] : [];
3025
3032
  const posStyle = taskbarPosition === "top" ? { top: taskbarH + 8, left: 8 } : taskbarPosition === "left" ? { top: 8, left: taskbarW + 8 } : taskbarPosition === "right" ? { top: 8, right: taskbarW + 8 } : { bottom: taskbarH + 8, left: 8 };
3026
3033
  const iconEl = (path) => {
3027
3034
  const icon = navIcons2[path];
@@ -3034,7 +3041,7 @@ function StartMenu({
3034
3041
  return null;
3035
3042
  };
3036
3043
  const hoveredVirtual = hoveredSection ? virtualByLabel[hoveredSection] : void 0;
3037
- const hoveredData = hoveredVirtual ? null : hoveredSection ? [...erpSections, ...systemSections].find((s) => s.label === hoveredSection) : null;
3044
+ const hoveredData = hoveredVirtual ? null : hoveredSection ? [...erpSections, ...systemSections, ...footerSections].find((s) => s.label === hoveredSection) : null;
3038
3045
  const flyoutItems = hoveredVirtual ? hoveredVirtual.items : hoveredData ? getVisibleItems(hoveredData) : [];
3039
3046
  const menuDensity = typeof document !== "undefined" ? getComputedStyle(document.documentElement).getPropertyValue("--menu-density")?.trim() || "normal" : "normal";
3040
3047
  const tight = menuDensity === "tight";
@@ -3148,6 +3155,20 @@ function StartMenu({
3148
3155
  i
3149
3156
  )) }) : /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto px-1 pb-1 flex flex-col", children: [
3150
3157
  isVertical && /* @__PURE__ */ jsxs(Fragment, { children: [
3158
+ footerItems.map((item) => /* @__PURE__ */ jsxs(
3159
+ "button",
3160
+ {
3161
+ onClick: () => handleClick(item.to),
3162
+ className: `${itemCls} text-gray-700 hover:bg-blue-50 hover:text-blue-700 transition-colors`,
3163
+ children: [
3164
+ iconEl(item.to),
3165
+ /* @__PURE__ */ jsx("span", { children: item.label })
3166
+ ]
3167
+ },
3168
+ item.to
3169
+ )),
3170
+ footerSections.map((s) => renderSection(s, false)),
3171
+ (footerSections.length > 0 || footerItems.length > 0) && /* @__PURE__ */ jsx("div", { className: "border-t border-white/20 my-1.5 mx-2" }),
3151
3172
  erpSections.map((s) => renderSection(s, true)),
3152
3173
  /* @__PURE__ */ jsx("div", { className: "border-t border-white/20 my-1.5 mx-2" }),
3153
3174
  topItems.map((item) => /* @__PURE__ */ jsxs("div", { children: [
@@ -3193,7 +3214,21 @@ function StartMenu({
3193
3214
  systemSections.map((s) => renderSection(s, false)),
3194
3215
  virtualSections.map((v) => renderVirtualSection(v)),
3195
3216
  /* @__PURE__ */ jsx("div", { className: "border-t border-white/20 my-1.5 mx-2" }),
3196
- erpSections.map((s) => renderSection(s, true))
3217
+ erpSections.map((s) => renderSection(s, true)),
3218
+ (footerSections.length > 0 || footerItems.length > 0) && /* @__PURE__ */ jsx("div", { className: "border-t border-white/20 my-1.5 mx-2" }),
3219
+ footerSections.map((s) => renderSection(s, false)),
3220
+ footerItems.map((item) => /* @__PURE__ */ jsxs(
3221
+ "button",
3222
+ {
3223
+ onClick: () => handleClick(item.to),
3224
+ className: `${itemCls} text-gray-700 hover:bg-blue-50 hover:text-blue-700 transition-colors`,
3225
+ children: [
3226
+ iconEl(item.to),
3227
+ /* @__PURE__ */ jsx("span", { children: item.label })
3228
+ ]
3229
+ },
3230
+ item.to
3231
+ ))
3197
3232
  ] })
3198
3233
  ] }),
3199
3234
  /* @__PURE__ */ jsx("div", { className: `${isVertical ? "border-b" : "border-t"} border-white/20 p-1`, children: /* @__PURE__ */ jsxs(
@@ -4081,7 +4116,7 @@ function MobileBottomNav({
4081
4116
  }
4082
4117
  );
4083
4118
  }
4084
- var Sidebar = lazy(() => import('./Sidebar-SHNDADVO.js'));
4119
+ var Sidebar = lazy(() => import('./Sidebar-Q3PRJ2FP.js'));
4085
4120
  function useFavorites(wallpapers) {
4086
4121
  const { prefs, save } = useShellPrefs();
4087
4122
  const favorites = prefs.favorite_pages || [];
@@ -4278,7 +4313,8 @@ function Layout({
4278
4313
  categories = startMenuCategories,
4279
4314
  notifications,
4280
4315
  search,
4281
- taskbarTrayLeft
4316
+ taskbarTrayLeft,
4317
+ showMail = true
4282
4318
  } = {}) {
4283
4319
  const bugReport = useBugReport();
4284
4320
  const { user, logout, hasAnyPerm } = useAuth();
@@ -4575,7 +4611,7 @@ function Layout({
4575
4611
  "data-menu-toggle": true,
4576
4612
  onClick: () => setMenuOpen((prev) => !prev),
4577
4613
  title: menuOpen ? "Close menu" : "Open menu",
4578
- className: `group/erp relative flex items-center gap-1.5 rounded-lg px-4 py-2 text-xs font-medium border overflow-hidden transition-all ${isVerticalTaskbar ? "w-full" : "min-w-[140px]"} ${menuOpen ? "bg-gray-200/40 border-gray-300/40 text-gray-800" : "bg-gray-50/40 border-gray-200/40 text-gray-600 hover:text-gray-800"}`,
4614
+ className: `group/erp relative flex items-center justify-center gap-1.5 rounded-lg px-4 py-2 text-xs font-medium border overflow-hidden transition-all ${isVerticalTaskbar ? "w-full" : "min-w-[140px]"} ${menuOpen ? "bg-gray-200/40 border-gray-300/40 text-gray-800" : "bg-gray-50/40 border-gray-200/40 text-gray-600 hover:text-gray-800"}`,
4579
4615
  style: { transition: "box-shadow 0.3s, border-color 0.3s" },
4580
4616
  onMouseMove: (e) => {
4581
4617
  const r = e.currentTarget.getBoundingClientRect();
@@ -4611,7 +4647,7 @@ function Layout({
4611
4647
  /* Vertical: clock + mail-connect + bell evenly spaced */
4612
4648
  /* @__PURE__ */ jsx("div", { className: "w-full px-2", children: /* @__PURE__ */ jsxs("div", { className: `flex items-center justify-center gap-2 ${taskbarPosition === "right" ? "flex-row-reverse" : ""}`, children: [
4613
4649
  /* @__PURE__ */ jsx(TaskbarClock, {}),
4614
- /* @__PURE__ */ jsx(
4650
+ showMail && /* @__PURE__ */ jsx(
4615
4651
  "button",
4616
4652
  {
4617
4653
  onClick: () => setMailConnectOpen(true),
@@ -4630,7 +4666,7 @@ function Layout({
4630
4666
  /* @__PURE__ */ jsx(TaskbarPomodoro, {}),
4631
4667
  taskbarTrayLeft,
4632
4668
  notifications && /* @__PURE__ */ jsx(NotificationBell, { ...notifications }),
4633
- /* @__PURE__ */ jsx(
4669
+ showMail && /* @__PURE__ */ jsx(
4634
4670
  "button",
4635
4671
  {
4636
4672
  onClick: () => setMailConnectOpen(true),