react-os-shell 0.4.0 → 0.5.0

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-6JQTSHQF.js → Browser-PIKJVKWD.js} +4 -4
  2. package/dist/{Browser-6JQTSHQF.js.map → Browser-PIKJVKWD.js.map} +1 -1
  3. package/dist/{Calculator-6ANBG6S2.js → Calculator-3RMMEJOR.js} +5 -5
  4. package/dist/{Calculator-6ANBG6S2.js.map → Calculator-3RMMEJOR.js.map} +1 -1
  5. package/dist/{Calendar-R4IBIPIU.js → Calendar-YI2OPWBN.js} +4 -4
  6. package/dist/{Calendar-R4IBIPIU.js.map → Calendar-YI2OPWBN.js.map} +1 -1
  7. package/dist/{CurrencyConverter-RVLGYNDE.js → CurrencyConverter-QW6RYH3K.js} +5 -5
  8. package/dist/{CurrencyConverter-RVLGYNDE.js.map → CurrencyConverter-QW6RYH3K.js.map} +1 -1
  9. package/dist/{Documents-AUK2YPDI.js → Documents-U3SM3I5H.js} +4 -4
  10. package/dist/{Documents-AUK2YPDI.js.map → Documents-U3SM3I5H.js.map} +1 -1
  11. package/dist/{Email-7FJHS6Y7.js → Email-F7P3EDVG.js} +4 -4
  12. package/dist/{Email-7FJHS6Y7.js.map → Email-F7P3EDVG.js.map} +1 -1
  13. package/dist/Files-NR2ZZRGK.js +11 -0
  14. package/dist/{Files-PGN4HKTC.js.map → Files-NR2ZZRGK.js.map} +1 -1
  15. package/dist/{Minesweeper-ZDK33A6S.js → Minesweeper-GG66GIOY.js} +4 -4
  16. package/dist/{Minesweeper-ZDK33A6S.js.map → Minesweeper-GG66GIOY.js.map} +1 -1
  17. package/dist/{Notepad-SRHBJ75G.js → Notepad-OSHH77DS.js} +4 -4
  18. package/dist/{Notepad-SRHBJ75G.js.map → Notepad-OSHH77DS.js.map} +1 -1
  19. package/dist/{PomodoroTimer-OJMQVA4G.js → PomodoroTimer-LTXRM4QE.js} +5 -5
  20. package/dist/{PomodoroTimer-OJMQVA4G.js.map → PomodoroTimer-LTXRM4QE.js.map} +1 -1
  21. package/dist/Preview-Z2ANAYNJ.js +8 -0
  22. package/dist/{Preview-Z5HQ4O3X.js.map → Preview-Z2ANAYNJ.js.map} +1 -1
  23. package/dist/{Sidebar-4V6NQROQ.js → Sidebar-SHNDADVO.js} +59 -17
  24. package/dist/Sidebar-SHNDADVO.js.map +1 -0
  25. package/dist/Spreadsheet-MYOVKLI2.js +6 -0
  26. package/dist/{Spreadsheet-UWKFN6PH.js.map → Spreadsheet-MYOVKLI2.js.map} +1 -1
  27. package/dist/{Weather-ZYNKEAOJ.js → Weather-5HJCLITK.js} +5 -5
  28. package/dist/{Weather-ZYNKEAOJ.js.map → Weather-5HJCLITK.js.map} +1 -1
  29. package/dist/{WorldClock-A6P3MXEI.js → WorldClock-IJLE7IOF.js} +5 -5
  30. package/dist/{WorldClock-A6P3MXEI.js.map → WorldClock-IJLE7IOF.js.map} +1 -1
  31. package/dist/apps/index.js +20 -20
  32. package/dist/{chunk-GI7ABQPU.js → chunk-2TNV3ODP.js} +3 -3
  33. package/dist/{chunk-GI7ABQPU.js.map → chunk-2TNV3ODP.js.map} +1 -1
  34. package/dist/{chunk-6YY6A6SV.js → chunk-6FNC3APL.js} +3 -3
  35. package/dist/{chunk-6YY6A6SV.js.map → chunk-6FNC3APL.js.map} +1 -1
  36. package/dist/{chunk-NRT2CU5Q.js → chunk-BRWWUKPE.js} +3 -3
  37. package/dist/{chunk-NRT2CU5Q.js.map → chunk-BRWWUKPE.js.map} +1 -1
  38. package/dist/{chunk-Z4JTKA7I.js → chunk-JKPSKZGZ.js} +3 -3
  39. package/dist/{chunk-Z4JTKA7I.js.map → chunk-JKPSKZGZ.js.map} +1 -1
  40. package/dist/{chunk-LZCEK7JF.js → chunk-K5ZMTKZC.js} +4 -4
  41. package/dist/{chunk-LZCEK7JF.js.map → chunk-K5ZMTKZC.js.map} +1 -1
  42. package/dist/{chunk-SSA762W5.js → chunk-YJONGQLG.js} +2 -2
  43. package/dist/chunk-YJONGQLG.js.map +1 -0
  44. package/dist/{chunk-5PZGJUQX.js → chunk-YSMCY46G.js} +4 -4
  45. package/dist/{chunk-5PZGJUQX.js.map → chunk-YSMCY46G.js.map} +1 -1
  46. package/dist/index.d.ts +3 -0
  47. package/dist/index.js +116 -31
  48. package/dist/index.js.map +1 -1
  49. package/package.json +1 -1
  50. package/dist/Files-PGN4HKTC.js +0 -11
  51. package/dist/Preview-Z5HQ4O3X.js +0 -8
  52. package/dist/Sidebar-4V6NQROQ.js.map +0 -1
  53. package/dist/Spreadsheet-UWKFN6PH.js +0 -6
  54. package/dist/chunk-SSA762W5.js.map +0 -1
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-LZCEK7JF.js';
9
+ import { PREVIEW_OPENED_EVENT, openPreviewFile } from './chunk-K5ZMTKZC.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-NRT2CU5Q.js';
11
+ import { setPdfPreview } from './chunk-BRWWUKPE.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-6YY6A6SV.js';
16
- import { useWindowManager, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, ModalActions, useIsMobile, useModalActive, client_default, LoadingSpinner, WINDOW_REGISTRY, isPageEntry, ThumbCard, activateModal } from './chunk-GI7ABQPU.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-GI7ABQPU.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';
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-SSA762W5.js';
23
- export { GLASS_DIVIDER, GLASS_INPUT_BG, glassStyle, setShellNavIcons } from './chunk-SSA762W5.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';
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.4.0" ;
918
+ var VERSION = "0.5.0" ;
919
919
  var APP_VERSION = VERSION;
920
920
 
921
921
  // src/changelog.ts
@@ -2895,17 +2895,25 @@ function StartMenu({
2895
2895
  const isMobile = useIsMobile();
2896
2896
  const [hoveredSection, setHoveredSection] = useState(null);
2897
2897
  const [hoveredY, setHoveredY] = useState(0);
2898
+ const [hoveredChild, setHoveredChild] = useState(null);
2899
+ const [hoveredChildY, setHoveredChildY] = useState(0);
2898
2900
  const [search, setSearch] = useState("");
2899
2901
  const [searchIdx, setSearchIdx] = useState(0);
2900
2902
  const menuRef = useRef(null);
2903
+ const flyoutRef = useRef(null);
2901
2904
  const hoverTimeout = useRef();
2905
+ const childHoverTimeout = useRef();
2902
2906
  useEffect(() => {
2903
2907
  if (!open) {
2904
2908
  setSearch("");
2905
2909
  setHoveredSection(null);
2910
+ setHoveredChild(null);
2906
2911
  setSearchIdx(0);
2907
2912
  }
2908
2913
  }, [open]);
2914
+ useEffect(() => {
2915
+ setHoveredChild(null);
2916
+ }, [hoveredSection]);
2909
2917
  useEffect(() => {
2910
2918
  if (!open) return;
2911
2919
  const handler = (e) => {
@@ -2929,18 +2937,20 @@ function StartMenu({
2929
2937
  };
2930
2938
  if (isMobile) {
2931
2939
  const allItems = [];
2940
+ const pushItem = (it, sectionLabel) => {
2941
+ if (it.perms && !hasAnyPerm(it.perms)) return;
2942
+ allItems.push({ item: it, sectionLabel });
2943
+ if (it.children) {
2944
+ for (const c of it.children) pushItem(c, it.label);
2945
+ }
2946
+ };
2932
2947
  for (const entry of navSections2) {
2933
2948
  if (isSection(entry)) {
2934
2949
  const sec = entry;
2935
2950
  if (sec.perms && !hasAnyPerm(sec.perms)) continue;
2936
- for (const it of sec.items) {
2937
- if (it.perms && !hasAnyPerm(it.perms)) continue;
2938
- allItems.push({ item: it, sectionLabel: sec.label });
2939
- }
2951
+ for (const it of sec.items) pushItem(it, sec.label);
2940
2952
  } else {
2941
- const it = entry;
2942
- if (it.perms && !hasAnyPerm(it.perms)) continue;
2943
- allItems.push({ item: it });
2953
+ pushItem(entry);
2944
2954
  }
2945
2955
  }
2946
2956
  const filtered = search.length >= 1 ? allItems.filter(({ item }) => item.label.toLowerCase().includes(search.toLowerCase())) : allItems;
@@ -2994,11 +3004,23 @@ function StartMenu({
2994
3004
  const erpSections = navSections2.filter((item) => isSection(item) && erpLabels.has(item.label));
2995
3005
  const systemSections = navSections2.filter((item) => isSection(item) && systemLabels.has(item.label));
2996
3006
  const getVisibleItems = (section) => section.items.filter((item) => !item.perms || hasAnyPerm(item.perms));
3007
+ const matchTree = (it, sectionLabel) => {
3008
+ if (it.perms && !hasAnyPerm(it.perms)) return [];
3009
+ const hits = [];
3010
+ if (it.label.toLowerCase().includes(search.toLowerCase())) {
3011
+ hits.push({ ...it, section: sectionLabel });
3012
+ }
3013
+ if (it.children) {
3014
+ for (const c of it.children) hits.push(...matchTree(c, it.label));
3015
+ }
3016
+ return hits;
3017
+ };
2997
3018
  const searchResults = search.length >= 2 ? navSections2.flatMap((item) => {
2998
3019
  if (isSection(item)) {
2999
- return item.items.filter((i) => (!i.perms || hasAnyPerm(i.perms)) && i.label.toLowerCase().includes(search.toLowerCase())).map((i) => ({ ...i, section: item.label }));
3020
+ const sec = item;
3021
+ return sec.items.flatMap((i) => matchTree(i, sec.label));
3000
3022
  }
3001
- return item.label.toLowerCase().includes(search.toLowerCase()) ? [{ ...item, section: "" }] : [];
3023
+ return matchTree(item, "");
3002
3024
  }) : [];
3003
3025
  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 };
3004
3026
  const iconEl = (path) => {
@@ -3204,28 +3226,91 @@ function StartMenu({
3204
3226
  hoveredSection && flyoutItems.length > 0 && search.length < 2 && /* @__PURE__ */ jsx(
3205
3227
  "div",
3206
3228
  {
3229
+ ref: flyoutRef,
3207
3230
  className: `fixed ${sizeConfig.fw} rounded-2xl overflow-hidden`,
3208
3231
  style: { left: menuRef.current ? menuRef.current.getBoundingClientRect().right + 4 : menuWidth + 12, top: flyoutTop, animation: "submenu-in 0.1s ease-out", ...menuGlass },
3209
3232
  onMouseEnter: () => clearTimeout(hoverTimeout.current),
3210
3233
  onMouseLeave: () => {
3211
- hoverTimeout.current = setTimeout(() => setHoveredSection(null), 200);
3234
+ hoverTimeout.current = setTimeout(() => {
3235
+ setHoveredSection(null);
3236
+ setHoveredChild(null);
3237
+ }, 200);
3212
3238
  },
3213
- children: /* @__PURE__ */ jsx("div", { className: "py-1 px-1", children: flyoutItems.map((item) => /* @__PURE__ */ jsxs("div", { children: [
3214
- /* @__PURE__ */ jsxs(
3215
- "button",
3239
+ children: /* @__PURE__ */ jsx("div", { className: "py-1 px-1", children: flyoutItems.map((item) => {
3240
+ const hasChildren = !!item.children && item.children.length > 0;
3241
+ const isChildHovered = hoveredChild === item.to;
3242
+ return /* @__PURE__ */ jsxs(
3243
+ "div",
3216
3244
  {
3217
- onClick: () => handleClick(item.to),
3218
- className: `${itemCls} text-gray-700 hover:bg-blue-50 hover:text-blue-700 transition-colors`,
3245
+ onMouseEnter: hasChildren ? (e) => {
3246
+ clearTimeout(childHoverTimeout.current);
3247
+ const rect = e.currentTarget.getBoundingClientRect();
3248
+ setHoveredChildY(rect.top + rect.height / 2);
3249
+ setHoveredChild(item.to);
3250
+ } : () => {
3251
+ childHoverTimeout.current = setTimeout(() => setHoveredChild(null), 200);
3252
+ },
3219
3253
  children: [
3220
- iconEl(item.to),
3221
- /* @__PURE__ */ jsx("span", { children: item.label })
3254
+ /* @__PURE__ */ jsxs(
3255
+ "button",
3256
+ {
3257
+ onClick: () => handleClick(item.to),
3258
+ className: `${itemCls} transition-colors ${isChildHovered ? "bg-blue-50 text-blue-700" : "text-gray-700 hover:bg-blue-50 hover:text-blue-700"}`,
3259
+ children: [
3260
+ iconEl(item.to),
3261
+ /* @__PURE__ */ jsx("span", { children: item.label }),
3262
+ hasChildren && /* @__PURE__ */ jsx("svg", { className: "h-3.5 w-3.5 ml-auto text-gray-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8.25 4.5l7.5 7.5-7.5 7.5" }) })
3263
+ ]
3264
+ }
3265
+ ),
3266
+ item.dividerAfter && /* @__PURE__ */ jsx("div", { className: "border-t border-white/20 my-1.5 mx-2" })
3222
3267
  ]
3223
- }
3224
- ),
3225
- item.dividerAfter && /* @__PURE__ */ jsx("div", { className: "border-t border-white/20 my-1.5 mx-2" })
3226
- ] }, item.to)) })
3268
+ },
3269
+ item.to
3270
+ );
3271
+ }) })
3227
3272
  }
3228
- )
3273
+ ),
3274
+ (() => {
3275
+ if (search.length >= 2 || !hoveredChild) return null;
3276
+ const parent = flyoutItems.find((it) => it.to === hoveredChild);
3277
+ const kids = (parent?.children ?? []).filter((c) => !c.perms || hasAnyPerm(c.perms));
3278
+ if (!parent || kids.length === 0) return null;
3279
+ const flyoutRect = flyoutRef.current?.getBoundingClientRect();
3280
+ const subLeft = flyoutRect ? flyoutRect.right + 4 : 0;
3281
+ const subH = kids.length * sizeConfig.itemH + 12;
3282
+ let subTop = hoveredChildY - subH / 2;
3283
+ if (subTop < minTop) subTop = minTop;
3284
+ if (subTop + subH > maxBottom) subTop = maxBottom - subH;
3285
+ return /* @__PURE__ */ jsx(
3286
+ "div",
3287
+ {
3288
+ className: `fixed ${sizeConfig.fw} rounded-2xl overflow-hidden`,
3289
+ style: { left: subLeft, top: subTop, animation: "submenu-in 0.1s ease-out", ...menuGlass },
3290
+ onMouseEnter: () => {
3291
+ clearTimeout(hoverTimeout.current);
3292
+ clearTimeout(childHoverTimeout.current);
3293
+ },
3294
+ onMouseLeave: () => {
3295
+ childHoverTimeout.current = setTimeout(() => setHoveredChild(null), 200);
3296
+ },
3297
+ children: /* @__PURE__ */ jsx("div", { className: "py-1 px-1", children: kids.map((child) => /* @__PURE__ */ jsxs("div", { children: [
3298
+ /* @__PURE__ */ jsxs(
3299
+ "button",
3300
+ {
3301
+ onClick: () => handleClick(child.to),
3302
+ className: `${itemCls} text-gray-700 hover:bg-blue-50 hover:text-blue-700 transition-colors`,
3303
+ children: [
3304
+ iconEl(child.to),
3305
+ /* @__PURE__ */ jsx("span", { children: child.label })
3306
+ ]
3307
+ }
3308
+ ),
3309
+ child.dividerAfter && /* @__PURE__ */ jsx("div", { className: "border-t border-white/20 my-1.5 mx-2" })
3310
+ ] }, child.to)) })
3311
+ }
3312
+ );
3313
+ })()
3229
3314
  ] }),
3230
3315
  /* @__PURE__ */ jsx("style", { children: `
3231
3316
  @keyframes menu-in { from { opacity: 0; transform: scale(0.95) translateY(8px); } to { opacity: 1; transform: scale(1) translateY(0); } }
@@ -3996,7 +4081,7 @@ function MobileBottomNav({
3996
4081
  }
3997
4082
  );
3998
4083
  }
3999
- var Sidebar = lazy(() => import('./Sidebar-4V6NQROQ.js'));
4084
+ var Sidebar = lazy(() => import('./Sidebar-SHNDADVO.js'));
4000
4085
  function useFavorites(wallpapers) {
4001
4086
  const { prefs, save } = useShellPrefs();
4002
4087
  const favorites = prefs.favorite_pages || [];