react-os-shell 4.2.1 → 4.3.1

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 (58) hide show
  1. package/README.md +5 -0
  2. package/dist/{Browser-JDPFFM43.js → Browser-674YMWMK.js} +6 -6
  3. package/dist/{Browser-JDPFFM43.js.map → Browser-674YMWMK.js.map} +1 -1
  4. package/dist/{Calculator-EIKUYW6O.js → Calculator-3ULKK5ZA.js} +5 -5
  5. package/dist/{Calculator-EIKUYW6O.js.map → Calculator-3ULKK5ZA.js.map} +1 -1
  6. package/dist/ConfirmDialog-XJP67AHR.js +4 -0
  7. package/dist/{ConfirmDialog-C25OKJZP.js.map → ConfirmDialog-XJP67AHR.js.map} +1 -1
  8. package/dist/{CurrencyConverter-PJUTWMCD.js → CurrencyConverter-JC2N7AY3.js} +5 -5
  9. package/dist/{CurrencyConverter-PJUTWMCD.js.map → CurrencyConverter-JC2N7AY3.js.map} +1 -1
  10. package/dist/{Documents-TIPUTUSS.js → Documents-MJKEUOOL.js} +6 -6
  11. package/dist/{Documents-TIPUTUSS.js.map → Documents-MJKEUOOL.js.map} +1 -1
  12. package/dist/{Files-Z6R3YGEB.js → Files-BTZMPTL6.js} +8 -8
  13. package/dist/{Files-Z6R3YGEB.js.map → Files-BTZMPTL6.js.map} +1 -1
  14. package/dist/{Notepad-NZXSKZ6I.js → Notepad-NGLFEJLA.js} +6 -6
  15. package/dist/{Notepad-NZXSKZ6I.js.map → Notepad-NGLFEJLA.js.map} +1 -1
  16. package/dist/{PomodoroTimer-K5NBAIVW.js → PomodoroTimer-RPCRTUKC.js} +6 -6
  17. package/dist/{PomodoroTimer-K5NBAIVW.js.map → PomodoroTimer-RPCRTUKC.js.map} +1 -1
  18. package/dist/{Preview-3F4LFED7.js → Preview-H4S427VB.js} +6 -6
  19. package/dist/{Preview-3F4LFED7.js.map → Preview-H4S427VB.js.map} +1 -1
  20. package/dist/{Sidebar-VF2IOOFX.js → Sidebar-E553SOXC.js} +4 -4
  21. package/dist/{Sidebar-VF2IOOFX.js.map → Sidebar-E553SOXC.js.map} +1 -1
  22. package/dist/{Spreadsheet-P2DB7LGI.js → Spreadsheet-2YYUKKSY.js} +6 -6
  23. package/dist/{Spreadsheet-P2DB7LGI.js.map → Spreadsheet-2YYUKKSY.js.map} +1 -1
  24. package/dist/{Stock-2XTWWH6K.js → Stock-YTQ2OYQ7.js} +5 -5
  25. package/dist/{Stock-2XTWWH6K.js.map → Stock-YTQ2OYQ7.js.map} +1 -1
  26. package/dist/{Weather-GCBITKTJ.js → Weather-4I4EFUJO.js} +5 -5
  27. package/dist/{Weather-GCBITKTJ.js.map → Weather-4I4EFUJO.js.map} +1 -1
  28. package/dist/{WorldClock-S52UINCL.js → WorldClock-7PZI7VRE.js} +5 -5
  29. package/dist/{WorldClock-S52UINCL.js.map → WorldClock-7PZI7VRE.js.map} +1 -1
  30. package/dist/apps/index.js +18 -18
  31. package/dist/chunk-3NZSR3ZG.js +20 -0
  32. package/dist/chunk-3NZSR3ZG.js.map +1 -0
  33. package/dist/{chunk-XIMGKR4G.js → chunk-ASRXGCSQ.js} +5 -5
  34. package/dist/{chunk-XIMGKR4G.js.map → chunk-ASRXGCSQ.js.map} +1 -1
  35. package/dist/{chunk-6Q4KYGMH.js → chunk-DKDD5KXG.js} +14 -3
  36. package/dist/chunk-DKDD5KXG.js.map +1 -0
  37. package/dist/chunk-K6MB36UJ.js +7 -0
  38. package/dist/{chunk-3S5NISAL.js.map → chunk-K6MB36UJ.js.map} +1 -1
  39. package/dist/{chunk-CWFH34LM.js → chunk-LBY7KH2W.js} +3 -3
  40. package/dist/{chunk-CWFH34LM.js.map → chunk-LBY7KH2W.js.map} +1 -1
  41. package/dist/{chunk-QAVN7ZV5.js → chunk-PMPJLVZV.js} +3 -3
  42. package/dist/{chunk-QAVN7ZV5.js.map → chunk-PMPJLVZV.js.map} +1 -1
  43. package/dist/{chunk-52RFL3OQ.js → chunk-QAKURGOG.js} +3 -3
  44. package/dist/{chunk-52RFL3OQ.js.map → chunk-QAKURGOG.js.map} +1 -1
  45. package/dist/{chunk-URHWXWZE.js → chunk-VA6M46NL.js} +274 -16
  46. package/dist/chunk-VA6M46NL.js.map +1 -0
  47. package/dist/{chunk-IGYB3NRR.js → chunk-YF2XNVGN.js} +3 -3
  48. package/dist/{chunk-IGYB3NRR.js.map → chunk-YF2XNVGN.js.map} +1 -1
  49. package/dist/index.d.ts +222 -1
  50. package/dist/index.js +53 -16
  51. package/dist/index.js.map +1 -1
  52. package/package.json +3 -2
  53. package/dist/ConfirmDialog-C25OKJZP.js +0 -4
  54. package/dist/chunk-3S5NISAL.js +0 -7
  55. package/dist/chunk-6Q4KYGMH.js.map +0 -1
  56. package/dist/chunk-ADJ3CERD.js +0 -31
  57. package/dist/chunk-ADJ3CERD.js.map +0 -1
  58. package/dist/chunk-URHWXWZE.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-os-shell",
3
- "version": "4.2.1",
3
+ "version": "4.3.1",
4
4
  "description": "Desktop-style React UI shell — windows, taskbar, start menu, sticky notes, frosted glass theming, and bundled apps.",
5
5
  "license": "MIT",
6
6
  "author": "Victor Y. Mau",
@@ -50,13 +50,14 @@
50
50
  "tailwindcss": ">=4",
51
51
  "xlsx": "*"
52
52
  },
53
- "dependencies": {},
54
53
  "devDependencies": {
54
+ "@types/jsdom": "^28.0.3",
55
55
  "@types/node": "^22.0.0",
56
56
  "@types/react": "^18.2.0",
57
57
  "@types/react-dom": "^18.2.0",
58
58
  "dxf-viewer": "^1.0.47",
59
59
  "esbuild": "^0.27.0",
60
+ "jsdom": "^26.1.0",
60
61
  "mammoth": "^1.8.0",
61
62
  "online-3d-viewer": "^0.18.0",
62
63
  "pdfjs-dist": "^5.6.205",
@@ -1,4 +0,0 @@
1
- export { ConfirmProvider, confirm, confirmDestructive, prompt, useConfirm } from './chunk-URHWXWZE.js';
2
- import './chunk-6Q4KYGMH.js';
3
- //# sourceMappingURL=ConfirmDialog-C25OKJZP.js.map
4
- //# sourceMappingURL=ConfirmDialog-C25OKJZP.js.map
@@ -1,7 +0,0 @@
1
- // src/version.ts
2
- var VERSION = "4.2.1" ;
3
- var APP_VERSION = VERSION;
4
-
5
- export { APP_VERSION, VERSION };
6
- //# sourceMappingURL=chunk-3S5NISAL.js.map
7
- //# sourceMappingURL=chunk-3S5NISAL.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/shell/nav-types.ts","../src/shell-config/nav.tsx","../src/utils/glass.ts"],"names":[],"mappings":"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","file":"chunk-6Q4KYGMH.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/** The host app's permission predicate — `useAuth().hasAnyPerm`. */\ntype HasAnyPerm = (perms: string[]) => boolean;\n\n/**\n * The sub-items of `item` this user may actually see.\n *\n * Every affordance for a nested group has to be derived from THIS list — the\n * chevron that advertises it, the hover handler that opens it, and the flyout\n * itself. Reading the raw `item.children` for the chevron while filtering only\n * for the flyout put an arrow on groups whose children were all\n * permission-hidden: hovering one highlighted the row and opened nothing.\n */\nexport function visibleChildren(item: NavItem, hasAnyPerm: HasAnyPerm): NavItem[] {\n return (item.children ?? []).filter(c => !c.perms || hasAnyPerm(c.perms));\n}\n\n/**\n * Whether a nav row leads anywhere for this user: either it's a plain\n * destination, or it's a group with at least one visible child. A group whose\n * children are all hidden has nothing to open — and by convention a group's\n * `to` is a synthetic key that never navigates, so there is nothing to fall\n * back to either. Such a row is dropped rather than rendered inert.\n */\nexport function isReachable(item: NavItem, hasAnyPerm: HasAnyPerm): boolean {\n return !item.children?.length || visibleChildren(item, hasAnyPerm).length > 0;\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/** Whether the \"Reduce transparency\" preference is active (root class set by\n * Layout). When on, glass surfaces render solid + blur-free — the blur is the\n * GPU-expensive part, and dropping it is the point of the setting. */\nfunction reduceTransparency(): boolean {\n try {\n return document.documentElement.classList.contains('rosh-reduce-transparency');\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 (reduceTransparency()) {\n // Reduce-transparency: a fully opaque, blur-free surface. No\n // backdrop-filter (the expensive part on low-end GPUs) and a solid\n // background so menus/popups stay legible over any wallpaper. The global\n // stylesheet rule also strips backdrop-filter, but returning a solid\n // background here is what keeps the surface from reading as washed-out\n // translucent glass with the blur gone.\n return isDarkTheme()\n ? {\n background: '#1e1e2e',\n border: '1px solid rgba(255,255,255,0.12)',\n boxShadow: '0 8px 24px rgba(0,0,0,0.5)',\n }\n : {\n background: '#ffffff',\n border: '1px solid rgba(0,0,0,0.12)',\n boxShadow: '0 8px 24px rgba(0,0,0,0.18)',\n };\n }\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"]}
@@ -1,31 +0,0 @@
1
- import { createContext, useContext } from 'react';
2
- import { jsx } from 'react/jsx-runtime';
3
-
4
- // src/shell/ShellAuth.tsx
5
- var DEFAULT = { hasAnyPerm: () => true };
6
- var ShellAuthContext = createContext(DEFAULT);
7
- function ShellAuthProvider({ value, children }) {
8
- return /* @__PURE__ */ jsx(ShellAuthContext.Provider, { value, children });
9
- }
10
- function useShellAuth() {
11
- return useContext(ShellAuthContext);
12
- }
13
-
14
- // src/contexts/AuthContext.tsx
15
- var _authBridge = {};
16
- function setShellAuthBridge(bridge) {
17
- _authBridge = bridge;
18
- }
19
- function useAuth() {
20
- const { hasAnyPerm } = useShellAuth();
21
- return {
22
- user: _authBridge.user,
23
- logout: _authBridge.logout ?? (() => {
24
- }),
25
- hasAnyPerm
26
- };
27
- }
28
-
29
- export { ShellAuthProvider, setShellAuthBridge, useAuth, useShellAuth };
30
- //# sourceMappingURL=chunk-ADJ3CERD.js.map
31
- //# sourceMappingURL=chunk-ADJ3CERD.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/shell/ShellAuth.tsx","../src/contexts/AuthContext.tsx"],"names":[],"mappings":";;;;AAqBA,IAAM,OAAA,GAAqB,EAAE,UAAA,EAAY,MAAM,IAAA,EAAK;AAEpD,IAAM,gBAAA,GAAmB,cAAyB,OAAO,CAAA;AAElD,SAAS,iBAAA,CAAkB,EAAE,KAAA,EAAO,QAAA,EAAS,EAA8C;AAChG,EAAA,uBAAO,GAAA,CAAC,gBAAA,CAAiB,QAAA,EAAjB,EAA0B,OAAe,QAAA,EAAS,CAAA;AAC5D;AAEO,SAAS,YAAA,GAA0B;AACxC,EAAA,OAAO,WAAW,gBAAgB,CAAA;AACpC;;;ACXA,IAAI,cAAyD,EAAC;AAGvD,SAAS,mBAAmB,MAAA,EAAmD;AACpF,EAAA,WAAA,GAAc,MAAA;AAChB;AAEO,SAAS,OAAA,GAAU;AACxB,EAAA,MAAM,EAAE,UAAA,EAAW,GAAI,YAAA,EAAa;AACpC,EAAA,OAAO;AAAA,IACL,MAAM,WAAA,CAAY,IAAA;AAAA,IAClB,MAAA,EAAQ,WAAA,CAAY,MAAA,KAAW,MAAM;AAAA,IAAC,CAAA,CAAA;AAAA,IACtC;AAAA,GACF;AACF","file":"chunk-ADJ3CERD.js","sourcesContent":["/**\n * Shell-side auth surface — JUST permission checking. The shell never\n * authenticates anyone or holds tokens; it only asks \"is the current user\n * allowed to see this nav item?\".\n *\n * Consumer wraps the app:\n *\n * <ShellAuthProvider value={{ hasAnyPerm: (perms) => myAuth.has(...perms) }}>\n * <Layout ... />\n * </ShellAuthProvider>\n *\n * When no provider is mounted, every permission check returns true — useful\n * for demos and consumers that don't gate their UI.\n */\nimport { createContext, useContext, type ReactNode } from 'react';\n\nexport interface ShellAuth {\n /** Returns true if the current user has any of the listed permission codes. */\n hasAnyPerm: (perms: string[]) => boolean;\n}\n\nconst DEFAULT: ShellAuth = { hasAnyPerm: () => true };\n\nconst ShellAuthContext = createContext<ShellAuth>(DEFAULT);\n\nexport function ShellAuthProvider({ value, children }: { value: ShellAuth; children: ReactNode }) {\n return <ShellAuthContext.Provider value={value}>{children}</ShellAuthContext.Provider>;\n}\n\nexport function useShellAuth(): ShellAuth {\n return useContext(ShellAuthContext);\n}\n","/**\n * INTERNAL stub — bridges legacy `useAuth()` calls inside the shell to the\n * new <ShellAuthProvider> contract.\n *\n * The shell only ever uses `hasAnyPerm` for nav-item visibility plus `user`\n * + `logout` for the profile menu. Consumers pass these in via\n * <ShellAuthProvider value={{...}}> at the App root.\n *\n * Long-term this file is removed when call sites migrate to `useShellAuth()`\n * + Layout's `user` / `onLogout` props directly.\n */\nimport { useShellAuth } from '../shell/ShellAuth';\n\ninterface ShellUser {\n email?: string;\n first_name?: string;\n last_name?: string;\n avatar_url?: string;\n}\n\nlet _authBridge: { user?: ShellUser; logout?: () => void } = {};\n\n/** Consumer registers user-identity + logout handler once at app startup. */\nexport function setShellAuthBridge(bridge: { user?: ShellUser; logout?: () => void }) {\n _authBridge = bridge;\n}\n\nexport function useAuth() {\n const { hasAnyPerm } = useShellAuth();\n return {\n user: _authBridge.user,\n logout: _authBridge.logout ?? (() => {}),\n hasAnyPerm,\n };\n}\n"]}