react-os-shell 3.8.5 → 3.9.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-Z6EGTCHG.js +7 -0
  2. package/dist/{Browser-46EJUBW5.js.map → Browser-Z6EGTCHG.js.map} +1 -1
  3. package/dist/{Calculator-5E7C5YLX.js → Calculator-2HX5CQHC.js} +4 -4
  4. package/dist/{Calculator-5E7C5YLX.js.map → Calculator-2HX5CQHC.js.map} +1 -1
  5. package/dist/{CurrencyConverter-27Q7CDIJ.js → CurrencyConverter-CCYVPA2T.js} +4 -4
  6. package/dist/{CurrencyConverter-27Q7CDIJ.js.map → CurrencyConverter-CCYVPA2T.js.map} +1 -1
  7. package/dist/{Documents-U7KFKFNT.js → Documents-W3WVPHAM.js} +4 -4
  8. package/dist/{Documents-U7KFKFNT.js.map → Documents-W3WVPHAM.js.map} +1 -1
  9. package/dist/Files-7TGZSJHD.js +12 -0
  10. package/dist/{Files-ZBUFKYWD.js.map → Files-7TGZSJHD.js.map} +1 -1
  11. package/dist/{Notepad-5OGGCJGO.js → Notepad-CVKD2JFL.js} +4 -4
  12. package/dist/{Notepad-5OGGCJGO.js.map → Notepad-CVKD2JFL.js.map} +1 -1
  13. package/dist/{PomodoroTimer-2FXTKPCH.js → PomodoroTimer-CHR6G3HN.js} +5 -5
  14. package/dist/{PomodoroTimer-2FXTKPCH.js.map → PomodoroTimer-CHR6G3HN.js.map} +1 -1
  15. package/dist/Preview-DVXWKJYX.js +8 -0
  16. package/dist/{Preview-JA4S64C6.js.map → Preview-DVXWKJYX.js.map} +1 -1
  17. package/dist/Spreadsheet-26YE7FV7.js +7 -0
  18. package/dist/{Spreadsheet-G6CQ6FU4.js.map → Spreadsheet-26YE7FV7.js.map} +1 -1
  19. package/dist/{Stock-YZFDBHRV.js → Stock-ALK2CV7R.js} +4 -4
  20. package/dist/{Stock-YZFDBHRV.js.map → Stock-ALK2CV7R.js.map} +1 -1
  21. package/dist/{Weather-ECNKTQWZ.js → Weather-CW5JMDKQ.js} +4 -4
  22. package/dist/{Weather-ECNKTQWZ.js.map → Weather-CW5JMDKQ.js.map} +1 -1
  23. package/dist/{WorldClock-WRIK5RPI.js → WorldClock-7B4JZOQR.js} +4 -4
  24. package/dist/{WorldClock-WRIK5RPI.js.map → WorldClock-7B4JZOQR.js.map} +1 -1
  25. package/dist/apps/index.d.ts +14 -13
  26. package/dist/apps/index.js +19 -19
  27. package/dist/{chunk-S3ZVBCKK.js → chunk-2E474D7Q.js} +132 -28
  28. package/dist/chunk-2E474D7Q.js.map +1 -0
  29. package/dist/{chunk-QTDUNBNQ.js → chunk-H7K4IKB6.js} +4 -4
  30. package/dist/{chunk-QTDUNBNQ.js.map → chunk-H7K4IKB6.js.map} +1 -1
  31. package/dist/{chunk-HJ5ZNXPB.js → chunk-JXW7H3DU.js} +54 -3
  32. package/dist/chunk-JXW7H3DU.js.map +1 -0
  33. package/dist/{chunk-3BN3QZX5.js → chunk-PM5G3GVW.js} +3 -3
  34. package/dist/{chunk-3BN3QZX5.js.map → chunk-PM5G3GVW.js.map} +1 -1
  35. package/dist/{chunk-OY6GC3ZI.js → chunk-R2M7SXLN.js} +4 -4
  36. package/dist/{chunk-OY6GC3ZI.js.map → chunk-R2M7SXLN.js.map} +1 -1
  37. package/dist/{chunk-6FET2LA4.js → chunk-RTHUQTNU.js} +4 -4
  38. package/dist/{chunk-6FET2LA4.js.map → chunk-RTHUQTNU.js.map} +1 -1
  39. package/dist/{chunk-3T75O6VR.js → chunk-SNIBFLLT.js} +4 -4
  40. package/dist/{chunk-3T75O6VR.js.map → chunk-SNIBFLLT.js.map} +1 -1
  41. package/dist/{chunk-YWRNK24T.js → chunk-YFKCWZ3A.js} +5 -5
  42. package/dist/{chunk-YWRNK24T.js.map → chunk-YFKCWZ3A.js.map} +1 -1
  43. package/dist/{chunk-F2KBTMSP.js → chunk-YLJY5LDU.js} +3 -3
  44. package/dist/{chunk-F2KBTMSP.js.map → chunk-YLJY5LDU.js.map} +1 -1
  45. package/dist/index.d.ts +82 -81
  46. package/dist/index.js +12 -12
  47. package/dist/{types-CXBKusuC.d.ts → types-CTPtgkiG.d.ts} +1 -1
  48. package/package.json +1 -1
  49. package/dist/Browser-46EJUBW5.js +0 -7
  50. package/dist/Files-ZBUFKYWD.js +0 -12
  51. package/dist/Preview-JA4S64C6.js +0 -8
  52. package/dist/Spreadsheet-G6CQ6FU4.js +0 -7
  53. package/dist/chunk-HJ5ZNXPB.js.map +0 -1
  54. package/dist/chunk-S3ZVBCKK.js.map +0 -1
@@ -1,5 +1,5 @@
1
- import { AboutApp } from './chunk-6FET2LA4.js';
2
- import { WindowTitle } from './chunk-HJ5ZNXPB.js';
1
+ import { AboutApp } from './chunk-RTHUQTNU.js';
2
+ import { WindowTitle } from './chunk-JXW7H3DU.js';
3
3
  import { confirm } from './chunk-UBN4IUDE.js';
4
4
  import { useRef, useEffect, useState } from 'react';
5
5
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -435,5 +435,5 @@ function BrowserBody({
435
435
  }
436
436
 
437
437
  export { Browser, setBrowserStartUrl };
438
- //# sourceMappingURL=chunk-QTDUNBNQ.js.map
439
- //# sourceMappingURL=chunk-QTDUNBNQ.js.map
438
+ //# sourceMappingURL=chunk-H7K4IKB6.js.map
439
+ //# sourceMappingURL=chunk-H7K4IKB6.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/apps/Browser.tsx"],"names":[],"mappings":"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","file":"chunk-QTDUNBNQ.js","sourcesContent":["/**\n * Browser — minimal iframe-backed web browser app.\n *\n * URL bar with back / forward / refresh, navigable bookmark bar\n * (persisted to localStorage), and a graceful \"open in new tab\"\n * escape hatch since most major sites refuse iframe embedding via\n * X-Frame-Options or Content-Security-Policy.\n */\nimport { useEffect, useRef, useState } from 'react';\nimport { WindowTitle } from '../shell/Modal';\nimport { confirm } from '../shell/ConfirmDialog';\nimport AboutApp from './_about';\n\ninterface Bookmark {\n label: string;\n url: string;\n}\n\nconst BOOKMARKS_KEY = 'react-os-shell:browser-bookmarks';\nconst HOMEPAGE_KEY = 'react-os-shell:browser-homepage';\nconst DEFAULT_HOMEPAGE = 'https://en.wikipedia.org/wiki/Main_Page';\nconst DEFAULT_BOOKMARKS: Bookmark[] = [\n { label: 'Wikipedia', url: 'https://en.wikipedia.org/wiki/Main_Page' },\n { label: 'MDN', url: 'https://developer.mozilla.org' },\n { label: 'Example', url: 'https://example.com' },\n];\n\nfunction normalizeUrl(input: string): string {\n let s = input.trim();\n if (!s) return '';\n // Already a URL? Otherwise treat as a search query (DuckDuckGo, no tracking).\n if (/^[a-z][a-z0-9+.-]*:\\/\\//i.test(s)) return s;\n if (/^[\\w.-]+\\.[a-z]{2,}(\\/.*)?$/i.test(s)) return 'https://' + s;\n return 'https://duckduckgo.com/?q=' + encodeURIComponent(s);\n}\n\n// Sites known to refuse iframe embedding via X-Frame-Options or CSP. There's\n// no workaround inside an iframe — the browser blocks the load. We keep a\n// list so we can short-circuit to a friendly \"open in new tab\" panel\n// instead of letting the browser's blank \"refused to connect\" error\n// through. Subdomain match: `mail.google.com` matches `google.com`.\nconst BLOCKED_HOSTS = [\n 'google.com', 'gmail.com', 'youtube.com',\n 'facebook.com', 'instagram.com', 'whatsapp.com',\n 'twitter.com', 'x.com',\n 'github.com', 'gitlab.com',\n 'linkedin.com', 'reddit.com', 'pinterest.com',\n 'amazon.com', 'amazon.ca', 'amazon.co.uk',\n 'apple.com', 'icloud.com',\n 'microsoft.com', 'outlook.com', 'live.com', 'office.com',\n 'netflix.com', 'spotify.com',\n 'paypal.com', 'stripe.com',\n 'chat.openai.com', 'chatgpt.com', 'claude.ai',\n];\n\nfunction hostIsBlocked(href: string): boolean {\n try {\n const host = new URL(href).hostname.toLowerCase();\n return BLOCKED_HOSTS.some(b => host === b || host.endsWith('.' + b));\n } catch { return false; }\n}\n\nfunction loadBookmarks(): Bookmark[] {\n if (typeof window === 'undefined') return DEFAULT_BOOKMARKS;\n try {\n const raw = localStorage.getItem(BOOKMARKS_KEY);\n if (!raw) return DEFAULT_BOOKMARKS;\n const parsed = JSON.parse(raw);\n if (Array.isArray(parsed) && parsed.every(b => typeof b?.url === 'string')) return parsed;\n } catch {}\n return DEFAULT_BOOKMARKS;\n}\n\ninterface PendingStartUrl {\n token: number;\n url: string;\n}\n\nlet pendingStartUrl: PendingStartUrl | null = null;\nlet nextStartToken = 0;\n\n/** Stage a URL for the next Browser window mount — pair with\n * `openPage('/browser')`. Used by \"open this link in the Browser\" flows\n * (e.g. links inside an email body). */\nexport function setBrowserStartUrl(url: string): void {\n pendingStartUrl = { token: ++nextStartToken, url };\n}\n\nfunction loadHomepage(): string {\n if (typeof window === 'undefined') return DEFAULT_HOMEPAGE;\n return localStorage.getItem(HOMEPAGE_KEY) || DEFAULT_HOMEPAGE;\n}\n\nexport default function Browser() {\n // One-shot drain of a staged start URL. The render phase only PEEKS — under\n // React 18 concurrent rendering the first render pass of this lazy component\n // can be discarded and replayed, so a destructive read here would lose the\n // payload (see Spreadsheet/Preview). The stage is cleared in the mount\n // effect below.\n const consumedRef = useRef<PendingStartUrl | null | undefined>(undefined);\n if (consumedRef.current === undefined) {\n consumedRef.current = pendingStartUrl;\n }\n useEffect(() => {\n if (consumedRef.current !== null && pendingStartUrl === consumedRef.current) {\n pendingStartUrl = null;\n }\n }, []);\n const startUrl = consumedRef.current ? normalizeUrl(consumedRef.current.url) : '';\n\n const [homepage, setHomepage] = useState(loadHomepage);\n const [url, setUrl] = useState(startUrl || homepage);\n const [inputUrl, setInputUrl] = useState(url);\n const [history, setHistory] = useState<string[]>([url]);\n const [historyIdx, setHistoryIdx] = useState(0);\n const [iframeKey, setIframeKey] = useState(0);\n const [bookmarks, setBookmarks] = useState<Bookmark[]>(loadBookmarks);\n const [showHelp, setShowHelp] = useState(false);\n // Inline \"name this bookmark\" popover state. Populated when the user\n // clicks the star icon to add — replaces the native window.prompt().\n const [bookmarkDraft, setBookmarkDraft] = useState<string | null>(null);\n const bookmarkInputRef = useRef<HTMLInputElement>(null);\n const iframeRef = useRef<HTMLIFrameElement>(null);\n\n // Persist bookmarks.\n useEffect(() => {\n try { localStorage.setItem(BOOKMARKS_KEY, JSON.stringify(bookmarks)); } catch {}\n }, [bookmarks]);\n\n const navigate = (next: string) => {\n const n = normalizeUrl(next);\n if (!n) return;\n setUrl(n);\n setInputUrl(n);\n // Truncate forward history when navigating from a back state.\n setHistory(h => {\n const trimmed = h.slice(0, historyIdx + 1);\n trimmed.push(n);\n return trimmed;\n });\n setHistoryIdx(i => i + 1);\n setShowHelp(false);\n };\n\n const back = () => {\n if (historyIdx > 0) {\n const next = historyIdx - 1;\n setHistoryIdx(next);\n setUrl(history[next]);\n setInputUrl(history[next]);\n setShowHelp(false);\n }\n };\n\n const forward = () => {\n if (historyIdx < history.length - 1) {\n const next = historyIdx + 1;\n setHistoryIdx(next);\n setUrl(history[next]);\n setInputUrl(history[next]);\n setShowHelp(false);\n }\n };\n\n const refresh = () => setIframeKey(k => k + 1);\n\n const goHome = () => navigate(homepage);\n\n const openExternal = () => {\n if (typeof window !== 'undefined') window.open(url, '_blank', 'noopener,noreferrer');\n };\n\n const openBookmarkPopover = () => {\n setBookmarkDraft(titleFromUrl(url));\n // Focus + select happens in a useEffect once the input is mounted.\n };\n\n const commitBookmark = () => {\n const label = bookmarkDraft?.trim();\n if (!label) { setBookmarkDraft(null); return; }\n setBookmarks(b => [...b, { label, url }]);\n setBookmarkDraft(null);\n };\n\n // Auto-focus + select the popover input when it opens, and dismiss on\n // outside click.\n useEffect(() => {\n if (bookmarkDraft === null) return;\n bookmarkInputRef.current?.focus();\n bookmarkInputRef.current?.select();\n const onDocClick = (e: MouseEvent) => {\n const target = e.target as HTMLElement | null;\n if (!target?.closest('[data-bookmark-popover]')) setBookmarkDraft(null);\n };\n // Defer one tick so the click that opened the popover doesn't close it.\n const t = setTimeout(() => document.addEventListener('mousedown', onDocClick), 0);\n return () => {\n clearTimeout(t);\n document.removeEventListener('mousedown', onDocClick);\n };\n }, [bookmarkDraft !== null]);\n\n const removeBookmark = (i: number) => {\n setBookmarks(b => b.filter((_, idx) => idx !== i));\n };\n\n const setAsHomepage = () => {\n setHomepage(url);\n try { localStorage.setItem(HOMEPAGE_KEY, url); } catch {}\n };\n\n const onSubmitUrl = (e: React.FormEvent) => {\n e.preventDefault();\n navigate(inputUrl);\n };\n\n const canBack = historyIdx > 0;\n const canForward = historyIdx < history.length - 1;\n const isBookmarked = bookmarks.some(b => b.url === url);\n const btn = 'p-1.5 rounded hover:bg-gray-200 transition-colors text-gray-600 disabled:opacity-30';\n\n return (\n <div className=\"relative flex flex-col h-full bg-white\">\n <WindowTitle title={`Browser - ${titleFromUrl(url)}`} />\n <AboutApp app=\"browser\" />\n\n {/* Top toolbar */}\n <div className=\"flex items-center gap-1 px-2 py-1.5 border-b border-gray-200 bg-gray-50 shrink-0\">\n <button onClick={back} disabled={!canBack} className={btn} title=\"Back\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M15.75 19.5L8.25 12l7.5-7.5\" /></svg>\n </button>\n <button onClick={forward} disabled={!canForward} className={btn} title=\"Forward\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M8.25 4.5l7.5 7.5-7.5 7.5\" /></svg>\n </button>\n <button onClick={refresh} className={btn} title=\"Refresh\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.8}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M16.023 9.348h4.992V4.356M2.985 19.644v-4.992h4.992M3.05 9.348a9 9 0 0114.85-3.36L21.015 9.348m0 5.304a9 9 0 01-14.85 3.36l-3.115-3.36\" /></svg>\n </button>\n <button onClick={goHome} className={btn} title=\"Home\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.8}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M2.25 12l8.954-8.955a1.5 1.5 0 012.122 0l8.954 8.955M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25\" /></svg>\n </button>\n\n <form onSubmit={onSubmitUrl} className=\"flex-1 flex items-center mx-1\">\n <div className=\"flex items-center w-full bg-white border border-gray-300 rounded focus-within:border-blue-400 focus-within:ring-1 focus-within:ring-blue-200\">\n <span className=\"px-2 text-gray-400 text-xs\">{url.startsWith('https://') ? '🔒' : '⚠️'}</span>\n <input\n type=\"text\"\n value={inputUrl}\n onChange={(e) => setInputUrl(e.target.value)}\n onFocus={(e) => e.target.select()}\n className=\"flex-1 px-1 py-1 text-sm bg-transparent outline-none font-mono\"\n spellCheck={false}\n placeholder=\"Enter URL or search…\"\n />\n {url !== inputUrl && (\n <button\n type=\"button\"\n onClick={() => setInputUrl(url)}\n className=\"px-1.5 text-[10px] text-gray-400 hover:text-gray-700\"\n title=\"Reset to current URL\"\n >×</button>\n )}\n </div>\n </form>\n\n <button\n data-bookmark-popover\n onClick={() => isBookmarked\n ? removeBookmark(bookmarks.findIndex(b => b.url === url))\n : openBookmarkPopover()}\n className={btn + ' ' + (isBookmarked ? 'text-yellow-500' : '')}\n title={isBookmarked ? 'Remove bookmark' : 'Add bookmark'}\n >\n <svg className=\"h-4 w-4\" fill={isBookmarked ? 'currentColor' : 'none'} viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.562.562 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z\" />\n </svg>\n </button>\n <button onClick={openExternal} className={btn} title=\"Open in new tab\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-7.5-9L21 3m0 0v6m0-6L9.75 14.25\" /></svg>\n </button>\n <button onClick={() => setShowHelp(s => !s)} className={btn} title=\"Embedding help\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9 5.25h.008v.008H12v-.008z\" /></svg>\n </button>\n </div>\n\n {/* Inline \"name this bookmark\" popover. Anchored to the right of the\n toolbar (where the star icon lives) so the visual flow matches\n how the user just clicked. Renders inside the panel so it\n inherits the window's z-stacking. */}\n {bookmarkDraft !== null && (\n <div\n data-bookmark-popover\n className=\"absolute right-3 top-12 z-30 w-72 bg-white border border-gray-200 rounded-md shadow-lg p-3\"\n >\n <div className=\"text-[11px] font-semibold uppercase tracking-wide text-gray-500 mb-1\">Bookmark this page</div>\n <div className=\"text-[11px] text-gray-400 truncate mb-2 font-mono\" title={url}>{url}</div>\n <input\n ref={bookmarkInputRef}\n type=\"text\"\n value={bookmarkDraft}\n onChange={(e) => setBookmarkDraft(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') commitBookmark();\n else if (e.key === 'Escape') setBookmarkDraft(null);\n }}\n placeholder=\"Name\"\n className=\"w-full text-sm px-2 py-1.5 border border-gray-300 rounded focus:outline-none focus:border-blue-400 focus:ring-1 focus:ring-blue-200\"\n />\n <div className=\"flex justify-end gap-1 mt-2\">\n <button\n onClick={() => setBookmarkDraft(null)}\n className=\"px-2 py-1 text-xs text-gray-600 hover:bg-gray-100 rounded\"\n >Cancel</button>\n <button\n onClick={commitBookmark}\n disabled={!bookmarkDraft.trim()}\n className=\"px-2 py-1 text-xs bg-blue-500 text-white rounded hover:bg-blue-600 disabled:opacity-40\"\n >Save</button>\n </div>\n </div>\n )}\n\n {/* Bookmarks bar */}\n <div className=\"flex items-center gap-0.5 px-2 py-1 border-b border-gray-200 bg-white shrink-0 overflow-x-auto\">\n {bookmarks.length === 0 && (\n <span className=\"text-[11px] text-gray-400 italic px-2\">No bookmarks yet — star the address bar to add one.</span>\n )}\n {bookmarks.map((b, i) => (\n <button\n key={i}\n onClick={() => navigate(b.url)}\n onContextMenu={async (e) => {\n e.preventDefault();\n const ok = await confirm({\n title: 'Remove bookmark',\n message: `\"${b.label}\" will be removed from your bookmarks.`,\n confirmLabel: 'Remove',\n variant: 'danger',\n });\n if (ok) removeBookmark(i);\n }}\n className=\"flex items-center gap-1.5 px-2 py-0.5 rounded text-[12px] text-gray-700 hover:bg-gray-100 whitespace-nowrap\"\n title={`${b.url}\\n(right-click to remove)`}\n >\n <img\n src={`https://icons.duckduckgo.com/ip3/${new URL(b.url).hostname}.ico`}\n alt=\"\"\n className=\"h-3.5 w-3.5\"\n onError={(e) => { (e.target as HTMLImageElement).style.visibility = 'hidden'; }}\n />\n {b.label}\n </button>\n ))}\n <div className=\"flex-1\" />\n <button\n onClick={setAsHomepage}\n className=\"px-2 py-0.5 text-[11px] text-gray-500 hover:text-gray-800\"\n title=\"Set current page as homepage\"\n >Set as home</button>\n </div>\n\n {/* Iframe area */}\n <div className=\"flex-1 relative min-h-0 bg-gray-50\">\n <BrowserBody\n url={url}\n iframeKey={iframeKey}\n iframeRef={iframeRef}\n openExternal={openExternal}\n showHelp={showHelp}\n dismissHelp={() => setShowHelp(false)}\n />\n </div>\n </div>\n );\n}\n\nfunction titleFromUrl(u: string): string {\n try {\n const url = new URL(u);\n return url.hostname.replace(/^www\\./, '');\n } catch {\n return u;\n }\n}\n\nfunction BrowserBody({\n url,\n iframeKey,\n iframeRef,\n openExternal,\n showHelp,\n dismissHelp,\n}: {\n url: string;\n iframeKey: number;\n iframeRef: React.RefObject<HTMLIFrameElement | null>;\n openExternal: () => void;\n showHelp: boolean;\n dismissHelp: () => void;\n}) {\n // If the user dismisses the blocked-site panel, allow them to attempt\n // the iframe load anyway. Reset the override whenever URL changes.\n const [forceTry, setForceTry] = useState(false);\n useEffect(() => { setForceTry(false); }, [url]);\n\n const blocked = hostIsBlocked(url) && !forceTry;\n\n if (blocked) {\n return (\n <div className=\"absolute inset-0 flex items-center justify-center bg-white p-8\">\n <div className=\"max-w-md text-center\">\n <svg className=\"h-14 w-14 mx-auto text-gray-300 mb-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728L5.636 5.636m12.728 12.728L21 21M5.636 5.636L3 3m9 9a9 9 0 110-18 9 9 0 010 18z\" />\n </svg>\n <h3 className=\"text-base font-semibold text-gray-800 mb-1\">\n {titleFromUrl(url)} can't be embedded\n </h3>\n <p className=\"text-sm text-gray-500 mb-4\">\n This site sends an <span className=\"font-mono text-xs\">X-Frame-Options</span>{' '}\n or <span className=\"font-mono text-xs\">Content-Security-Policy</span> header\n that refuses iframe embedding. The browser blocks the load before our app\n can do anything about it.\n </p>\n <div className=\"flex flex-col items-center gap-2\">\n <button\n onClick={openExternal}\n className=\"px-4 py-2 bg-blue-500 text-white text-sm rounded hover:bg-blue-600 inline-flex items-center gap-2\"\n >\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-7.5-9L21 3m0 0v6m0-6L9.75 14.25\" />\n </svg>\n Open in a new tab\n </button>\n <button\n onClick={() => setForceTry(true)}\n className=\"text-xs text-gray-500 hover:text-gray-800 underline\"\n >\n Try loading it here anyway\n </button>\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <>\n <iframe\n key={iframeKey + url}\n ref={iframeRef as React.RefObject<HTMLIFrameElement>}\n src={url}\n className=\"absolute inset-0 w-full h-full bg-white\"\n // Sandboxing keeps embedded pages from messing with the parent\n // window state. allow-same-origin lets sites that *do* allow\n // embedding actually behave normally; allow-scripts is needed\n // for any modern site.\n sandbox=\"allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-modals\"\n referrerPolicy=\"no-referrer-when-downgrade\"\n />\n\n {showHelp && (\n <div className=\"absolute top-2 right-2 max-w-sm bg-white border border-gray-200 rounded-md shadow-lg p-3 text-xs text-gray-700 z-10\">\n <div className=\"font-medium text-gray-900 mb-1\">Why is this page blank?</div>\n <p className=\"mb-2\">\n Most major sites (Google, GitHub, banks, news) refuse to be embedded in\n an iframe via <span className=\"font-mono\">X-Frame-Options</span> or\n Content Security Policy. There's no workaround — the browser blocks the\n load before our app can do anything.\n </p>\n <p>\n Hit the <span className=\"font-medium\">↗</span> button to open the page in\n a real new tab. Sites that <em>do</em> allow embedding (Wikipedia, MDN,\n docs sites, your own apps) work fine in here.\n </p>\n <button\n onClick={dismissHelp}\n className=\"mt-2 text-[11px] text-blue-600 hover:underline\"\n >Got it</button>\n </div>\n )}\n </>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/apps/Browser.tsx"],"names":[],"mappings":"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","file":"chunk-H7K4IKB6.js","sourcesContent":["/**\n * Browser — minimal iframe-backed web browser app.\n *\n * URL bar with back / forward / refresh, navigable bookmark bar\n * (persisted to localStorage), and a graceful \"open in new tab\"\n * escape hatch since most major sites refuse iframe embedding via\n * X-Frame-Options or Content-Security-Policy.\n */\nimport { useEffect, useRef, useState } from 'react';\nimport { WindowTitle } from '../shell/Modal';\nimport { confirm } from '../shell/ConfirmDialog';\nimport AboutApp from './_about';\n\ninterface Bookmark {\n label: string;\n url: string;\n}\n\nconst BOOKMARKS_KEY = 'react-os-shell:browser-bookmarks';\nconst HOMEPAGE_KEY = 'react-os-shell:browser-homepage';\nconst DEFAULT_HOMEPAGE = 'https://en.wikipedia.org/wiki/Main_Page';\nconst DEFAULT_BOOKMARKS: Bookmark[] = [\n { label: 'Wikipedia', url: 'https://en.wikipedia.org/wiki/Main_Page' },\n { label: 'MDN', url: 'https://developer.mozilla.org' },\n { label: 'Example', url: 'https://example.com' },\n];\n\nfunction normalizeUrl(input: string): string {\n let s = input.trim();\n if (!s) return '';\n // Already a URL? Otherwise treat as a search query (DuckDuckGo, no tracking).\n if (/^[a-z][a-z0-9+.-]*:\\/\\//i.test(s)) return s;\n if (/^[\\w.-]+\\.[a-z]{2,}(\\/.*)?$/i.test(s)) return 'https://' + s;\n return 'https://duckduckgo.com/?q=' + encodeURIComponent(s);\n}\n\n// Sites known to refuse iframe embedding via X-Frame-Options or CSP. There's\n// no workaround inside an iframe — the browser blocks the load. We keep a\n// list so we can short-circuit to a friendly \"open in new tab\" panel\n// instead of letting the browser's blank \"refused to connect\" error\n// through. Subdomain match: `mail.google.com` matches `google.com`.\nconst BLOCKED_HOSTS = [\n 'google.com', 'gmail.com', 'youtube.com',\n 'facebook.com', 'instagram.com', 'whatsapp.com',\n 'twitter.com', 'x.com',\n 'github.com', 'gitlab.com',\n 'linkedin.com', 'reddit.com', 'pinterest.com',\n 'amazon.com', 'amazon.ca', 'amazon.co.uk',\n 'apple.com', 'icloud.com',\n 'microsoft.com', 'outlook.com', 'live.com', 'office.com',\n 'netflix.com', 'spotify.com',\n 'paypal.com', 'stripe.com',\n 'chat.openai.com', 'chatgpt.com', 'claude.ai',\n];\n\nfunction hostIsBlocked(href: string): boolean {\n try {\n const host = new URL(href).hostname.toLowerCase();\n return BLOCKED_HOSTS.some(b => host === b || host.endsWith('.' + b));\n } catch { return false; }\n}\n\nfunction loadBookmarks(): Bookmark[] {\n if (typeof window === 'undefined') return DEFAULT_BOOKMARKS;\n try {\n const raw = localStorage.getItem(BOOKMARKS_KEY);\n if (!raw) return DEFAULT_BOOKMARKS;\n const parsed = JSON.parse(raw);\n if (Array.isArray(parsed) && parsed.every(b => typeof b?.url === 'string')) return parsed;\n } catch {}\n return DEFAULT_BOOKMARKS;\n}\n\ninterface PendingStartUrl {\n token: number;\n url: string;\n}\n\nlet pendingStartUrl: PendingStartUrl | null = null;\nlet nextStartToken = 0;\n\n/** Stage a URL for the next Browser window mount — pair with\n * `openPage('/browser')`. Used by \"open this link in the Browser\" flows\n * (e.g. links inside an email body). */\nexport function setBrowserStartUrl(url: string): void {\n pendingStartUrl = { token: ++nextStartToken, url };\n}\n\nfunction loadHomepage(): string {\n if (typeof window === 'undefined') return DEFAULT_HOMEPAGE;\n return localStorage.getItem(HOMEPAGE_KEY) || DEFAULT_HOMEPAGE;\n}\n\nexport default function Browser() {\n // One-shot drain of a staged start URL. The render phase only PEEKS — under\n // React 18 concurrent rendering the first render pass of this lazy component\n // can be discarded and replayed, so a destructive read here would lose the\n // payload (see Spreadsheet/Preview). The stage is cleared in the mount\n // effect below.\n const consumedRef = useRef<PendingStartUrl | null | undefined>(undefined);\n if (consumedRef.current === undefined) {\n consumedRef.current = pendingStartUrl;\n }\n useEffect(() => {\n if (consumedRef.current !== null && pendingStartUrl === consumedRef.current) {\n pendingStartUrl = null;\n }\n }, []);\n const startUrl = consumedRef.current ? normalizeUrl(consumedRef.current.url) : '';\n\n const [homepage, setHomepage] = useState(loadHomepage);\n const [url, setUrl] = useState(startUrl || homepage);\n const [inputUrl, setInputUrl] = useState(url);\n const [history, setHistory] = useState<string[]>([url]);\n const [historyIdx, setHistoryIdx] = useState(0);\n const [iframeKey, setIframeKey] = useState(0);\n const [bookmarks, setBookmarks] = useState<Bookmark[]>(loadBookmarks);\n const [showHelp, setShowHelp] = useState(false);\n // Inline \"name this bookmark\" popover state. Populated when the user\n // clicks the star icon to add — replaces the native window.prompt().\n const [bookmarkDraft, setBookmarkDraft] = useState<string | null>(null);\n const bookmarkInputRef = useRef<HTMLInputElement>(null);\n const iframeRef = useRef<HTMLIFrameElement>(null);\n\n // Persist bookmarks.\n useEffect(() => {\n try { localStorage.setItem(BOOKMARKS_KEY, JSON.stringify(bookmarks)); } catch {}\n }, [bookmarks]);\n\n const navigate = (next: string) => {\n const n = normalizeUrl(next);\n if (!n) return;\n setUrl(n);\n setInputUrl(n);\n // Truncate forward history when navigating from a back state.\n setHistory(h => {\n const trimmed = h.slice(0, historyIdx + 1);\n trimmed.push(n);\n return trimmed;\n });\n setHistoryIdx(i => i + 1);\n setShowHelp(false);\n };\n\n const back = () => {\n if (historyIdx > 0) {\n const next = historyIdx - 1;\n setHistoryIdx(next);\n setUrl(history[next]);\n setInputUrl(history[next]);\n setShowHelp(false);\n }\n };\n\n const forward = () => {\n if (historyIdx < history.length - 1) {\n const next = historyIdx + 1;\n setHistoryIdx(next);\n setUrl(history[next]);\n setInputUrl(history[next]);\n setShowHelp(false);\n }\n };\n\n const refresh = () => setIframeKey(k => k + 1);\n\n const goHome = () => navigate(homepage);\n\n const openExternal = () => {\n if (typeof window !== 'undefined') window.open(url, '_blank', 'noopener,noreferrer');\n };\n\n const openBookmarkPopover = () => {\n setBookmarkDraft(titleFromUrl(url));\n // Focus + select happens in a useEffect once the input is mounted.\n };\n\n const commitBookmark = () => {\n const label = bookmarkDraft?.trim();\n if (!label) { setBookmarkDraft(null); return; }\n setBookmarks(b => [...b, { label, url }]);\n setBookmarkDraft(null);\n };\n\n // Auto-focus + select the popover input when it opens, and dismiss on\n // outside click.\n useEffect(() => {\n if (bookmarkDraft === null) return;\n bookmarkInputRef.current?.focus();\n bookmarkInputRef.current?.select();\n const onDocClick = (e: MouseEvent) => {\n const target = e.target as HTMLElement | null;\n if (!target?.closest('[data-bookmark-popover]')) setBookmarkDraft(null);\n };\n // Defer one tick so the click that opened the popover doesn't close it.\n const t = setTimeout(() => document.addEventListener('mousedown', onDocClick), 0);\n return () => {\n clearTimeout(t);\n document.removeEventListener('mousedown', onDocClick);\n };\n }, [bookmarkDraft !== null]);\n\n const removeBookmark = (i: number) => {\n setBookmarks(b => b.filter((_, idx) => idx !== i));\n };\n\n const setAsHomepage = () => {\n setHomepage(url);\n try { localStorage.setItem(HOMEPAGE_KEY, url); } catch {}\n };\n\n const onSubmitUrl = (e: React.FormEvent) => {\n e.preventDefault();\n navigate(inputUrl);\n };\n\n const canBack = historyIdx > 0;\n const canForward = historyIdx < history.length - 1;\n const isBookmarked = bookmarks.some(b => b.url === url);\n const btn = 'p-1.5 rounded hover:bg-gray-200 transition-colors text-gray-600 disabled:opacity-30';\n\n return (\n <div className=\"relative flex flex-col h-full bg-white\">\n <WindowTitle title={`Browser - ${titleFromUrl(url)}`} />\n <AboutApp app=\"browser\" />\n\n {/* Top toolbar */}\n <div className=\"flex items-center gap-1 px-2 py-1.5 border-b border-gray-200 bg-gray-50 shrink-0\">\n <button onClick={back} disabled={!canBack} className={btn} title=\"Back\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M15.75 19.5L8.25 12l7.5-7.5\" /></svg>\n </button>\n <button onClick={forward} disabled={!canForward} className={btn} title=\"Forward\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M8.25 4.5l7.5 7.5-7.5 7.5\" /></svg>\n </button>\n <button onClick={refresh} className={btn} title=\"Refresh\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.8}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M16.023 9.348h4.992V4.356M2.985 19.644v-4.992h4.992M3.05 9.348a9 9 0 0114.85-3.36L21.015 9.348m0 5.304a9 9 0 01-14.85 3.36l-3.115-3.36\" /></svg>\n </button>\n <button onClick={goHome} className={btn} title=\"Home\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.8}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M2.25 12l8.954-8.955a1.5 1.5 0 012.122 0l8.954 8.955M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25\" /></svg>\n </button>\n\n <form onSubmit={onSubmitUrl} className=\"flex-1 flex items-center mx-1\">\n <div className=\"flex items-center w-full bg-white border border-gray-300 rounded focus-within:border-blue-400 focus-within:ring-1 focus-within:ring-blue-200\">\n <span className=\"px-2 text-gray-400 text-xs\">{url.startsWith('https://') ? '🔒' : '⚠️'}</span>\n <input\n type=\"text\"\n value={inputUrl}\n onChange={(e) => setInputUrl(e.target.value)}\n onFocus={(e) => e.target.select()}\n className=\"flex-1 px-1 py-1 text-sm bg-transparent outline-none font-mono\"\n spellCheck={false}\n placeholder=\"Enter URL or search…\"\n />\n {url !== inputUrl && (\n <button\n type=\"button\"\n onClick={() => setInputUrl(url)}\n className=\"px-1.5 text-[10px] text-gray-400 hover:text-gray-700\"\n title=\"Reset to current URL\"\n >×</button>\n )}\n </div>\n </form>\n\n <button\n data-bookmark-popover\n onClick={() => isBookmarked\n ? removeBookmark(bookmarks.findIndex(b => b.url === url))\n : openBookmarkPopover()}\n className={btn + ' ' + (isBookmarked ? 'text-yellow-500' : '')}\n title={isBookmarked ? 'Remove bookmark' : 'Add bookmark'}\n >\n <svg className=\"h-4 w-4\" fill={isBookmarked ? 'currentColor' : 'none'} viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.562.562 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z\" />\n </svg>\n </button>\n <button onClick={openExternal} className={btn} title=\"Open in new tab\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-7.5-9L21 3m0 0v6m0-6L9.75 14.25\" /></svg>\n </button>\n <button onClick={() => setShowHelp(s => !s)} className={btn} title=\"Embedding help\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9 5.25h.008v.008H12v-.008z\" /></svg>\n </button>\n </div>\n\n {/* Inline \"name this bookmark\" popover. Anchored to the right of the\n toolbar (where the star icon lives) so the visual flow matches\n how the user just clicked. Renders inside the panel so it\n inherits the window's z-stacking. */}\n {bookmarkDraft !== null && (\n <div\n data-bookmark-popover\n className=\"absolute right-3 top-12 z-30 w-72 bg-white border border-gray-200 rounded-md shadow-lg p-3\"\n >\n <div className=\"text-[11px] font-semibold uppercase tracking-wide text-gray-500 mb-1\">Bookmark this page</div>\n <div className=\"text-[11px] text-gray-400 truncate mb-2 font-mono\" title={url}>{url}</div>\n <input\n ref={bookmarkInputRef}\n type=\"text\"\n value={bookmarkDraft}\n onChange={(e) => setBookmarkDraft(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') commitBookmark();\n else if (e.key === 'Escape') setBookmarkDraft(null);\n }}\n placeholder=\"Name\"\n className=\"w-full text-sm px-2 py-1.5 border border-gray-300 rounded focus:outline-none focus:border-blue-400 focus:ring-1 focus:ring-blue-200\"\n />\n <div className=\"flex justify-end gap-1 mt-2\">\n <button\n onClick={() => setBookmarkDraft(null)}\n className=\"px-2 py-1 text-xs text-gray-600 hover:bg-gray-100 rounded\"\n >Cancel</button>\n <button\n onClick={commitBookmark}\n disabled={!bookmarkDraft.trim()}\n className=\"px-2 py-1 text-xs bg-blue-500 text-white rounded hover:bg-blue-600 disabled:opacity-40\"\n >Save</button>\n </div>\n </div>\n )}\n\n {/* Bookmarks bar */}\n <div className=\"flex items-center gap-0.5 px-2 py-1 border-b border-gray-200 bg-white shrink-0 overflow-x-auto\">\n {bookmarks.length === 0 && (\n <span className=\"text-[11px] text-gray-400 italic px-2\">No bookmarks yet — star the address bar to add one.</span>\n )}\n {bookmarks.map((b, i) => (\n <button\n key={i}\n onClick={() => navigate(b.url)}\n onContextMenu={async (e) => {\n e.preventDefault();\n const ok = await confirm({\n title: 'Remove bookmark',\n message: `\"${b.label}\" will be removed from your bookmarks.`,\n confirmLabel: 'Remove',\n variant: 'danger',\n });\n if (ok) removeBookmark(i);\n }}\n className=\"flex items-center gap-1.5 px-2 py-0.5 rounded text-[12px] text-gray-700 hover:bg-gray-100 whitespace-nowrap\"\n title={`${b.url}\\n(right-click to remove)`}\n >\n <img\n src={`https://icons.duckduckgo.com/ip3/${new URL(b.url).hostname}.ico`}\n alt=\"\"\n className=\"h-3.5 w-3.5\"\n onError={(e) => { (e.target as HTMLImageElement).style.visibility = 'hidden'; }}\n />\n {b.label}\n </button>\n ))}\n <div className=\"flex-1\" />\n <button\n onClick={setAsHomepage}\n className=\"px-2 py-0.5 text-[11px] text-gray-500 hover:text-gray-800\"\n title=\"Set current page as homepage\"\n >Set as home</button>\n </div>\n\n {/* Iframe area */}\n <div className=\"flex-1 relative min-h-0 bg-gray-50\">\n <BrowserBody\n url={url}\n iframeKey={iframeKey}\n iframeRef={iframeRef}\n openExternal={openExternal}\n showHelp={showHelp}\n dismissHelp={() => setShowHelp(false)}\n />\n </div>\n </div>\n );\n}\n\nfunction titleFromUrl(u: string): string {\n try {\n const url = new URL(u);\n return url.hostname.replace(/^www\\./, '');\n } catch {\n return u;\n }\n}\n\nfunction BrowserBody({\n url,\n iframeKey,\n iframeRef,\n openExternal,\n showHelp,\n dismissHelp,\n}: {\n url: string;\n iframeKey: number;\n iframeRef: React.RefObject<HTMLIFrameElement | null>;\n openExternal: () => void;\n showHelp: boolean;\n dismissHelp: () => void;\n}) {\n // If the user dismisses the blocked-site panel, allow them to attempt\n // the iframe load anyway. Reset the override whenever URL changes.\n const [forceTry, setForceTry] = useState(false);\n useEffect(() => { setForceTry(false); }, [url]);\n\n const blocked = hostIsBlocked(url) && !forceTry;\n\n if (blocked) {\n return (\n <div className=\"absolute inset-0 flex items-center justify-center bg-white p-8\">\n <div className=\"max-w-md text-center\">\n <svg className=\"h-14 w-14 mx-auto text-gray-300 mb-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728L5.636 5.636m12.728 12.728L21 21M5.636 5.636L3 3m9 9a9 9 0 110-18 9 9 0 010 18z\" />\n </svg>\n <h3 className=\"text-base font-semibold text-gray-800 mb-1\">\n {titleFromUrl(url)} can't be embedded\n </h3>\n <p className=\"text-sm text-gray-500 mb-4\">\n This site sends an <span className=\"font-mono text-xs\">X-Frame-Options</span>{' '}\n or <span className=\"font-mono text-xs\">Content-Security-Policy</span> header\n that refuses iframe embedding. The browser blocks the load before our app\n can do anything about it.\n </p>\n <div className=\"flex flex-col items-center gap-2\">\n <button\n onClick={openExternal}\n className=\"px-4 py-2 bg-blue-500 text-white text-sm rounded hover:bg-blue-600 inline-flex items-center gap-2\"\n >\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-7.5-9L21 3m0 0v6m0-6L9.75 14.25\" />\n </svg>\n Open in a new tab\n </button>\n <button\n onClick={() => setForceTry(true)}\n className=\"text-xs text-gray-500 hover:text-gray-800 underline\"\n >\n Try loading it here anyway\n </button>\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <>\n <iframe\n key={iframeKey + url}\n ref={iframeRef as React.RefObject<HTMLIFrameElement>}\n src={url}\n className=\"absolute inset-0 w-full h-full bg-white\"\n // Sandboxing keeps embedded pages from messing with the parent\n // window state. allow-same-origin lets sites that *do* allow\n // embedding actually behave normally; allow-scripts is needed\n // for any modern site.\n sandbox=\"allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-modals\"\n referrerPolicy=\"no-referrer-when-downgrade\"\n />\n\n {showHelp && (\n <div className=\"absolute top-2 right-2 max-w-sm bg-white border border-gray-200 rounded-md shadow-lg p-3 text-xs text-gray-700 z-10\">\n <div className=\"font-medium text-gray-900 mb-1\">Why is this page blank?</div>\n <p className=\"mb-2\">\n Most major sites (Google, GitHub, banks, news) refuse to be embedded in\n an iframe via <span className=\"font-mono\">X-Frame-Options</span> or\n Content Security Policy. There's no workaround — the browser blocks the\n load before our app can do anything.\n </p>\n <p>\n Hit the <span className=\"font-medium\">↗</span> button to open the page in\n a real new tab. Sites that <em>do</em> allow embedding (Wikipedia, MDN,\n docs sites, your own apps) work fine in here.\n </p>\n <button\n onClick={dismissHelp}\n className=\"mt-2 text-[11px] text-blue-600 hover:underline\"\n >Got it</button>\n </div>\n )}\n </>\n );\n}\n"]}
@@ -662,6 +662,47 @@ function hideSnapPreview() {
662
662
  snapPreviewEl.style.opacity = "0";
663
663
  snapPreviewEl.style.display = "none";
664
664
  }
665
+ var GESTURE_STYLE_ID = "rosh-gesture-style";
666
+ function ensureGestureStyle() {
667
+ if (typeof document === "undefined" || document.getElementById(GESTURE_STYLE_ID)) return;
668
+ const style = document.createElement("style");
669
+ style.id = GESTURE_STYLE_ID;
670
+ style.textContent = "body.rosh-gesturing .backdrop-blur-sm{backdrop-filter:none!important;-webkit-backdrop-filter:none!important}body.rosh-gesturing [data-modal-panel]{will-change:transform}";
671
+ document.head.appendChild(style);
672
+ }
673
+ var RESIZE_CURSOR = {
674
+ se: "nwse-resize",
675
+ nw: "nwse-resize",
676
+ sw: "nesw-resize",
677
+ ne: "nesw-resize",
678
+ n: "ns-resize",
679
+ s: "ns-resize",
680
+ e: "ew-resize",
681
+ w: "ew-resize"
682
+ };
683
+ function beginPointerGesture(handle, pointerId, cursor) {
684
+ ensureGestureStyle();
685
+ try {
686
+ handle.setPointerCapture(pointerId);
687
+ } catch {
688
+ }
689
+ document.body.classList.add("rosh-gesturing");
690
+ const shield = document.createElement("div");
691
+ shield.setAttribute("data-drag-shield", "");
692
+ shield.style.cssText = `position:fixed;inset:0;z-index:2147483647;cursor:${cursor};background:transparent;touch-action:none`;
693
+ document.body.appendChild(shield);
694
+ let done = false;
695
+ return () => {
696
+ if (done) return;
697
+ done = true;
698
+ try {
699
+ handle.releasePointerCapture(pointerId);
700
+ } catch {
701
+ }
702
+ shield.remove();
703
+ document.body.classList.remove("rosh-gesturing");
704
+ };
705
+ }
665
706
  window.addEventListener("deactivate-all-modals", deactivateAllModals);
666
707
  function getZForModal(id) {
667
708
  const idx = activationOrder.indexOf(id);
@@ -1303,6 +1344,7 @@ function Modal({ open, onClose, title, icon, copyText, size = "lg", dirty = fals
1303
1344
  return;
1304
1345
  }
1305
1346
  e.preventDefault();
1347
+ const endGesture = beginPointerGesture(e.currentTarget, e.pointerId, "move");
1306
1348
  const sx = e.clientX, sy = e.clientY;
1307
1349
  const panel = panelRef.current;
1308
1350
  const rect = panel?.getBoundingClientRect();
@@ -1350,6 +1392,7 @@ function Modal({ open, onClose, title, icon, copyText, size = "lg", dirty = fals
1350
1392
  const up = () => {
1351
1393
  window.removeEventListener("pointermove", move);
1352
1394
  window.removeEventListener("pointerup", up);
1395
+ endGesture();
1353
1396
  hideSnapPreview();
1354
1397
  const finalBox = { ...boxRef.current };
1355
1398
  if (!widget && currentZone) {
@@ -1371,6 +1414,7 @@ function Modal({ open, onClose, title, icon, copyText, size = "lg", dirty = fals
1371
1414
  if (e.button !== 0) return;
1372
1415
  e.preventDefault();
1373
1416
  e.stopPropagation();
1417
+ const endGesture = beginPointerGesture(e.currentTarget, e.pointerId, RESIZE_CURSOR[corner]);
1374
1418
  const sx = e.clientX, sy = e.clientY;
1375
1419
  const panel = panelRef.current;
1376
1420
  const rect = panel?.getBoundingClientRect();
@@ -1411,7 +1455,12 @@ function Modal({ open, onClose, title, icon, copyText, size = "lg", dirty = fals
1411
1455
  const next = pending;
1412
1456
  pending = null;
1413
1457
  boxRef.current = next;
1414
- setBox(next);
1458
+ if (panel) {
1459
+ panel.style.left = `${next.x}px`;
1460
+ panel.style.top = `${next.y}px`;
1461
+ panel.style.width = `${next.w}px`;
1462
+ panel.style.height = `${next.h}px`;
1463
+ }
1415
1464
  };
1416
1465
  const move = (ev) => {
1417
1466
  pending = compute(ev.clientX - sx, ev.clientY - sy);
@@ -1422,6 +1471,8 @@ function Modal({ open, onClose, title, icon, copyText, size = "lg", dirty = fals
1422
1471
  window.removeEventListener("pointerup", up);
1423
1472
  if (raf) cancelAnimationFrame(raf);
1424
1473
  flush();
1474
+ endGesture();
1475
+ setBox({ ...boxRef.current });
1425
1476
  };
1426
1477
  window.addEventListener("pointermove", move);
1427
1478
  window.addEventListener("pointerup", up);
@@ -2563,5 +2614,5 @@ function WindowManagerProvider({ children }) {
2563
2614
  }
2564
2615
 
2565
2616
  export { CancelButton, CopyButton, DocFavStar, LoadingSpinner, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, ShellPrefsProvider, ThumbCard, WINDOW_REGISTRY, WindowCrashedFallback, WindowErrorBoundary, WindowManagerProvider, WindowTitle, activateModal, client_default, commitExposeHighlight, exitExposeMode, getActiveModalId, getActiveWindowRoute, getExposeHighlight, getWindowPosition, isEntityEntry, isPageEntry, registerModalEscapeInterceptor, setExposeHighlight, setShellApiClient, setShellWindowRegistry, setWindowDefaultPosition, setWindowPosition, subscribeExposeHighlight, toggleExposeMode, useIsMobile, useLocalStoragePrefs, useModalActive, useShellPrefs, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle };
2566
- //# sourceMappingURL=chunk-HJ5ZNXPB.js.map
2567
- //# sourceMappingURL=chunk-HJ5ZNXPB.js.map
2617
+ //# sourceMappingURL=chunk-JXW7H3DU.js.map
2618
+ //# sourceMappingURL=chunk-JXW7H3DU.js.map