react-os-shell 4.79.3 → 4.82.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 (68) hide show
  1. package/README.md +18 -0
  2. package/dist/{Browser-2DFSZ3RP.js → Browser-5FNVWP3Q.js} +7 -7
  3. package/dist/{Browser-2DFSZ3RP.js.map → Browser-5FNVWP3Q.js.map} +1 -1
  4. package/dist/{Calculator-PAPSDNSJ.js → Calculator-2FCNKTPN.js} +6 -6
  5. package/dist/{Calculator-PAPSDNSJ.js.map → Calculator-2FCNKTPN.js.map} +1 -1
  6. package/dist/{CurrencyConverter-VJQI2XVV.js → CurrencyConverter-KZU7MTWE.js} +6 -6
  7. package/dist/{CurrencyConverter-VJQI2XVV.js.map → CurrencyConverter-KZU7MTWE.js.map} +1 -1
  8. package/dist/{Documents-GIP67CHC.js → Documents-ZTK6SSDK.js} +7 -7
  9. package/dist/{Documents-GIP67CHC.js.map → Documents-ZTK6SSDK.js.map} +1 -1
  10. package/dist/{Files-JAE2LL65.js → Files-4PNE3MBV.js} +12 -12
  11. package/dist/{Files-JAE2LL65.js.map → Files-4PNE3MBV.js.map} +1 -1
  12. package/dist/{Notepad-SXHXJ6PC.js → Notepad-63JJ2WB5.js} +7 -7
  13. package/dist/{Notepad-SXHXJ6PC.js.map → Notepad-63JJ2WB5.js.map} +1 -1
  14. package/dist/{PomodoroTimer-GFL4L3XS.js → PomodoroTimer-SL372V3I.js} +7 -7
  15. package/dist/{PomodoroTimer-GFL4L3XS.js.map → PomodoroTimer-SL372V3I.js.map} +1 -1
  16. package/dist/{Preview-5HFE6MCG.js → Preview-QZL2BXLP.js} +9 -9
  17. package/dist/Preview-QZL2BXLP.js.map +1 -0
  18. package/dist/{Sidebar-B3LY5T2U.js → Sidebar-GFDPPC4X.js} +24 -6
  19. package/dist/Sidebar-GFDPPC4X.js.map +1 -0
  20. package/dist/{Spreadsheet-KZLORYAA.js → Spreadsheet-RCKDHL66.js} +8 -8
  21. package/dist/{Spreadsheet-KZLORYAA.js.map → Spreadsheet-RCKDHL66.js.map} +1 -1
  22. package/dist/{Stock-WZXVQX3G.js → Stock-YDCHLKSV.js} +6 -6
  23. package/dist/{Stock-WZXVQX3G.js.map → Stock-YDCHLKSV.js.map} +1 -1
  24. package/dist/{Weather-FQ7ZVXVR.js → Weather-HM3Y5LMI.js} +6 -6
  25. package/dist/{Weather-FQ7ZVXVR.js.map → Weather-HM3Y5LMI.js.map} +1 -1
  26. package/dist/{WorldClock-XAFQ5ZQF.js → WorldClock-RXKMY3YJ.js} +6 -6
  27. package/dist/{WorldClock-XAFQ5ZQF.js.map → WorldClock-RXKMY3YJ.js.map} +1 -1
  28. package/dist/apps/index.js +19 -19
  29. package/dist/{chunk-GO2LCDHS.js → chunk-26S2Q6GA.js} +3 -3
  30. package/dist/{chunk-GO2LCDHS.js.map → chunk-26S2Q6GA.js.map} +1 -1
  31. package/dist/{chunk-EWDYCO65.js → chunk-35RG2LD2.js} +3 -3
  32. package/dist/{chunk-EWDYCO65.js.map → chunk-35RG2LD2.js.map} +1 -1
  33. package/dist/{chunk-ZO4XGUZQ.js → chunk-3TSIRZUW.js} +3 -3
  34. package/dist/{chunk-ZO4XGUZQ.js.map → chunk-3TSIRZUW.js.map} +1 -1
  35. package/dist/{chunk-BLLINYDD.js → chunk-5TLIIDRZ.js} +186 -5
  36. package/dist/chunk-5TLIIDRZ.js.map +1 -0
  37. package/dist/chunk-6XQHH7D2.js +105 -0
  38. package/dist/chunk-6XQHH7D2.js.map +1 -0
  39. package/dist/{chunk-OQ7GRU7G.js → chunk-7RUYFI6O.js} +3 -3
  40. package/dist/{chunk-OQ7GRU7G.js.map → chunk-7RUYFI6O.js.map} +1 -1
  41. package/dist/{chunk-A42MTWLI.js → chunk-F54RMKRL.js} +5 -5
  42. package/dist/{chunk-A42MTWLI.js.map → chunk-F54RMKRL.js.map} +1 -1
  43. package/dist/{chunk-TT2WNTDS.js → chunk-IZ2FABWU.js} +3 -3
  44. package/dist/{chunk-TT2WNTDS.js.map → chunk-IZ2FABWU.js.map} +1 -1
  45. package/dist/chunk-KLSUJ46L.js +7 -0
  46. package/dist/{chunk-M2IJT4OA.js.map → chunk-KLSUJ46L.js.map} +1 -1
  47. package/dist/{chunk-YZVJCHXV.js → chunk-LEMEFL6U.js} +300 -194
  48. package/dist/chunk-LEMEFL6U.js.map +1 -0
  49. package/dist/{chunk-EXSEW5F3.js → chunk-MHUVU7ZX.js} +102 -16
  50. package/dist/chunk-MHUVU7ZX.js.map +1 -0
  51. package/dist/{chunk-QJS6RBH4.js → chunk-XWLEA4B7.js} +3 -3
  52. package/dist/{chunk-QJS6RBH4.js.map → chunk-XWLEA4B7.js.map} +1 -1
  53. package/dist/{chunk-WNLPTLT6.js → chunk-ZESNO4TZ.js} +2 -2
  54. package/dist/chunk-ZESNO4TZ.js.map +1 -0
  55. package/dist/{index-BjEcKEsJ.d.ts → index-D9ZuIsBe.d.ts} +130 -1
  56. package/dist/index.d.ts +53 -3
  57. package/dist/index.js +157 -56
  58. package/dist/index.js.map +1 -1
  59. package/dist/ui/index.d.ts +1 -1
  60. package/dist/ui/index.js +4 -3
  61. package/package.json +1 -1
  62. package/dist/Preview-5HFE6MCG.js.map +0 -1
  63. package/dist/Sidebar-B3LY5T2U.js.map +0 -1
  64. package/dist/chunk-BLLINYDD.js.map +0 -1
  65. package/dist/chunk-EXSEW5F3.js.map +0 -1
  66. package/dist/chunk-M2IJT4OA.js +0 -7
  67. package/dist/chunk-WNLPTLT6.js.map +0 -1
  68. package/dist/chunk-YZVJCHXV.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/shell/Sidebar.tsx"],"names":["navSections","navIcons","sectionIcons"],"mappings":"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","file":"Sidebar-B3LY5T2U.js","sourcesContent":["/**\n * Sidebar — persistent left strip used when `prefs.layout_mode === 'sidebar'`.\n *\n * Same configuration surface as <StartMenu> (navSections, navIcons,\n * sectionIcons, categories) but rendered inline:\n * - No flyouts. Sections expand/collapse accordion-style below their\n * header, indented one step.\n * - No taskbar-anchored positioning — fixed full-height left strip,\n * width pulled from `--sidebar-width`.\n * - Right edge `rounded-r-2xl` so it matches windowed cards on the\n * right (which use `rounded-2xl`).\n *\n * Designed for small-screen layouts where flyouts would clip and where\n * keeping the menu always-visible saves a tap to switch apps.\n */\n\nimport { useEffect, useMemo, useRef, useState, isValidElement, cloneElement, type ReactElement, type ReactNode } from 'react';\nimport {\n navSections as defaultNavSections,\n navIcons as defaultNavIcons,\n sectionIcons as defaultSectionIcons,\n startMenuCategories as defaultCategories,\n isSection,\n type NavSection,\n type NavItem,\n type StartMenuCategories,\n type VirtualSection,\n} from '../shell-config/nav';\nimport { visibleChildren, isReachable, navVisible } from './nav-types';\nimport { useAuth } from '../contexts/AuthContext';\nimport { glassStyle, GLASS_INPUT_BG } from '../utils/glass';\n\ninterface SidebarProps {\n width: number;\n openPage: (path: string) => void;\n profile: any;\n user: any;\n onLogout: () => void;\n onNavigate: (path: string) => void;\n navSections?: (NavSection | NavItem)[];\n navIcons?: Record<string, ReactNode>;\n sectionIcons?: Record<string, ReactNode>;\n categories?: StartMenuCategories;\n productName?: string;\n productIcon?: string;\n}\n\nexport default function Sidebar({\n width,\n openPage,\n profile,\n user,\n onLogout,\n onNavigate,\n navSections = defaultNavSections,\n navIcons = defaultNavIcons,\n sectionIcons = defaultSectionIcons,\n categories = defaultCategories,\n productName,\n productIcon,\n}: SidebarProps) {\n const { hasAnyPerm } = useAuth();\n const erpLabels = new Set(categories.erp);\n const systemLabels = new Set(categories.system);\n const footerLabels = new Set(categories.footer ?? []);\n // Flat rows pinned to the footer (next to the profile) — rendered inline,\n // not as an accordion section. Mirrors StartMenu's `footerItems`.\n const footerItems = (categories.footerItems ?? []).filter(it => navVisible(it, hasAnyPerm));\n const virtualSections = categories.virtual ?? [];\n\n const [search, setSearch] = useState('');\n const [expanded, setExpanded] = useState<Set<string>>(new Set());\n const searchRef = useRef<HTMLInputElement>(null);\n\n const toggleExpanded = (label: string) => {\n setExpanded(prev => {\n const next = new Set(prev);\n if (next.has(label)) next.delete(label);\n else next.add(label);\n return next;\n });\n };\n\n // Top-level items vs sections, mirroring StartMenu's split.\n const topItems = navSections.filter(item => !isSection(item)) as NavItem[];\n const erpSections = navSections.filter(item => isSection(item) && erpLabels.has((item as NavSection).label)) as NavSection[];\n const systemSections = navSections.filter(item => isSection(item) && systemLabels.has((item as NavSection).label)) as NavSection[];\n const footerSections = navSections.filter(item => isSection(item) && footerLabels.has((item as NavSection).label)) as NavSection[];\n\n const getVisibleItems = (section: { items: NavItem[]; perms?: string[]; allPerms?: string[] }) => {\n if (!navVisible(section, hasAnyPerm)) return [];\n return section.items\n .filter(it => navVisible(it, hasAnyPerm))\n // Same rule as <StartMenu>: a group whose children are all\n // permission-hidden has nothing to expand, and its `to` is a synthetic\n // key that never navigates — so drop it rather than leave an inert row.\n .filter(it => isReachable(it, hasAnyPerm));\n };\n\n // Search across all items + sections (same flat list StartMenu uses).\n // Walks 3rd-level children too so nested entries are still discoverable.\n const matchTree = (it: NavItem, q: string): NavItem[] => {\n if (!navVisible(it, hasAnyPerm)) return [];\n if (!isReachable(it, hasAnyPerm)) return [];\n const hits: NavItem[] = [];\n if (it.label.toLowerCase().includes(q)) hits.push(it);\n for (const c of visibleChildren(it, hasAnyPerm)) hits.push(...matchTree(c, q));\n return hits;\n };\n const searchResults = useMemo(() => {\n if (search.length < 2) return [] as NavItem[];\n const q = search.toLowerCase();\n return [\n ...navSections.flatMap((entry) => {\n if (isSection(entry)) {\n return getVisibleItems(entry).flatMap(it => matchTree(it, q));\n }\n return matchTree(entry as NavItem, q);\n }),\n ...footerItems.flatMap(it => matchTree(it, q)),\n ];\n }, [search, navSections, footerItems, hasAnyPerm]);\n\n // Esc collapses any expanded section + clears search; '/' focuses search.\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n setExpanded(new Set());\n setSearch('');\n } else if (e.key === '/' && document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') {\n e.preventDefault();\n searchRef.current?.focus();\n }\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, []);\n\n const handleClick = (path: string) => {\n onNavigate(path);\n onPageOpenedReset();\n };\n\n // Reset search after navigating so the next visit starts clean.\n const onPageOpenedReset = () => {\n setSearch('');\n };\n\n const itemCls = 'w-full flex items-center gap-2 rounded-lg px-3 py-2 text-sm';\n const menuGlass = glassStyle();\n\n // Helper that returns the (possibly recolored) per-route icon.\n const iconEl = (to: string) => {\n const icon = navIcons[to];\n if (icon && isValidElement(icon)) {\n return cloneElement(icon as ReactElement<{ className?: string }>, {\n className: 'h-4 w-4 shrink-0 text-gray-500',\n });\n }\n return <span className=\"h-4 w-4 shrink-0\" />;\n };\n\n const secIcon = (label: string) => {\n const icon = sectionIcons[label];\n if (icon && isValidElement(icon)) {\n return cloneElement(icon as ReactElement<{ className?: string }>, {\n className: 'h-4 w-4 shrink-0 text-gray-500',\n });\n }\n return <span className=\"h-4 w-4 shrink-0\" />;\n };\n\n const renderItem = (item: NavItem) => (\n <div key={item.to}>\n <button\n onClick={() => handleClick(item.to)}\n className={`${itemCls} text-gray-700 hover:bg-blue-50 hover:text-blue-700 transition-colors`}\n >\n {iconEl(item.to)}\n <span className=\"truncate\">{item.label}</span>\n </button>\n {item.dividerAfter && <div className=\"border-t border-white/20 my-1.5 mx-2\" />}\n </div>\n );\n\n // A NavItem with children becomes its own mini-accordion, indented one step\n // further — and so does one of ITS children, for as many levels as the nav\n // data has. Recursion rather than a hand-written level: the version that\n // rendered the children of a child as plain rows silently dropped everything\n // below the third level, the same cap <StartMenu>'s flyouts used to have.\n // Expansion key is `child:<to>` so it doesn't clash with the section labels\n // in `expanded`.\n const renderNestedItem = (item: NavItem): ReactNode => {\n const kids = visibleChildren(item, hasAnyPerm).filter(k => isReachable(k, hasAnyPerm));\n if (kids.length === 0) return renderItem(item);\n const key = `child:${item.to}`;\n const isOpen = expanded.has(key);\n return (\n <div key={item.to}>\n <button\n onClick={() => toggleExpanded(key)}\n aria-expanded={isOpen}\n className={`${itemCls} text-gray-700 hover:bg-blue-50 hover:text-blue-700 transition-colors`}\n >\n {iconEl(item.to)}\n <span className=\"truncate\">{item.label}</span>\n <svg\n className={`h-3.5 w-3.5 ml-auto text-gray-500 transition-transform ${isOpen ? 'rotate-90' : ''}`}\n fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M8.25 4.5l7.5 7.5-7.5 7.5\" />\n </svg>\n </button>\n {isOpen && (\n <div className=\"pl-4 mt-0.5 mb-1 space-y-0.5\">\n {kids.map(c => renderNestedItem(c))}\n </div>\n )}\n {item.dividerAfter && <div className=\"border-t border-white/20 my-1.5 mx-2\" />}\n </div>\n );\n };\n\n const renderSectionAccordion = (section: NavSection | VirtualSection, isErp: boolean) => {\n const items = 'perms' in section\n ? getVisibleItems(section as NavSection)\n : (section as VirtualSection).items;\n if (items.length === 0) return null;\n const isOpen = expanded.has(section.label);\n return (\n <div key={section.label}>\n <button\n onClick={() => toggleExpanded(section.label)}\n aria-expanded={isOpen}\n className={`${itemCls} text-gray-700 hover:bg-blue-50 hover:text-blue-700 transition-colors`}\n >\n {'icon' in section && section.icon\n ? section.icon\n : secIcon(section.label)}\n <span className={`truncate ${isErp ? 'font-medium' : ''}`}>{section.label}</span>\n <svg\n className={`h-3.5 w-3.5 ml-auto text-gray-500 transition-transform ${isOpen ? 'rotate-90' : ''}`}\n fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M8.25 4.5l7.5 7.5-7.5 7.5\" />\n </svg>\n </button>\n {isOpen && (\n <div className=\"pl-4 mt-0.5 mb-1 space-y-0.5\">\n {items.map(it => renderNestedItem(it))}\n </div>\n )}\n {'dividerAfter' in section && section.dividerAfter && <div className=\"border-t border-white/20 my-1.5 mx-2\" />}\n </div>\n );\n };\n\n return (\n <div\n className=\"fixed top-0 left-0 bottom-0 z-[260] flex flex-col rounded-r-2xl overflow-hidden\"\n style={{ width, ...menuGlass }}\n >\n {/* Brand */}\n <div className=\"flex items-center gap-2 px-4 py-3 border-b border-white/15 shrink-0\">\n {productIcon && <img src={productIcon} alt=\"\" className=\"h-5 w-5 shrink-0 opacity-80\" />}\n <span className=\"text-sm font-semibold text-gray-800 truncate\">{productName ?? 'Apps'}</span>\n </div>\n\n {/* Search */}\n <div className=\"px-3 pt-3 pb-2 shrink-0\">\n <div className={`flex items-center gap-2 ${GLASS_INPUT_BG} rounded-lg px-2.5 py-1.5`}>\n <svg className=\"h-3.5 w-3.5 text-gray-400 shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z\" />\n </svg>\n <input\n ref={searchRef}\n value={search}\n onChange={e => setSearch(e.target.value)}\n placeholder=\"Search...\"\n className=\"flex-1 bg-transparent text-xs outline-none placeholder-gray-400\"\n />\n {search && (\n <button onClick={() => setSearch('')} className=\"text-gray-400 hover:text-gray-600 text-xs\">×</button>\n )}\n </div>\n </div>\n\n {/* Body */}\n <div className=\"flex-1 overflow-y-auto px-1 pb-1\">\n {search.length >= 2 ? (\n // Search results take over the body.\n <div>\n {searchResults.length === 0 ? (\n <div className=\"px-3 py-6 text-center text-xs text-gray-400\">No matches</div>\n ) : (\n searchResults.map(r => (\n <button\n key={r.to}\n onClick={() => handleClick(r.to)}\n className={`${itemCls} text-gray-700 hover:bg-blue-50 hover:text-blue-700 transition-colors`}\n >\n {iconEl(r.to)}\n <span className=\"truncate\">{r.label}</span>\n </button>\n ))\n )}\n </div>\n ) : (\n <>\n {/* Top-level apps */}\n {topItems.map(renderItem)}\n\n {/* Divider only when both sides have content — with every top-group\n entry moved into the footer group the top group can be empty, and\n an unconditional rule would collapse against the search box\n (mirrors StartMenu's hasAppsGroup condition). */}\n {topItems.length > 0 && (erpSections.length > 0 || systemSections.length > 0 || virtualSections.length > 0) && (\n <div className=\"border-t border-white/15 my-1.5 mx-2\" />\n )}\n\n {/* ERP sections then system sections — same order as StartMenu's vertical layout. */}\n {erpSections.map(s => renderSectionAccordion(s, true))}\n {systemSections.map(s => renderSectionAccordion(s, false))}\n {virtualSections.map(v => renderSectionAccordion(v, false))}\n {/* Footer items + sections: pinned just above the profile, divided from the rest. */}\n {(footerSections.length > 0 || footerItems.length > 0) && <div className=\"border-t border-white/15 my-1.5 mx-2\" />}\n {footerSections.map(s => renderSectionAccordion(s, false))}\n {footerItems.map(renderItem)}\n </>\n )}\n </div>\n\n {/* Profile + Sign out at the bottom — mirrors StartMenu's user row. */}\n <div className=\"border-t border-white/15 p-1 shrink-0\">\n <div\n onClick={() => handleClick('/profile')}\n className=\"rounded-lg px-2 py-1.5 flex items-center gap-2.5 hover:bg-blue-50 hover:text-blue-700 transition-colors cursor-pointer\"\n >\n {profile?.avatar_url ? (\n <img src={profile.avatar_url} alt=\"\" className=\"h-8 w-8 rounded-full object-cover border border-white/20 shrink-0\" />\n ) : (\n <div className=\"h-8 w-8 rounded-full bg-blue-100 flex items-center justify-center text-sm font-bold text-blue-700 shrink-0\">\n {(profile?.first_name?.charAt(0) || user?.email?.charAt(0) || '?').toUpperCase()}\n </div>\n )}\n <p className=\"flex-1 min-w-0 text-sm font-medium text-gray-900 truncate\">\n {profile?.first_name ? `${profile.first_name} ${profile.last_name || ''}`.trim() : user?.email}\n </p>\n <button\n onClick={e => { e.stopPropagation(); onLogout(); }}\n title=\"Sign Out\"\n className=\"shrink-0 p-1.5 rounded-md text-gray-500 hover:text-red-600 hover:bg-red-50 transition-colors\"\n >\n <svg className=\"h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15m3 0l3-3m0 0l-3-3m3 3H9\" />\n </svg>\n </button>\n </div>\n </div>\n </div>\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/shell/useIsMobile.ts","../src/shell/strings.tsx","../src/shell/PopupMenu.tsx","../src/shell/ShellPrefs.tsx"],"names":["jsx","PopupMenuItem","createContext","useContext"],"mappings":"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","file":"chunk-BLLINYDD.js","sourcesContent":["/**\n * Mobile breakpoint hook — single source of truth for \"is this a phone/tablet\n * portrait viewport?\" Drives whether <Layout> renders the desktop chrome\n * (windows / taskbar / start menu sidebar) or the <MobileAppLanding> screen\n * that points the user at the consumer-wired mobile app. A handful of\n * primitives (Modal, ResizableTable) also read it to adapt touch behaviour.\n *\n * Locked at 768 px so iPad portrait counts as mobile. Also OR's with\n * `pointer: coarse` so touch-only devices that happen to be wider (e.g. an\n * Android tablet in landscape) still get touch-appropriate UI.\n */\nimport { useSyncExternalStore } from 'react';\n\nconst QUERY = '(max-width: 767px), (pointer: coarse)';\n\nfunction getSnapshot(): boolean {\n if (typeof window === 'undefined' || !window.matchMedia) return false;\n return window.matchMedia(QUERY).matches;\n}\n\nfunction getServerSnapshot(): boolean {\n return false;\n}\n\nfunction subscribe(cb: () => void): () => void {\n if (typeof window === 'undefined' || !window.matchMedia) return () => {};\n const mql = window.matchMedia(QUERY);\n // Older Safari uses addListener; modern browsers use addEventListener.\n if (mql.addEventListener) {\n mql.addEventListener('change', cb);\n return () => mql.removeEventListener('change', cb);\n }\n mql.addListener(cb);\n return () => mql.removeListener(cb);\n}\n\nexport function useIsMobile(): boolean {\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n}\n","/**\n * ShellStrings — the shell's user-facing strings, in one typed catalog.\n *\n * Every string here was hardcoded English at its call site, which made the\n * shell untranslatable no matter what the consuming portal did. The catalog\n * is the fix's whole shape: components read strings through `useShellStrings`\n * (which works with NO provider — the English defaults are the context\n * default), and a consumer that wants another language mounts\n * `ShellStringsProvider` once with a partial override. Overrides merge per\n * SECTION, so translating the window controls does not oblige anyone to\n * translate the help viewer.\n *\n * This is deliberately not an i18n library: no message IDs, no interpolation\n * DSL, no plural rules. The shell's strings are labels and short sentences;\n * a typed object keeps them discoverable and lets TypeScript flag a\n * translation that goes stale when a string is added.\n *\n * Prop-level text (a `emptyText` prop, a `placeholder`) always wins over the\n * catalog — the catalog replaces hardcoded DEFAULTS, never a caller's words.\n *\n * Kit-safe: no window-manager import, so `react-os-shell/ui` consumers get it\n * too.\n */\nimport { createContext, useContext, useMemo, type ReactNode } from 'react';\n\nexport interface ShellStrings {\n /** Window chrome: control tooltips and the title bar's accessible name. */\n window: {\n minimize: string;\n maximize: string;\n windowed: string;\n pinOnTop: string;\n unpin: string;\n close: string;\n /** Suffix of the title bar's aria-label: `\"{title} — {windowSuffix}\"`. */\n windowSuffix: string;\n prev: string;\n next: string;\n snapLayouts: string;\n snapLeft: string;\n snapRight: string;\n snapTopLeft: string;\n snapTopRight: string;\n snapBottomLeft: string;\n snapBottomRight: string;\n };\n /** Taskbar and exposé. */\n taskbar: {\n closeWindow: string;\n offscreenHint: string;\n offscreenDot: string;\n expose: string;\n addToDesktop: string;\n removeFromDesktop: string;\n };\n /** The logout cover. */\n logout: {\n goodbye: string;\n seeYou: string;\n };\n /** About + What's New dialogs. */\n about: {\n aboutPrefix: string;\n thisApp: string;\n openSourceLicenses: string;\n whatsNew: string;\n noChangelog: string;\n };\n /** Data-display defaults (DataTable, lists). */\n table: {\n empty: string;\n loading: string;\n selectAll: string;\n selectRow: string;\n };\n /** Picker defaults (SearchableSelect, TagInput). */\n select: {\n none: string;\n noMatches: string;\n allSelected: string;\n clear: string;\n /** aria-label of a TagInput chip's remove button: `\"{remove} {label}\"`. */\n remove: string;\n };\n /** Notification bell + popup. */\n notifications: {\n title: string;\n markAllRead: string;\n dnd: string;\n dndOn: string;\n caughtUp: string;\n empty: string;\n viewAll: string;\n cardLabel: string;\n dismiss: string;\n };\n /** Form-level messages. */\n form: {\n errorSummaryTitle: string;\n };\n /** HelpCenter chrome. */\n help: {\n title: string;\n searchPlaceholder: string;\n empty: string;\n noResults: string;\n loading: string;\n pickArticle: string;\n noBody: string;\n draft: string;\n newArticle: string;\n edit: string;\n };\n}\n\nexport const DEFAULT_SHELL_STRINGS: ShellStrings = {\n window: {\n minimize: 'Minimize',\n maximize: 'Maximize',\n windowed: 'Windowed',\n pinOnTop: 'Pin on top',\n unpin: 'Unpin from top',\n close: 'Close',\n windowSuffix: 'window',\n prev: 'Prev',\n next: 'Next',\n snapLayouts: 'Snap layouts',\n snapLeft: 'Snap left half',\n snapRight: 'Snap right half',\n snapTopLeft: 'Snap top-left quarter',\n snapTopRight: 'Snap top-right quarter',\n snapBottomLeft: 'Snap bottom-left quarter',\n snapBottomRight: 'Snap bottom-right quarter',\n },\n taskbar: {\n closeWindow: 'Close window',\n offscreenHint: 'This window is off screen — click to bring it back',\n offscreenDot: 'Off screen — click to bring this window back',\n expose: 'Exposé — show all open windows as thumbnails',\n addToDesktop: 'Add to desktop',\n removeFromDesktop: 'Remove from desktop',\n },\n logout: {\n goodbye: 'Goodbye',\n seeYou: 'See you next time',\n },\n about: {\n aboutPrefix: 'About',\n thisApp: 'this app',\n openSourceLicenses: 'Open Source Licenses',\n whatsNew: \"What's New\",\n noChangelog: 'No changelog available.',\n },\n table: {\n empty: 'Nothing to show',\n loading: 'Loading',\n selectAll: 'Select all rows',\n selectRow: 'Select row',\n },\n select: {\n none: '— None —',\n noMatches: 'No matches',\n allSelected: 'All options selected',\n clear: 'Clear selection',\n remove: 'Remove',\n },\n notifications: {\n title: 'Notifications',\n markAllRead: 'Mark all read',\n dnd: 'Do not disturb',\n dndOn: 'Do not disturb is on',\n caughtUp: 'All caught up',\n empty: 'No notifications yet',\n viewAll: 'View all notifications',\n cardLabel: 'Notification',\n dismiss: 'Dismiss notification',\n },\n form: {\n errorSummaryTitle: 'There is a problem',\n },\n help: {\n title: 'Help',\n searchPlaceholder: 'Search help…',\n empty: 'No help articles yet.',\n noResults: 'No articles match your search.',\n loading: 'Loading…',\n pickArticle: 'Pick a help article from the left.',\n noBody: 'This article has no body yet.',\n draft: 'Draft',\n newArticle: '+ New',\n edit: 'Edit',\n },\n};\n\n/** A per-section partial: override any subset of a section's strings. */\nexport type ShellStringsOverride = {\n [S in keyof ShellStrings]?: Partial<ShellStrings[S]>;\n};\n\nconst ShellStringsContext = createContext<ShellStrings>(DEFAULT_SHELL_STRINGS);\n\n/**\n * Mount once, near the top of the app. `value` is a partial — sections and\n * keys you do not translate keep their English defaults, so a catalog never\n * breaks by falling behind a release.\n */\nexport function ShellStringsProvider({ value, children }: { value: ShellStringsOverride; children: ReactNode }) {\n const merged = useMemo<ShellStrings>(() => {\n const out = {} as ShellStrings;\n for (const key of Object.keys(DEFAULT_SHELL_STRINGS) as (keyof ShellStrings)[]) {\n out[key] = { ...DEFAULT_SHELL_STRINGS[key], ...(value[key] ?? {}) } as never;\n }\n return out;\n }, [value]);\n return <ShellStringsContext.Provider value={merged}>{children}</ShellStringsContext.Provider>;\n}\n\n/** The active catalog — English defaults when no provider is mounted. */\nexport function useShellStrings(): ShellStrings {\n return useContext(ShellStringsContext);\n}\n","import { forwardRef, useEffect, useRef, type ReactNode, type CSSProperties } from 'react';\nimport { createPortal } from 'react-dom';\nimport { glassStyle, GLASS_DIVIDER } from '../utils/glass';\n\n/**\n * Unified popup menu component — used for all context menus, dropdowns, and flyouts.\n * Reads --menu-density CSS variable: 'tight', 'normal' (default), or 'large'.\n */\n\nexport interface PopupMenuProps {\n children: ReactNode;\n style?: CSSProperties;\n className?: string;\n onClose?: () => void;\n minWidth?: number;\n /** Render into document.body instead of in place. Required when the menu\n * is opened from INSIDE a window: the window panel is a transformed /\n * backdrop-filtered `overflow-hidden` container, which both re-anchors\n * `position: fixed` descendants to itself and clips them — a menu\n * positioned at viewport coordinates ends up offset or invisible.\n * Portaling restores true viewport positioning. */\n portal?: boolean;\n}\n\nfunction getDensity(): 'tight' | 'normal' | 'large' {\n return (getComputedStyle(document.documentElement).getPropertyValue('--menu-density')?.trim() as any) || 'normal';\n}\n\n/** Container for a popup menu — auto-clamps to stay within viewport */\nexport function PopupMenu({ children, style, className = '', onClose, minWidth = 180, portal = false }: PopupMenuProps) {\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!onClose) return;\n const handleClick = (e: PointerEvent | MouseEvent) => {\n if ((e.target as HTMLElement).closest('[data-menu-toggle]')) return;\n if (ref.current && !ref.current.contains(e.target as Node)) onClose();\n };\n const handleKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); };\n window.addEventListener('pointerdown', handleClick);\n window.addEventListener('keydown', handleKey);\n return () => { window.removeEventListener('pointerdown', handleClick); window.removeEventListener('keydown', handleKey); };\n }, [onClose]);\n\n // After render, clamp position to viewport boundaries\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n requestAnimationFrame(() => {\n const rect = el.getBoundingClientRect();\n const margin = 8;\n // Clamp right edge\n if (rect.right > window.innerWidth - margin) {\n const overflow = rect.right - window.innerWidth + margin;\n if (el.style.left) {\n el.style.left = `${parseFloat(el.style.left) - overflow}px`;\n } else if (!el.style.right) {\n el.style.left = `${rect.left - overflow}px`;\n }\n }\n // Clamp left edge\n if (rect.left < margin) {\n if (el.style.left) {\n el.style.left = `${margin}px`;\n } else if (el.style.right) {\n el.style.right = `${window.innerWidth - rect.width - margin}px`;\n }\n }\n // Clamp bottom edge\n if (rect.bottom > window.innerHeight - margin) {\n const overflow = rect.bottom - window.innerHeight + margin;\n if (el.style.top) {\n el.style.top = `${parseFloat(el.style.top) - overflow}px`;\n } else if (el.style.bottom) {\n // Already anchored to bottom, just clamp\n el.style.bottom = `${margin}px`;\n } else {\n el.style.top = `${rect.top - overflow}px`;\n }\n }\n // Clamp top edge\n if (rect.top < margin) {\n if (el.style.top) {\n el.style.top = `${margin}px`;\n } else if (el.style.bottom) {\n el.style.bottom = `${window.innerHeight - rect.height - margin}px`;\n }\n }\n });\n });\n\n const density = getDensity();\n\n const menu = (\n <div ref={ref}\n className={`fixed z-[400] rounded-2xl ${density === 'tight' ? 'py-1' : density === 'large' ? 'py-2' : 'py-1.5'} ${className}`}\n style={{ minWidth, animation: 'popup-in 0.12s ease-out', ...glassStyle(), ...style }}>\n {children}\n <style>{`@keyframes popup-in { from { opacity: 0; transform: scale(0.96); } to { opacity: 1; transform: scale(1); } }`}</style>\n </div>\n );\n\n return portal ? createPortal(menu, document.body) : menu;\n}\n\n/** A clickable menu item */\nexport interface PopupMenuItemProps {\n onClick?: () => void;\n children: ReactNode;\n className?: string;\n danger?: boolean;\n disabled?: boolean;\n /**\n * The menu semantics, when this item is part of one.\n *\n * A context menu on the desktop is a list of buttons and needs none of this;\n * a dropdown attached to a trigger is a `menu` whose items are `menuitem`s\n * with one tab stop between them. Both draw the same item, so the styling\n * lives here rather than being copied into whichever one is newer.\n */\n role?: 'menuitem';\n tabIndex?: number;\n id?: string;\n onMouseEnter?: () => void;\n}\n\n/**\n * `forwardRef`, not a `ref` prop.\n *\n * Taking `ref` as an ordinary prop is React 19 only. This package's peer range\n * is `react: \">=18\"`, and React 18 strips `ref` from a function component's\n * props and warns — so on an 18 consumer the ref would silently never attach,\n * `DropdownMenu`'s `itemRefs` would all be null, and its arrow keys would move\n * `tabIndex` while DOM focus stayed put. A keyboard-dead menu with no error.\n */\nexport const PopupMenuItem = forwardRef<HTMLButtonElement, PopupMenuItemProps>(function PopupMenuItem({\n onClick, children, className = '', danger, disabled,\n role, tabIndex, id, onMouseEnter,\n}, ref) {\n const density = getDensity();\n // Vertical gap between items. `normal` sits a little tighter than the raw\n // size padding; `large` adds a bit more room. Floored at the tight value so\n // the reduced `normal` never drops below `tight` at the smallest menu size.\n const itemPadY = density === 'tight' ? '0.25rem'\n : density === 'large' ? '0.6rem'\n : 'max(0.25rem, calc(var(--menu-padding-y, 0.5rem) - 0.1rem))';\n return (\n <button\n ref={ref}\n id={id}\n role={role}\n tabIndex={tabIndex}\n onClick={onClick}\n onMouseEnter={onMouseEnter}\n disabled={disabled}\n className={`w-full flex items-center gap-2 text-left transition-colors rounded-lg mx-auto\n ${danger ? 'text-red-600 hover:bg-red-50' : 'text-gray-700 hover:bg-blue-50 hover:text-blue-700'}\n ${disabled ? 'opacity-40 cursor-not-allowed' : ''}\n ${className}`}\n style={{\n width: 'calc(100% - 8px)',\n marginLeft: 4,\n marginRight: 4,\n fontSize: 'var(--menu-font-size, 14px)',\n paddingLeft: 'var(--menu-padding-x, 1rem)',\n paddingRight: 'var(--menu-padding-x, 1rem)',\n paddingTop: itemPadY,\n paddingBottom: itemPadY,\n }}\n >\n {children}\n </button>\n );\n});\n\n/** A divider line between menu items */\nexport function PopupMenuDivider() {\n const density = getDensity();\n return <div className={`border-t ${GLASS_DIVIDER} ${density === 'tight' ? 'my-0.5' : density === 'large' ? 'my-1.5' : 'my-1'} mx-3`} />;\n}\n\n/** A section header label */\nexport function PopupMenuLabel({ children }: { children: ReactNode }) {\n const density = getDensity();\n const labelPadY = density === 'tight' ? '0.125rem' : density === 'large' ? '0.375rem' : '0.25rem';\n return (\n <div\n className=\"text-[10px] font-medium text-gray-400 uppercase tracking-wider\"\n style={{\n paddingLeft: 'var(--menu-padding-x, 1rem)',\n paddingRight: 'var(--menu-padding-x, 1rem)',\n paddingTop: labelPadY,\n paddingBottom: labelPadY,\n }}\n >\n {children}\n </div>\n );\n}\n\n/** An icon helper */\nexport function MenuIcon({ d, className = 'h-4 w-4 text-gray-400' }: { d: string; className?: string }) {\n return (\n <svg className={className} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d={d} />\n </svg>\n );\n}\n","/**\n * Shell-side user-preferences surface — the package never owns where prefs\n * live. The consumer supplies a hook returning the current prefs object plus\n * a save callback; the shell reads keys it knows about (theme,\n * taskbar_position, taskbar_size, world_clocks, favorite_documents,\n * desktop_folders, desktop_snap, notepad_notes, …) and patches them.\n *\n * When no provider is mounted, the shell falls back to localStorage scoped\n * by `storageKey` — so the package works out of the box for a backend-less\n * consumer.\n */\nimport { createContext, useContext, useState, useCallback, type ReactNode } from 'react';\n\nexport interface ShellPrefsAdapter {\n /** The current prefs object. The shell reads its known keys directly off\n * this; consumer-private keys are ignored. */\n prefs: Record<string, any>;\n /** Patch a subset of prefs. The shell calls this with shallow diffs. */\n save: (patch: Record<string, any>) => Promise<void> | void;\n}\n\nconst ShellPrefsContext = createContext<ShellPrefsAdapter | null>(null);\n\nexport function ShellPrefsProvider({\n value,\n children,\n}: { value: ShellPrefsAdapter; children: ReactNode }) {\n return <ShellPrefsContext.Provider value={value}>{children}</ShellPrefsContext.Provider>;\n}\n\n/** Default localStorage-backed adapter — useful when the consumer doesn't\n * ship a backend. Pass the result into <ShellPrefsProvider value={…}>.\n *\n * `defaults` are merged behind whatever's already stored, so they only\n * apply for keys the user hasn't set yet. Useful for opting out of bundled\n * features (e.g. `{ show_desktop_version: false }`). */\nexport function useLocalStoragePrefs(\n storageKey = 'react-os-shell:prefs',\n defaults?: Record<string, any>,\n): ShellPrefsAdapter {\n const [prefs, setPrefs] = useState<Record<string, any>>(() => {\n try {\n const stored = JSON.parse(localStorage.getItem(storageKey) || '{}');\n return { ...(defaults ?? {}), ...stored };\n } catch { return { ...(defaults ?? {}) }; }\n });\n const save = useCallback((patch: Record<string, any>) => {\n setPrefs(prev => {\n const next = { ...prev, ...patch };\n try { localStorage.setItem(storageKey, JSON.stringify(next)); } catch {}\n return next;\n });\n }, [storageKey]);\n return { prefs, save };\n}\n\n/** Returns the active prefs adapter. When no provider is mounted, returns a\n * no-op adapter that reads as empty and silently drops saves — components\n * still render, but persistence is a no-op. */\nexport function useShellPrefs(): ShellPrefsAdapter {\n const ctx = useContext(ShellPrefsContext);\n if (ctx) return ctx;\n return { prefs: {}, save: () => {} };\n}\n"]}