react-os-shell 4.75.0 → 4.77.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.
- package/dist/{Browser-AXSL5ZUK.js → Browser-G7A6O5KI.js} +5 -5
- package/dist/{Browser-AXSL5ZUK.js.map → Browser-G7A6O5KI.js.map} +1 -1
- package/dist/{Calculator-6MI37S5J.js → Calculator-SRZGJITP.js} +4 -4
- package/dist/{Calculator-6MI37S5J.js.map → Calculator-SRZGJITP.js.map} +1 -1
- package/dist/{CurrencyConverter-OENZ4I74.js → CurrencyConverter-3KBUNSD6.js} +4 -4
- package/dist/{CurrencyConverter-OENZ4I74.js.map → CurrencyConverter-3KBUNSD6.js.map} +1 -1
- package/dist/{Documents-BCMEMP2J.js → Documents-7CMK5XDC.js} +5 -5
- package/dist/{Documents-BCMEMP2J.js.map → Documents-7CMK5XDC.js.map} +1 -1
- package/dist/{Files-IPTA3GTC.js → Files-KFHBFAEL.js} +9 -9
- package/dist/{Files-IPTA3GTC.js.map → Files-KFHBFAEL.js.map} +1 -1
- package/dist/{Notepad-YROTVDE5.js → Notepad-3QOAGMND.js} +5 -5
- package/dist/{Notepad-YROTVDE5.js.map → Notepad-3QOAGMND.js.map} +1 -1
- package/dist/{PomodoroTimer-LPRIDZ7U.js → PomodoroTimer-QGQBN2OH.js} +4 -4
- package/dist/{PomodoroTimer-LPRIDZ7U.js.map → PomodoroTimer-QGQBN2OH.js.map} +1 -1
- package/dist/{Preview-Z2JANMZG.js → Preview-SEO3K7T6.js} +6 -6
- package/dist/{Preview-Z2JANMZG.js.map → Preview-SEO3K7T6.js.map} +1 -1
- package/dist/{Spreadsheet-GNDQKFRC.js → Spreadsheet-2ZRR3TVZ.js} +6 -6
- package/dist/{Spreadsheet-GNDQKFRC.js.map → Spreadsheet-2ZRR3TVZ.js.map} +1 -1
- package/dist/{Stock-MELZXEUY.js → Stock-OVVGE7US.js} +4 -4
- package/dist/{Stock-MELZXEUY.js.map → Stock-OVVGE7US.js.map} +1 -1
- package/dist/{Weather-QHKRQA4F.js → Weather-PKUXHYIL.js} +4 -4
- package/dist/{Weather-QHKRQA4F.js.map → Weather-PKUXHYIL.js.map} +1 -1
- package/dist/{WorldClock-ED46KQ3H.js → WorldClock-OUO4IYKF.js} +4 -4
- package/dist/{WorldClock-ED46KQ3H.js.map → WorldClock-OUO4IYKF.js.map} +1 -1
- package/dist/apps/index.js +15 -15
- package/dist/chunk-FSOC6W3V.js +7 -0
- package/dist/{chunk-VNPCQL2A.js.map → chunk-FSOC6W3V.js.map} +1 -1
- package/dist/{chunk-JIDY2KKZ.js → chunk-HEULN5GY.js} +4 -4
- package/dist/{chunk-JIDY2KKZ.js.map → chunk-HEULN5GY.js.map} +1 -1
- package/dist/{chunk-DW7EBCCP.js → chunk-TT56U4GY.js} +3 -3
- package/dist/{chunk-DW7EBCCP.js.map → chunk-TT56U4GY.js.map} +1 -1
- package/dist/{chunk-G2CXBFXR.js → chunk-UEJC6VOM.js} +5 -4
- package/dist/chunk-UEJC6VOM.js.map +1 -0
- package/dist/{chunk-STGKVZB3.js → chunk-XYP45LGG.js} +3 -3
- package/dist/{chunk-STGKVZB3.js.map → chunk-XYP45LGG.js.map} +1 -1
- package/dist/index.d.ts +33 -1
- package/dist/index.js +13 -9
- package/dist/index.js.map +1 -1
- package/dist/ui/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-G2CXBFXR.js.map +0 -1
- package/dist/chunk-VNPCQL2A.js +0 -7
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/windowRegistry/types.ts","../src/api/client.ts","../src/shell/WindowErrorBoundary.tsx","../src/shell/entityFetchPolicy.ts","../src/shell/LoadingSpinner.tsx","../src/shell/WindowManager.tsx","../src/shell/mobileSwipeStore.ts","../src/shell/perfEvents.ts","../src/shell/workArea.ts","../src/shell/Modal.tsx","../src/hooks/undoHistory.ts","../src/shell/UndoProvider.tsx"],"names":["jsx","Component","jsxs","counts","id","workArea","createContext","isValidElement","useContext","useEffect","useRef","useState","useSyncExternalStore","createPortal","confirm","a","useCallback","useLayoutEffect","cloneElement","content","Fragment","value","useMemo"],"mappings":"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","file":"chunk-UEJC6VOM.js","sourcesContent":["/**\n * Window registry types — generic shell concepts (no consumer-specific data).\n *\n * Two kinds of entries can be registered:\n * - PageRegistryEntry: a lazy-loaded React component rendered as a windowed\n * page (Calculator, Notepad, Sales Order list, etc.).\n * - ModalRegistryEntry: a detail-modal definition that fetches an entity\n * from a REST endpoint and hands it to a render function (Sales Order\n * detail, Bug Report detail, etc.).\n *\n * Consumers compose their full registry by passing entries to\n * `createWindowRegistry()` (see ./createWindowRegistry).\n */\nimport type { ReactNode, LazyExoticComponent } from 'react';\n\n/** Page window entry — renders a lazy-loaded page component. */\nexport interface PageRegistryEntry {\n component: LazyExoticComponent<any>;\n label: string;\n size?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl';\n allowPinOnTop?: boolean;\n /** Utility apps don't show as taskbar window tabs. */\n utility?: boolean;\n /** Initial position hint. */\n initialPosition?: 'top-right' | 'top-left';\n /** Widget mode: no title bar, drag via body, right-click context menu. */\n widget?: boolean;\n /** Compact title bar: smaller header with title + close only, no footer. */\n compact?: boolean;\n /** App-style window for self-chromed apps (Preview, Files, Browser, etc.):\n * small title bar with full controls, no body padding, no footer. */\n appStyle?: boolean;\n /** Flush body — keeps the STANDARD full title bar and footer, but drops the\n * body padding so the app's content (e.g. a `<SidebarLayout>`) sits flush to\n * the window edges. Implies `bodyScroll: false`; the app manages its own\n * scrolling. Use for two-pane / sidebar apps that want normal window chrome. */\n flushBody?: boolean;\n /** Custom window dimensions [width, height] in pixels. */\n dimensions?: [number, number];\n /** Auto-size window height to its content. Naturally-flowing content (forms,\n * settings, simple tools) shrinks the window to hug it; a fill-height root\n * (`h-full` / `flex-1` between a fixed header and footer) keeps the normal\n * size-ladder height and scrolls internally rather than collapsing. */\n autoHeight?: boolean;\n /** Floor for `autoHeight` (px). Defaults to 240. */\n autoMinHeight?: number;\n /** When true, openPage(path) opens a new instance each time instead of\n * activating an existing one. Each instance gets a unique window id and\n * the taskbar groups them under a single icon. */\n multiInstance?: boolean;\n /** Collapse this window with other windows that share the same\n * `taskbarGroup.key` into ONE taskbar button — even across DIFFERENT routes\n * — showing the group `label` and a window count. Without it, windows group\n * by route only (so only same-route `multiInstance` copies stack). `icon` is\n * a navIcon route key for the grouped button's icon. Use for a family of\n * related windows, e.g. a hub + the editors it opens. */\n taskbarGroup?: { key: string; label: string; icon?: string };\n /** navIcon route key for window title icon (e.g. '/orders'). */\n icon?: string;\n}\n\n/** Entity window entry — renders a detail modal with API data. */\nexport interface ModalRegistryEntry {\n /** API endpoint prefix — entity fetched via GET {endpoint}{id}/. */\n endpoint: string;\n /** How to render the detail content. */\n render: (entity: any, onClose: () => void, entityId?: string, editing?: boolean, setEditing?: (v: boolean) => void) => ReactNode;\n /** Generate modal title from entity data. Editing state passed for Edit button. */\n title: (entity: any, editing?: boolean, setEditing?: (v: boolean) => void) => ReactNode;\n /** Generate modal footer from entity data. */\n footer?: (entity: any) => ReactNode;\n /** Modal size. */\n size?: string;\n /** Custom open dimensions [width, height] in px (clamped to the viewport).\n * Overrides the size ladder and any stale per-window size the shell\n * persisted — use for content-heavy detail windows that must open large. */\n dimensions?: [number, number];\n /** If true, the component fetches its own data — pass ID, not entity. */\n selfFetching?: boolean;\n /** If true, the component renders its own Modal — skip outer Modal wrapper. */\n rendersOwnModal?: boolean;\n /** Query key prefix for React Query — must match what detail components invalidate. */\n queryKey?: string;\n /** Auto-size window height to its content. See PageRegistryEntry.autoHeight. */\n autoHeight?: boolean;\n /** Floor for `autoHeight` (px). Defaults to 240. */\n autoMinHeight?: number;\n /** App-style window: small title bar, no body padding, no footer. */\n appStyle?: boolean;\n /** Flush body — keeps the STANDARD full title bar and footer, but drops the\n * body padding so the detail content sits flush to the window edges.\n * Implies `bodyScroll: false`; the detail component manages its own\n * scrolling. Use for full-height tabbed / split-pane detail windows.\n * See PageRegistryEntry.flushBody. */\n flushBody?: boolean;\n /** navIcon route key for window title icon (e.g. '/orders'). */\n icon?: string;\n}\n\nexport type WindowRegistryEntry = PageRegistryEntry | ModalRegistryEntry;\n\nexport type WindowRegistry = Record<string, WindowRegistryEntry>;\n\n/** Type guard: true if entry is a page window (has `component`). */\nexport function isPageEntry(entry: WindowRegistryEntry): entry is PageRegistryEntry {\n return 'component' in entry;\n}\n\n/** Type guard: true if entry is an entity window (has `endpoint`). */\nexport function isEntityEntry(entry: WindowRegistryEntry): entry is ModalRegistryEntry {\n return 'endpoint' in entry;\n}\n\n/** Module-level registry — the package no longer ships entity/page data;\n * consumers register their composed registry once at app startup via\n * setShellWindowRegistry(). The shell's WindowManager reads from here at\n * every openEntity / openPage call. */\nlet _registry: WindowRegistry = {};\n\nexport function setShellWindowRegistry(registry: WindowRegistry): void {\n _registry = registry;\n}\n\n/** Live proxy onto the consumer-registered registry — reads always reflect\n * the latest setShellWindowRegistry() call. */\nexport const WINDOW_REGISTRY: WindowRegistry = new Proxy({} as WindowRegistry, {\n get(_t, prop: string) { return _registry[prop]; },\n has(_t, prop: string) { return prop in _registry; },\n ownKeys() { return Object.keys(_registry); },\n getOwnPropertyDescriptor(_t, prop: string) {\n if (prop in _registry) {\n return { configurable: true, enumerable: true, value: _registry[prop] };\n }\n return undefined;\n },\n});\n","/**\n * INTERNAL stub — bridges legacy `apiClient.get/patch('/auth/me/', ...)` calls\n * inside the shell to the new <ShellPrefsProvider> contract. This keeps the\n * package's copied source compiling without rewriting every call site at\n * once; consumer-supplied prefs flow through `<ShellPrefsProvider>`.\n *\n * Outside calls (anything not hitting `/auth/me/`) need the consumer to mount\n * <ShellEntityFetcherProvider> and wire `entityFetcher` on <WindowManager>.\n *\n * When `setShellApiClient` has not been called, HTTP methods resolve with an\n * empty payload instead of throwing — so consumers without a backend (the\n * Pages demo, for instance) can still mount the shell. A one-time console\n * warning surfaces the missing wiring without crashing the app.\n *\n * Long-term this file is removed when each call site migrates to\n * `useShellPrefs()` directly.\n */\nimport type { AxiosInstance } from 'axios';\n\nlet _apiClient: AxiosInstance | null = null;\n\n/** Consumer registers their own axios instance — typically the same one\n * they use elsewhere. The package only delegates HTTP to this. */\nexport function setShellApiClient(instance: AxiosInstance) {\n _apiClient = instance;\n}\n\n/** Whether the consumer has wired an api client. Internal shell queries gate\n * themselves on this so demos / consumers without a backend don't fire\n * doomed HTTP requests. */\nexport function isShellApiClientConfigured(): boolean {\n return _apiClient !== null;\n}\n\n// HTTP methods that resolve with empty data when no client is wired. Internal\n// callers gate on `isShellApiClientConfigured()` so this branch shouldn't\n// fire normally; it remains as a safety net for consumer-supplied apps that\n// import the shell's `apiClient` directly without setting one up.\nconst NOOP_METHODS = new Set([\n 'get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'request',\n]);\n\nconst apiClient: AxiosInstance = new Proxy({} as AxiosInstance, {\n get(_t, prop) {\n if (_apiClient) return (_apiClient as any)[prop];\n if (typeof prop === 'string' && NOOP_METHODS.has(prop)) {\n return () => Promise.resolve({ data: null, status: 0, statusText: '', headers: {}, config: {} });\n }\n return undefined;\n },\n});\n\nexport default apiClient;\n// Re-export the axios type for legacy code that imports it.\nexport type { AxiosInstance };\n","import { Component, type ErrorInfo, type ReactNode } from 'react';\n\n/** Inline crash state rendered in place of a window's content. Centers itself\n * in whatever space the body gives it; `onReload` resets the owning boundary\n * so the content remounts from scratch. */\nexport function WindowCrashedFallback({ error, onReload }: { error: Error; onReload: () => void }) {\n return (\n <div className=\"flex-1 flex flex-col items-center justify-center gap-3 px-6 py-12 text-center\">\n <svg className=\"h-8 w-8 text-amber-500\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z\" />\n </svg>\n <div className=\"min-w-0\">\n <p className=\"text-sm font-medium text-gray-700\">This window crashed</p>\n <p className=\"mt-1 text-xs text-gray-400 max-w-sm break-words\">{error.message || String(error)}</p>\n </div>\n <button type=\"button\" onClick={onReload}\n className=\"bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 text-sm font-medium rounded-lg\">\n Reload window\n </button>\n </div>\n );\n}\n\ninterface WindowErrorBoundaryProps {\n children: ReactNode;\n /** Replaces the default inline {@link WindowCrashedFallback}. `reset`\n * clears the caught error so the children remount. */\n fallback?: (error: Error, reset: () => void) => ReactNode;\n}\n\n/**\n * Error boundary around a window's content. Without it, a page/entity\n * component that throws during render propagates to the root and unmounts the\n * entire desktop. With it, only the crashed window's body is replaced — the\n * window chrome (close/minimize), the taskbar and every other window keep\n * running. Modal wraps its body in one; WindowManager wraps each whole window\n * in another as a last resort for crashes outside the body (e.g. a registry\n * `title()` throwing on malformed data).\n */\nexport default class WindowErrorBoundary extends Component<WindowErrorBoundaryProps, { error: Error | null }> {\n state: { error: Error | null } = { error: null };\n\n static getDerivedStateFromError(error: unknown) {\n return { error: error instanceof Error ? error : new Error(String(error)) };\n }\n\n componentDidCatch(error: Error, info: ErrorInfo) {\n console.error('[react-os-shell] window content crashed:', error, info.componentStack);\n }\n\n reset = () => this.setState({ error: null });\n\n render() {\n const { error } = this.state;\n if (error) {\n return this.props.fallback\n ? this.props.fallback(error, this.reset)\n : <WindowCrashedFallback error={error} onReload={this.reset} />;\n }\n return this.props.children;\n }\n}\n","/**\n * Retry / poll policy for a restored entity window's detail fetch.\n *\n * A window restored from the saved session (`RestoredRegistryModal` in\n * `WindowManager`) re-reads its entity on mount, on window focus, and on a 60s\n * fallback interval. That is right for a record that still exists — but it was\n * applied just as eagerly to one that does not. TanStack's default `retry: 3`\n * (1s/2s/4s backoff) on top of the 60s interval kept a permanently-404ing\n * window asking forever, ~4 requests a minute, for as long as the tab stayed\n * open. The window itself looks fine the whole time: it renders from the\n * `entitySnapshot` saved alongside it, so nothing surfaces to the user and\n * nothing ever stops.\n *\n * Production hit exactly that. One saved receipt window whose `entityId` was a\n * document number rather than a uuid produced 2,848 404s on\n * `GET /api/receipts/RP/` from a single browser in 48 hours — continuous,\n * overnight, resuming on every page load because the window list is restored\n * from localStorage.\n *\n * The rule: a 4xx is the server saying *this request is wrong*. Repeating it\n * verbatim cannot change the answer, so stop — do not retry it, and do not\n * keep polling it. Anything else (a 5xx, a timeout, an offline blip) is the\n * server or the network having a bad moment, and is still worth another go.\n */\n\n/** 4xx codes that are nonetheless worth retrying: the server is asking us to\n * wait, not telling us the request is malformed. */\nconst RETRYABLE_CLIENT_STATUSES = new Set([\n 408, // Request Timeout\n 429, // Too Many Requests\n]);\n\n/** Attempts after the first, for errors that are actually worth repeating.\n * Matches TanStack's own default so transient failures behave as before. */\nexport const ENTITY_FETCH_MAX_RETRIES = 3;\n\n/** The fallback poll cadence for a live entity window. WebSocket pushes are\n * the primary update path; this only covers the socket being unavailable. */\nexport const ENTITY_REFETCH_INTERVAL_MS = 60_000;\n\n/**\n * Whether `error` is a client error that repeating cannot fix (4xx, except the\n * explicitly retryable ones).\n *\n * An error with no numeric `response.status` — a network failure, a DNS blip,\n * an aborted request, anything thrown before a reply arrived — is deliberately\n * NOT permanent: those are exactly the cases retrying exists for.\n */\nexport function isPermanentClientError(error: unknown): boolean {\n const status = (error as { response?: { status?: unknown } } | null | undefined)?.response?.status;\n if (typeof status !== 'number') return false;\n return status >= 400 && status < 500 && !RETRYABLE_CLIENT_STATUSES.has(status);\n}\n\n/** `retry` for the entity detail query — never repeats a permanent 4xx. */\nexport function shouldRetryEntityFetch(failureCount: number, error: unknown): boolean {\n return !isPermanentClientError(error) && failureCount < ENTITY_FETCH_MAX_RETRIES;\n}\n\n/** `refetchInterval` for the entity detail query — stops polling a window\n * whose entity the server has told us is not there. */\nexport function entityRefetchInterval(error: unknown): number | false {\n return isPermanentClientError(error) ? false : ENTITY_REFETCH_INTERVAL_MS;\n}\n\n/**\n * Build the detail URL for an entity window.\n *\n * The id is encoded because it is not always the uuid the registry assumes: it\n * comes from saved session state and can be anything a past build (or a future\n * one) put there. An id carrying a `#` — a document number like `RP#60001`,\n * say — otherwise truncates the URL at the fragment before it is ever sent,\n * turning a wrong-but-legible request into a silently different one. Encoding\n * is a no-op for a uuid and keeps a bad id honest: it 404s as itself.\n */\nexport function entityDetailUrl(endpoint: string, entityId: string): string {\n return `${endpoint}${encodeURIComponent(entityId)}/`;\n}\n","export default function LoadingSpinner() {\n return <div className=\"flex items-center justify-center p-8 text-sm text-gray-400\">Loading...</div>;\n}\n","import { createContext, useContext, useState, useCallback, useEffect, useLayoutEffect, useRef, useSyncExternalStore, cloneElement, isValidElement, Suspense, type ReactNode, type ReactElement } from 'react';\nimport { useLocation } from 'react-router-dom';\nimport { createPortal } from 'react-dom';\nimport { useQuery, useQueryClient } from '@tanstack/react-query';\nimport apiClient, { isShellApiClientConfigured } from '../api/client';\nimport { useShellStrings } from './strings';\nimport { entityDetailUrl, entityRefetchInterval, shouldRetryEntityFetch } from './entityFetchPolicy';\nimport { WINDOW_REGISTRY, isPageEntry, isEntityEntry, type PageRegistryEntry, type ModalRegistryEntry } from '../windowRegistry/types';\nimport Modal, { triggerSplitView, modalDepthRef, getActiveModalId, subscribeActive, activateModal, ExposeBackdrop, WindowShortcutProvider, setWindowDefaultPosition, isPanelFullyVisible, panelOffscreenBearing, revealWindow, requestModalClose, type WindowShortcutSpec } from './Modal';\nimport WindowErrorBoundary, { WindowCrashedFallback } from './WindowErrorBoundary';\nimport { UndoProvider } from './UndoProvider';\nimport PartNumberDetailPopup from './PartNumberDetailPopup';\nimport LoadingSpinner from './LoadingSpinner';\nimport { navIcons } from '../shell-config/nav';\n\n\ninterface SavedBox {\n x: number; y: number; w: number; h: number; maximized: boolean;\n}\n\nexport interface MinimizedItem {\n id: string;\n type: 'part_number' | 'modal' | 'page';\n label: string;\n /** Route path for icon lookup (e.g. '/orders', '/invoices') */\n route?: string;\n savedBox?: SavedBox;\n /** Entity registry key (e.g. 'order', 'manufacturer') for restore */\n entityType?: string;\n /** Entity UUID for API fetch on cross-page restore */\n entityId?: string;\n /** Cached entity data for instant rendering while refetch happens */\n entitySnapshot?: any;\n /** windowKey of the window that was active when this opened — used by the\n * mobile swipe-to-back gesture to reveal the parent (e.g. the list a\n * detail entity was opened from) instead of the home wallpaper. Undefined\n * when this window opened directly from home / the start menu. */\n openedFrom?: string;\n}\n\ninterface MinimizedContextType {\n openWindows: MinimizedItem[];\n openEntity: (entityType: string, entityId: string, snapshot?: any, label?: string, route?: string) => void;\n openPage: (path: string) => void;\n closeEntity: (id: string) => void;\n /** @deprecated kept for backward compat — aliases openEntity/closeEntity */\n minimize: (item: MinimizedItem) => void;\n items: MinimizedItem[];\n restore: (item: MinimizedItem) => void;\n remove: (id: string) => void;\n restoreIfMinimized: (label: string) => boolean;\n openItems: MinimizedItem[];\n}\n\nconst MinimizedContext = createContext<MinimizedContextType>({\n openWindows: [],\n openEntity: () => {},\n openPage: () => {},\n closeEntity: () => {},\n minimize: () => {},\n items: [],\n restore: () => {},\n remove: () => {},\n restoreIfMinimized: () => false,\n openItems: [],\n});\n\ntype WindowDirtyRegistration = (id: symbol, dirty: boolean) => () => void;\n\nconst WindowDirtyContext = createContext<WindowDirtyRegistration | null>(null);\n\n/**\n * Registers controlled dirty state with the enclosing shell window, so closing\n * it asks before discarding. Works in both kinds of window the shell owns the\n * Modal for: page windows and entity/detail windows.\n *\n * Ignored — deliberately, and silently — in the one place the shell has no\n * Modal to guard: a registry entry with `rendersOwnModal`, where the consumer\n * renders its own Modal and should pass that Modal `dirty` directly. Also a\n * no-op outside a WindowManager entirely.\n */\nexport function useWindowDirty(dirty: boolean): void {\n const register = useContext(WindowDirtyContext);\n // Lazily minted so a re-render doesn't allocate a Symbol it then discards.\n const idRef = useRef<symbol | null>(null);\n if (idRef.current === null) idRef.current = Symbol('window-dirty');\n\n useLayoutEffect(() => {\n if (!register) return;\n return register(idRef.current!, dirty);\n }, [register, dirty]);\n}\n\n/**\n * The dirty-registration store one shell window owns.\n *\n * Lives here rather than inside PageWindow because entity windows need exactly\n * the same thing: a set of registrations from whatever the window is currently\n * rendering, aggregated to the single boolean the Modal's close guard reads.\n */\nfunction useWindowDirtyRegistry(): { dirty: boolean; registerDirty: WindowDirtyRegistration } {\n const registrations = useRef(new Map<symbol, boolean>());\n const [dirty, setDirty] = useState(false);\n const registerDirty = useCallback<WindowDirtyRegistration>((id, value) => {\n const updateAggregate = () => {\n const next = Array.from(registrations.current.values()).some(Boolean);\n setDirty(current => current === next ? current : next);\n };\n registrations.current.set(id, value);\n updateAggregate();\n return () => {\n registrations.current.delete(id);\n updateAggregate();\n };\n }, []);\n return { dirty, registerDirty };\n}\n\nexport function useWindowManager() {\n return useContext(MinimizedContext);\n}\n\nfunction RestoredPartNumber({ partNumber, savedBox, onClose, onMinimize }: { partNumber: string; savedBox?: SavedBox; onClose: () => void; onMinimize: (sb: SavedBox) => void }) {\n const { data: pn, isLoading } = useQuery({\n queryKey: ['part-number-lookup', partNumber],\n enabled: isShellApiClientConfigured(),\n queryFn: () => apiClient.get('/products/part-numbers/', { params: { search: partNumber, page_size: 1 } }).then(r => {\n const results = r.data?.results ?? r.data ?? [];\n return results.find((p: any) => p.part_number === partNumber) || results[0] || null;\n }),\n });\n\n return (\n <Modal\n open={true}\n onClose={onClose}\n onMinimize={onMinimize}\n initialBox={savedBox}\n size=\"2xl\"\n title={pn ? (\n <span className=\"flex items-center gap-2\">\n {pn.part_number}\n <span className={`inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${pn.is_active ? 'bg-green-100 text-green-800' : 'bg-gray-300 text-gray-800'}`}>{pn.is_active ? 'Active' : 'Inactive'}</span>\n </span>\n ) : partNumber}\n footer={pn ? (\n <>\n <span className=\"text-gray-500\">{pn.brand_name} · {pn.category_name || 'Wheel'} · {pn.manufacturer_mid || '—'}</span>\n <span className=\"text-gray-400\">Stock: <b className=\"text-gray-700\">{pn.stock_quantity ?? 0}</b></span>\n </>\n ) : undefined}\n >\n {isLoading ? <div className=\"flex items-center justify-center py-12\"><LoadingSpinner /></div> : pn ? <PartNumberDetailPopup pn={pn} /> : <p className=\"text-sm text-gray-500\">Part number not found.</p>}\n </Modal>\n );\n}\n\n/** Window → desktop-shortcut spec for the Modal window menu's \"Add to\n * Desktop\" item. Pages save as entityType 'page' keyed by route; entities\n * by registry key + id. Windows with no stable identity return null and\n * get no menu item. */\nfunction shortcutSpecFor(item: MinimizedItem): WindowShortcutSpec | null {\n const entityType = item.type === 'page' ? 'page' : (item.entityType || '');\n const entityId = item.type === 'page' ? (item.route || '') : (item.entityId || '');\n if (!entityType || !entityId) return null;\n return { entityType, entityId, label: item.label };\n}\n\nfunction PageWindow({ item, onClose, accentRgb }: { item: MinimizedItem; onClose: () => void; accentRgb?: string }) {\n const { dirty, registerDirty } = useWindowDirtyRegistry();\n\n const raw = WINDOW_REGISTRY[item.route!];\n if (!raw || !isPageEntry(raw)) return null;\n const entry = raw as PageRegistryEntry;\n const Component = entry.component;\n return (\n <Modal open={true} onClose={onClose} icon={navIcons[item.route!]} title={entry.label} size={entry.size || '2xl'} dirty={dirty} allowPinOnTop={entry.allowPinOnTop} initialPosition={entry.initialPosition} widget={entry.widget} compact={entry.compact} appStyle={entry.appStyle} flushBody={entry.flushBody} autoHeight={entry.autoHeight} autoMinHeight={entry.autoMinHeight} dimensions={entry.dimensions} windowKey={item.id} openedFromKey={item.openedFrom} accentRgb={accentRgb}>\n <WindowDirtyContext.Provider value={registerDirty}>\n <Suspense fallback={<div className=\"flex items-center justify-center py-12\"><LoadingSpinner /></div>}>\n <Component />\n </Suspense>\n </WindowDirtyContext.Provider>\n </Modal>\n );\n}\n\n/** Star button to favorite a document — saves to preferences.favorite_documents */\nexport function DocFavStar({ entityType, entityId, label }: { entityType: string; entityId: string; label: string }) {\n const shellStrings = useShellStrings();\n const queryClient = useQueryClient();\n const { data: profile } = useQuery({ queryKey: ['my-profile-sidebar'], enabled: isShellApiClientConfigured(), queryFn: () => apiClient.get('/auth/me/').then(r => r.data) });\n const favDocs: { entityType: string; entityId: string; label: string }[] = (profile?.preferences || {}).favorite_documents || [];\n const isFav = favDocs.some(d => d.entityType === entityType && d.entityId === entityId);\n\n const toggle = () => {\n const next = isFav\n ? favDocs.filter(d => !(d.entityType === entityType && d.entityId === entityId))\n : [...favDocs, { entityType, entityId, label }];\n apiClient.patch('/auth/me/', { preferences: { favorite_documents: next } }).then(() => {\n queryClient.invalidateQueries({ queryKey: ['my-profile-sidebar'] });\n });\n };\n\n return (\n <button onClick={toggle} title={isFav ? shellStrings.taskbar.removeFromDesktop : shellStrings.taskbar.addToDesktop}\n className={`shrink-0 transition-colors ${isFav ? 'text-yellow-500 hover:text-yellow-600' : 'text-gray-300 hover:text-yellow-400'}`}>\n <svg className=\"h-4 w-4\" fill={isFav ? '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 );\n}\n\nfunction RestoredRegistryModal({ item, onClose, onMinimize, accentRgb }: { item: MinimizedItem; onClose: () => void; onMinimize: (sb: SavedBox) => void; accentRgb?: string }) {\n const raw = WINDOW_REGISTRY[item.entityType!];\n if (!raw || !isEntityEntry(raw)) return null;\n const entry = raw as ModalRegistryEntry;\n\n const [editing, setEditing] = useState(false);\n const { dirty, registerDirty } = useWindowDirtyRegistry();\n\n // Use queryKey from registry (matches what detail components invalidate) or derive from endpoint\n const qkPrefix = entry.queryKey || entry.endpoint.replace(/^\\/|\\/$/g, '').split('/').pop() || item.entityType;\n const isDuplicate = item.entitySnapshot?._duplicate;\n // Unsaved \"create\" windows carry a placeholder id like `new-1783415283039`\n // (openEntity mints these for a not-yet-persisted record). There is nothing to\n // fetch — the GET would always 404 — so skip the detail query, exactly as we\n // do for duplicate windows. The snapshot already drives the create form.\n const isDraft = typeof item.entityId === 'string' && item.entityId.startsWith('new-');\n const { data: entity, isLoading, refetch } = useQuery({\n queryKey: [qkPrefix, item.entityId],\n queryFn: () => apiClient.get(entityDetailUrl(entry.endpoint, String(item.entityId))).then(r => r.data),\n initialData: item.entitySnapshot,\n initialDataUpdatedAt: 0, // Treat snapshot as stale so query refetches immediately\n enabled: !entry.selfFetching && !isDuplicate && !isDraft && isShellApiClientConfigured(),\n staleTime: 0,\n refetchOnWindowFocus: true,\n refetchOnMount: 'always',\n // Fallback polling; WebSocket provides instant updates. A window whose\n // entity the server says is not there stops polling instead of asking\n // every 60s forever — see entityFetchPolicy.\n refetchInterval: query => entityRefetchInterval(query.state.error),\n refetchIntervalInBackground: false,\n retry: shouldRetryEntityFetch,\n });\n\n // Refetch entity data whenever this modal is activated (brought to front)\n useEffect(() => {\n if (entry.selfFetching || isDuplicate || isDraft) return;\n const handler = () => { refetch(); };\n window.addEventListener('modal-reorder', handler);\n return () => window.removeEventListener('modal-reorder', handler);\n }, [refetch, entry.selfFetching, isDuplicate, isDraft]);\n\n // Chrome close (the title-bar X / ESC) while editing exits edit mode instead\n // of closing the window.\n //\n // Unless a registration says the window is dirty: the Modal's close guard has\n // then already asked \"discard changes?\" and been told yes, and dropping the\n // user back into a still-open detail view would answer a different question\n // than the one they were asked.\n //\n // This guard is for the CHROME only. entry.render() gets the raw `onClose`:\n // a render-callback close is the app saying \"this window is done\" — most\n // critically after a delete, where the guard used to swallow the close and\n // strand the window on a detail view of a record that no longer existed\n // (`onDeleted={onClose}` was a silent no-op for a pristine form).\n const handleClose = useCallback(() => {\n if (editing && !dirty) {\n setEditing(false);\n } else {\n onClose();\n }\n }, [editing, dirty, onClose]);\n\n const titleBase = entry.selfFetching\n ? item.label\n : (entity ? entry.title(entity, editing, setEditing) : item.label);\n\n const entityIconKey = (entry as ModalRegistryEntry).icon;\n const entityIcon = entityIconKey ? navIcons[entityIconKey] : null;\n const titleContent = titleBase;\n\n const footerContent = (!entry.selfFetching && entity && entry.footer && !isDuplicate)\n ? entry.footer(entity)\n : undefined;\n\n // Components that render their own Modal — skip outer wrapper\n if (entry.rendersOwnModal) {\n // selfFetching components handle their own data loading — always render them\n if (entry.selfFetching) {\n return (\n <Suspense fallback={<LoadingSpinner />}>\n {entry.render(entity ?? item.entitySnapshot, onClose, item.entityId, editing, setEditing)}\n </Suspense>\n );\n }\n return (\n <Suspense fallback={<LoadingSpinner />}>\n {isLoading && !entity ? (\n <LoadingSpinner />\n ) : entity ? (\n entry.render(entity, onClose, item.entityId, editing, setEditing)\n ) : (\n <Modal open={true} onClose={onClose} title={item.label} size={(entry.size || '2xl') as any}>\n <p className=\"text-sm text-gray-500 py-8 text-center\">Not found.</p>\n </Modal>\n )}\n </Suspense>\n );\n }\n\n return (\n <Modal\n open={true}\n onClose={handleClose}\n onMinimize={onMinimize}\n initialBox={item.savedBox}\n icon={entityIcon}\n title={titleContent}\n footer={footerContent}\n copyText={item.label}\n windowKey={item.id}\n openedFromKey={item.openedFrom}\n size={(entry.size || '2xl') as any}\n dirty={dirty}\n dimensions={entry.dimensions}\n autoHeight={entry.autoHeight}\n autoMinHeight={entry.autoMinHeight}\n appStyle={entry.appStyle}\n flushBody={entry.flushBody}\n accentRgb={accentRgb}\n >\n <WindowDirtyContext.Provider value={registerDirty}>\n <Suspense fallback={<LoadingSpinner />}>\n {entry.selfFetching ? (\n entry.render(null, onClose, item.entityId, editing, setEditing)\n ) : isLoading && !entity ? (\n <LoadingSpinner />\n ) : entity ? (\n entry.render(entity, onClose, item.entityId, editing, setEditing)\n ) : (\n <p className=\"text-sm text-gray-500 py-8 text-center\">Not found.</p>\n )}\n </Suspense>\n </WindowDirtyContext.Provider>\n </Modal>\n );\n}\n\n\n/** Find a modal panel by its window key (the openWindows item id). */\nfunction findPanelByWindowKey(key: string): HTMLElement | null {\n return document.querySelector(`[data-modal-panel][data-window-key=\"${key}\"]`) as HTMLElement | null;\n}\n\n/** Look up the windowKey of whichever modal is currently active. Used when\n * opening a new window so we can record what was on screen at the moment of\n * open as the new window's `openedFrom` — drives the mobile swipe-to-back\n * gesture's \"reveal the parent\" behavior. Returns undefined when nothing is\n * active (i.e. the user opened from home / start menu). */\nfunction currentlyActiveWindowKey(): string | undefined {\n const activeId = getActiveModalId();\n if (!activeId) return undefined;\n const panel = document.querySelector(`[data-modal-panel][data-modal-id=\"${activeId}\"]`) as HTMLElement | null;\n return panel?.getAttribute('data-window-key') ?? undefined;\n}\n\n/** Module-level mirror of windowKey → route for the currently-open\n * windows. Kept in sync by the Provider's effect (see below). Lets\n * non-React code (e.g. a bug-report submit callback) ask \"which app\n * window is the user currently looking at\" without grabbing context.\n * Bug-report and similar HeadlessUI dialogs don't go through the\n * shell's Modal store, so the active window key keeps pointing at\n * the underlying app window even while such a dialog is open. */\nconst routeByWindowKey = new Map<string, string>();\n\n/** Public, framework-free helper: route ('/orders', '/qc-reports', …)\n * of the window the user is currently focused on. Returns undefined\n * when no app window is active (start menu / dashboard with nothing\n * open). Useful for code paths that fire outside React render — the\n * shell consumer can stamp metadata on a payload (e.g. \"which module\n * is this bug report against?\") without needing to lift state. */\nexport function getActiveWindowRoute(): string | undefined {\n const key = currentlyActiveWindowKey();\n if (!key) return undefined;\n return routeByWindowKey.get(key);\n}\n\n/** Find a modal panel whose title text contains `label`. Used as a fallback\n * when no window key is available (legacy code paths). */\nfunction findPanelByLabel(label: string): HTMLElement | null {\n const panels = document.querySelectorAll('[data-modal-panel]');\n for (const p of Array.from(panels)) {\n const t = p.querySelector('[data-window-title]');\n if (t?.textContent?.includes(label)) return p as HTMLElement;\n }\n return null;\n}\n\n// Aero-peek: while the user hovers a taskbar thumbnail, the window it belongs\n// to is raised above its siblings and stays fully opaque, while every other\n// window falls back a layer and fades to 40%. Toggled purely via a body class\n// + a marker attribute — never touches a panel's inline styles, so it cleans\n// up for free and can't be stranded. The dim animates (transition is scoped to\n// `.rosh-peeking`); dropping the class snaps every window crisply back.\n// Mirrors `ensureGestureStyle` in Modal.tsx.\n//\n// The raise has to be `!important`: a panel's z-index is an inline style (see\n// Modal.tsx, `zIndex: pinnedOnTop ? 999 : zIndex + 1`), and an author\n// `!important` declaration is the only thing in the cascade that beats inline\n// without writing to `panel.style` — which a stray `modal-reorder` would\n// clobber — or calling `activateModal`, which would turn a hover into a click.\n//\n// 249 sits above every window in the ladder (50 + index*10 + 1) but below the\n// taskbar at z-250, so a peeked window never paints over the very thumbnail\n// you are hovering. A window that is currently pinned on top rides the 999\n// lane instead, so raising it to 249 would *demote* it — hence the\n// `[data-pinned-top]` exemption, the same reason Windows leaves topmost\n// windows out of Aero Peek. (`data-utility` is not the test: it only means the\n// window *may* be pinned, and every bundled app sets it.)\nconst PEEK_STYLE_ID = 'rosh-peek-style';\nconst PEEK_Z = 249;\nfunction ensurePeekStyle() {\n if (typeof document === 'undefined' || document.getElementById(PEEK_STYLE_ID)) return;\n const style = document.createElement('style');\n style.id = PEEK_STYLE_ID;\n style.textContent =\n 'body.rosh-peeking [data-modal-panel]{transition:opacity .18s ease}' +\n 'body.rosh-peeking [data-modal-panel]:not([data-peek-focus]){opacity:.4}' +\n 'body.rosh-peeking [data-modal-panel][data-peek-focus]{opacity:1}' +\n `body.rosh-peeking [data-modal-panel][data-peek-focus]:not([data-pinned-top]){z-index:${PEEK_Z}!important}` +\n // Someone who turned transparency off gets the raise, not a fade.\n 'html.rosh-reduce-transparency body.rosh-peeking [data-modal-panel]:not([data-peek-focus]){opacity:.92}' +\n '@media (prefers-reduced-motion:reduce){body.rosh-peeking [data-modal-panel]{transition:none}}';\n document.head.appendChild(style);\n}\n\n/** Bring `panel` forward by fading every other open window to 40%. Passing\n * null clears the effect. Re-marking a different panel while already peeking\n * keeps the body class on, so sliding between thumbnails cross-fades the two\n * windows instead of flashing everything back to full opacity. */\nfunction setPeekFocus(panel: HTMLElement | null) {\n if (typeof document === 'undefined') return;\n ensurePeekStyle();\n document.querySelectorAll('[data-modal-panel][data-peek-focus]')\n .forEach(el => el.removeAttribute('data-peek-focus'));\n if (panel) panel.setAttribute('data-peek-focus', '');\n document.body.classList.toggle('rosh-peeking', !!panel);\n}\n\n/** Drop the peek — restore every window to full opacity. */\nfunction clearPeekFocus() {\n if (typeof document === 'undefined') return;\n document.body.classList.remove('rosh-peeking');\n document.querySelectorAll('[data-modal-panel][data-peek-focus]')\n .forEach(el => el.removeAttribute('data-peek-focus'));\n}\n\n/** Render a single window snapshot. The card sizes itself to the source\n * panel's aspect ratio (clamped to maxW × maxH) so the snapshot fills\n * the card with no empty letterboxing. When the source window is\n * hidden (zero rect — e.g. show-desktop just minimised it) we fall\n * back to a frosted card with the icon + label so the preview is\n * never empty. When `titleAbove` is true the bottom overlay label\n * is dropped — the parent renders the title in a row above instead. */\n/** Snapshot card for an open window. Exported for the mobile switcher.\n * See JSDoc above for sizing/snapshot semantics. */\nexport function ThumbCard({ id, label, maxW, maxH, titleAbove = false, onClick, onClose }: {\n id: string; label: string; maxW: number; maxH: number; titleAbove?: boolean; onClick?: () => void; onClose?: () => void;\n}) {\n const shellStrings = useShellStrings();\n const previewRef = useRef<HTMLDivElement>(null);\n const [size, setSize] = useState<{ w: number; h: number }>({ w: maxW, h: Math.round(maxH * 0.75) });\n const [hasSnapshot, setHasSnapshot] = useState(false);\n\n useLayoutEffect(() => {\n const inner = previewRef.current;\n if (!inner) return;\n const target = findPanelByWindowKey(id) ?? findPanelByLabel(label);\n if (!target) { setHasSnapshot(false); return; }\n const rect = target.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) { setHasSnapshot(false); return; }\n const ratio = Math.min(maxW / rect.width, maxH / rect.height);\n const cardW = Math.max(80, Math.round(rect.width * ratio));\n const cardH = Math.max(60, Math.round(rect.height * ratio));\n setSize({ w: cardW, h: cardH });\n setHasSnapshot(true);\n const clone = target.cloneNode(true) as HTMLElement;\n clone.style.position = 'absolute';\n clone.style.top = '0'; clone.style.left = '0';\n clone.style.right = 'auto'; clone.style.bottom = 'auto';\n clone.style.width = rect.width + 'px';\n clone.style.height = rect.height + 'px';\n clone.style.transform = `scale(${ratio})`;\n clone.style.transformOrigin = 'top left';\n clone.style.pointerEvents = 'none';\n clone.style.animation = 'none';\n // A live panel carries an inline z-index (Modal.tsx: `zIndex: pinnedOnTop ?\n // 999 : zIndex + 1`) and the clone inherits it — which floated the snapshot\n // over the card's own overlays and buried the close button. Flatten it; the\n // container below also traps whatever the cloned subtree carries.\n clone.style.zIndex = 'auto';\n clone.removeAttribute('data-modal-panel');\n clone.removeAttribute('data-modal-id');\n clone.removeAttribute('data-window-key');\n clone.querySelectorAll<HTMLElement>('[role=\"dialog\"], [data-portal]').forEach(el => { el.style.display = 'none'; });\n inner.innerHTML = '';\n inner.appendChild(clone);\n return () => { inner.innerHTML = ''; };\n }, [id, label, maxW, maxH]);\n\n return (\n <div\n style={{ width: size.w, height: size.h }}\n className=\"relative rounded-md overflow-hidden bg-white/95 border border-gray-300 shadow-md cursor-pointer ring-2 ring-transparent group-hover:ring-blue-400 transition shrink-0\"\n onClick={onClick}\n >\n {/* `z-0` makes the snapshot layer its own stacking context, so no z-index\n inside the cloned window (a pinned panel, a sticky header, a dropdown)\n can climb over the card's title strip or close button. */}\n <div ref={previewRef} className=\"absolute inset-0 z-0 overflow-hidden\" />\n {!hasSnapshot && (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center text-gray-400 bg-gray-50\">\n <svg className=\"h-6 w-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M3.75 6.75A2.25 2.25 0 016 4.5h12a2.25 2.25 0 012.25 2.25v10.5A2.25 2.25 0 0118 19.5H6a2.25 2.25 0 01-2.25-2.25V6.75z M3.75 9h16.5\" />\n </svg>\n <span className=\"mt-1 text-[10px] uppercase tracking-wide\">Hidden</span>\n </div>\n )}\n {!titleAbove && (\n <div className=\"absolute bottom-0 left-0 right-0 z-10 px-2 py-1 text-[10px] font-medium text-white bg-gradient-to-t from-black/80 to-transparent truncate pointer-events-none\">\n {label}\n </div>\n )}\n {onClose && (\n <button\n onClick={(e) => { e.stopPropagation(); onClose(); }}\n className=\"absolute top-1 right-1 z-20 h-5 w-5 rounded-full bg-gray-900/90 ring-1 ring-white/80 shadow-sm hover:bg-red-500 text-white flex items-center justify-center\"\n title={shellStrings.taskbar.closeWindow}\n >\n <svg className=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={3}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" /></svg>\n </button>\n )}\n </div>\n );\n}\n\n/** Hover popover — single thumbnail for a single window, or a row of\n * thumbnails for a grouped set so the user can pick which instance to\n * activate. Each thumb sizes to its window's aspect ratio (clamped).\n * After mount, the popover measures its own bounding box and centers\n * itself horizontally on the button below — fixed-width math doesn't\n * hold once cards reflect their source aspect ratios. */\nfunction TaskbarTabPreview({ items, anchorEl, onActivate, onClose, onMouseEnter, onMouseLeave }: {\n items: MinimizedItem[]; anchorEl: HTMLElement; onActivate: (id: string) => void; onClose: (id: string) => void;\n onMouseEnter: () => void; onMouseLeave: () => void;\n}) {\n const shellStrings = useShellStrings();\n const MAX_W = 240;\n const MAX_H = 160;\n const isGroup = items.length > 1;\n const popoverRef = useRef<HTMLDivElement>(null);\n // Provisional position (off-screen above viewport) so we can measure the\n // actual rendered size before snapping into place. This avoids a single\n // mis-aligned frame.\n const [pos, setPos] = useState<{ left: number; top: number; ready: boolean }>({ left: -9999, top: -9999, ready: false });\n const [taskbarPos, setTaskbarPos] = useState<string>(() =>\n typeof document !== 'undefined'\n ? (getComputedStyle(document.documentElement).getPropertyValue('--taskbar-position')?.trim() || 'bottom')\n : 'bottom'\n );\n\n useLayoutEffect(() => {\n const el = popoverRef.current;\n if (!el) return;\n const measure = () => {\n const tabRect = anchorEl.getBoundingClientRect();\n const popRect = el.getBoundingClientRect();\n const tbPos = getComputedStyle(document.documentElement).getPropertyValue('--taskbar-position')?.trim() || 'bottom';\n setTaskbarPos(tbPos);\n let left = tabRect.left + tabRect.width / 2 - popRect.width / 2;\n let top: number;\n if (tbPos === 'top') {\n top = tabRect.bottom + 8;\n } else if (tbPos === 'left') {\n left = tabRect.right + 8;\n top = tabRect.top + tabRect.height / 2 - popRect.height / 2;\n } else if (tbPos === 'right') {\n left = tabRect.left - popRect.width - 8;\n top = tabRect.top + tabRect.height / 2 - popRect.height / 2;\n } else {\n // bottom\n top = tabRect.top - popRect.height - 8;\n }\n // Clamp to viewport.\n left = Math.max(8, Math.min(left, window.innerWidth - popRect.width - 8));\n top = Math.max(8, Math.min(top, window.innerHeight - popRect.height - 8));\n setPos({ left, top, ready: true });\n };\n measure();\n // Re-measure when child cards finalise their size (they pick their\n // dimensions in a useLayoutEffect after the first paint).\n const ro = new ResizeObserver(measure);\n ro.observe(el);\n return () => ro.disconnect();\n }, [anchorEl, items.length]);\n\n // Safety net: always drop the peek when the popover unmounts, so the\n // desktop never gets stranded dimmed if the mouse never fires a leave\n // (e.g. the popover closes because its taskbar button was activated).\n useEffect(() => clearPeekFocus, []);\n\n // When the taskbar is on top, the popover hangs below the tab, so the\n // snapshot should sit closest to the tab (i.e. on top of the popover) and\n // the title sits beneath it. Every other taskbar position keeps the title\n // above the snapshot.\n const titleBelow = taskbarPos === 'top';\n const titleClass = `${titleBelow ? 'mt-1' : 'mb-1'} max-w-[240px] truncate text-[11px] font-medium text-gray-900 bg-white/80 px-2 py-0.5 rounded shadow-sm ring-2 ring-transparent transition group-hover:ring-blue-400`;\n\n return createPortal(\n <div\n ref={popoverRef}\n style={{\n position: 'fixed', left: pos.left, top: pos.top, zIndex: 9999,\n maxWidth: 'calc(100vw - 16px)',\n opacity: pos.ready ? 1 : 0,\n }}\n className={isGroup ? 'flex gap-2 flex-wrap' : ''}\n onMouseEnter={onMouseEnter}\n onMouseLeave={() => { clearPeekFocus(); onMouseLeave(); }}\n >\n {items.map(it => {\n const panel = findPanelByWindowKey(it.id) ?? findPanelByLabel(it.label);\n // Null unless this window is (partly) outside the work area. The arrow\n // lives here, on the taskbar chrome, rather than floating on the\n // desktop: the thumbnail already shows the window's content, so all\n // that's missing is which way it went — and clicking fetches it back.\n const bearing = panel ? panelOffscreenBearing(panel) : null;\n return (\n <div\n key={it.id}\n className=\"group flex flex-col items-center\"\n onMouseEnter={() => setPeekFocus(panel)}\n >\n {!titleBelow && <span className={titleClass}>{it.label}</span>}\n <ThumbCard\n id={it.id}\n label={it.label}\n maxW={MAX_W}\n maxH={MAX_H}\n titleAbove\n onClick={() => onActivate(it.id)}\n onClose={() => onClose(it.id)}\n />\n {titleBelow && <span className={titleClass}>{it.label}</span>}\n {bearing !== null && (\n <span\n title={shellStrings.taskbar.offscreenHint}\n className=\"mt-1 inline-flex items-center gap-1 rounded bg-amber-500 px-1.5 py-0.5 text-[10px] font-semibold text-white shadow-sm\"\n >\n <svg className=\"h-3 w-3\" style={{ transform: `rotate(${bearing}deg)` }} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={3}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 12h14m0 0l-5-5m5 5l-5 5\" />\n </svg>\n Off screen\n </span>\n )}\n </div>\n );\n })}\n </div>,\n document.body,\n );\n}\n\nfunction TaskbarWindows({ openWindows, onRemove, onSplitView, onActivate, onActivateById }: {\n openWindows: MinimizedItem[]; onRemove: (id: string) => void; onSplitView: () => void;\n onActivate: (label: string) => void;\n onActivateById: (id: string) => void;\n}) {\n const shellStrings = useShellStrings();\n const [target, setTarget] = useState<HTMLElement | null>(null);\n useEffect(() => {\n const el = document.getElementById('taskbar-windows');\n if (el) setTarget(el);\n else { const t = setInterval(() => { const e = document.getElementById('taskbar-windows'); if (e) { setTarget(e); clearInterval(t); } }, 100); return () => clearInterval(t); }\n }, []);\n\n const activeModalId = useSyncExternalStore(subscribeActive, getActiveModalId);\n\n // Off-screen markers are read straight off the panels' live rects, so the\n // tabs need re-rendering whenever a window settles (`modal-geometry`, fired\n // once per drag/resize/snap/reveal — never per frame) or the viewport moves\n // under them.\n const [, setGeomTick] = useState(0);\n useEffect(() => {\n const bump = () => setGeomTick(t => t + 1);\n window.addEventListener('modal-geometry', bump);\n window.addEventListener('resize', bump);\n return () => {\n window.removeEventListener('modal-geometry', bump);\n window.removeEventListener('resize', bump);\n };\n }, []);\n\n // Re-render the taskbar when any window's title changes so the dynamic\n // title (e.g. \"Untitled - Spreadsheets\") shows up on the tab.\n const [, forceTick] = useState(0);\n useEffect(() => {\n const onTitle = () => forceTick(t => t + 1);\n window.addEventListener('window-title-update', onTitle);\n return () => window.removeEventListener('window-title-update', onTitle);\n }, []);\n const liveTitle = (label: string): string => {\n const panel = findPanelByLabel(label);\n const titleEl = panel?.querySelector('[data-window-title]');\n return titleEl?.textContent?.trim() || label;\n };\n\n const [hoveredItems, setHoveredItems] = useState<MinimizedItem[] | null>(null);\n const [hoveredAnchor, setHoveredAnchor] = useState<HTMLElement | null>(null);\n const hoverTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const handleEnter = (items: MinimizedItem[], el: HTMLElement) => {\n if (hoverTimerRef.current) { clearTimeout(hoverTimerRef.current); hoverTimerRef.current = null; }\n hoverTimerRef.current = setTimeout(() => { setHoveredItems(items); setHoveredAnchor(el); }, 350);\n };\n const handleLeave = () => {\n if (hoverTimerRef.current) { clearTimeout(hoverTimerRef.current); hoverTimerRef.current = null; }\n hoverTimerRef.current = setTimeout(() => { setHoveredItems(null); setHoveredAnchor(null); }, 150);\n };\n const cancelLeave = () => {\n if (hoverTimerRef.current) { clearTimeout(hoverTimerRef.current); hoverTimerRef.current = null; }\n };\n // Filter out utility apps (e.g. calculator) from taskbar tabs\n const tabWindows = openWindows.filter(item => !item.route || !(WINDOW_REGISTRY[item.route] as PageRegistryEntry)?.utility);\n if (!target || tabWindows.length === 0) return null;\n\n // Group windows into one taskbar button with a count badge instead of N\n // tabs. Same-route `multiInstance` copies stack; windows that declare a\n // shared `taskbarGroup.key` also stack ACROSS routes (e.g. the Storefront\n // console + the editors it opens), taking the group's label + icon.\n type Group = { key: string; route?: string; label: string; items: MinimizedItem[] };\n const groups: Group[] = [];\n const idx = new Map<string, number>();\n for (const item of tabWindows) {\n const entry = item.route ? (WINDOW_REGISTRY[item.route] as PageRegistryEntry | undefined) : undefined;\n const grp = entry?.taskbarGroup;\n const key = grp?.key ?? item.route ?? `entity:${item.id}`;\n const i = idx.get(key);\n if (i !== undefined) {\n groups[i].items.push(item);\n } else {\n idx.set(key, groups.length);\n // A cross-route group shows its own label + icon; a plain route group\n // shows the window's registry label + its own route icon (as before).\n const label = grp?.label ?? entry?.label ?? item.label;\n groups.push({ key, route: grp?.icon ?? item.route, label, items: [item] });\n }\n }\n\n return createPortal(\n <>\n {groups.map(group => {\n const icon = group.route ? navIcons[group.route] : null;\n // The \"primary\" item for activation/preview: the most recently opened.\n const primary = group.items[group.items.length - 1];\n // Group is active if any of its instances is the active modal.\n let isActive = false;\n if (activeModalId) {\n const panel = document.querySelector(`[data-modal-id=\"${activeModalId}\"]`);\n if (panel) {\n const titleEl = panel.querySelector('[data-window-title]');\n const titleText = titleEl?.textContent ?? '';\n isActive = group.items.some(it => titleText.includes(it.label));\n }\n }\n const isGrouped = group.items.length > 1;\n // Ambient \"you have a window out there\" signal, visible before the\n // user hovers anything.\n const offscreen = group.items.some(it => {\n const p = findPanelByWindowKey(it.id) ?? findPanelByLabel(it.label);\n return !!p && !isPanelFullyVisible(p);\n });\n\n return (\n <button key={group.key} onClick={() => onActivateById(primary.id)}\n onMouseEnter={(e) => handleEnter(group.items, e.currentTarget)}\n onMouseLeave={handleLeave}\n onDoubleClick={(e) => { e.stopPropagation(); window.dispatchEvent(new CustomEvent('modal-center', { detail: { label: primary.label } })); }}\n onContextMenu={(e) => { e.preventDefault(); e.stopPropagation(); window.dispatchEvent(new CustomEvent('modal-context-menu', { detail: { label: primary.label, x: e.clientX, y: e.clientY } })); }}\n style={{ width: 'var(--window-tab-width, 200px)', fontSize: 'var(--window-tab-font-size, 12px)' }}\n data-tab-group={group.key}\n className={`group relative flex items-center gap-1.5 rounded-lg px-3 py-2 font-medium transition-all min-w-0 shrink ${\n isActive ? 'bg-blue-100/60 border border-blue-400/60 text-blue-700' : 'bg-gray-50/40 border border-gray-200/40 text-gray-700 hover:bg-gray-200/40'\n }`}>\n {icon && isValidElement(icon)\n ? cloneElement(icon as ReactElement, { className: `h-3.5 w-3.5 shrink-0 ${isActive ? 'text-blue-600' : 'text-gray-400'}` })\n : <svg className={`h-3.5 w-3.5 shrink-0 ${isActive ? 'text-blue-600' : 'text-gray-400'}`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4\" /></svg>\n }\n <span className=\"truncate flex-1\">{isGrouped ? group.label : liveTitle(primary.label)}</span>\n {offscreen && (\n <span title={shellStrings.taskbar.offscreenDot} className=\"shrink-0 h-1.5 w-1.5 rounded-full bg-amber-500\" />\n )}\n {isGrouped && (\n <span className=\"shrink-0 px-1.5 py-0.5 rounded-full bg-blue-500/80 text-white text-[10px] font-bold leading-none\">{group.items.length}</span>\n )}\n {!isGrouped && (\n <span role=\"button\" onClick={(e) => { e.stopPropagation(); onRemove(primary.id); }} className=\"ml-auto text-gray-400 hover:text-red-500 shrink-0 opacity-0 group-hover:opacity-100 transition-opacity\">\n <svg className=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" /></svg>\n </span>\n )}\n </button>\n );\n })}\n <div className=\"flex-1\" />\n {tabWindows.length >= 2 && (\n <button onClick={onSplitView} title={shellStrings.taskbar.expose}\n className=\"flex items-center gap-1 rounded px-2 py-1 text-[11px] font-medium text-blue-600 border border-blue-300 hover:bg-blue-50 transition-colors shrink-0\">\n {/* 2×2 grid icon — exposé toggle, mirrors macOS Mission Control. */}\n <svg className=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <rect x=\"3.5\" y=\"3.5\" width=\"7\" height=\"7\" rx=\"1\" />\n <rect x=\"13.5\" y=\"3.5\" width=\"7\" height=\"7\" rx=\"1\" />\n <rect x=\"3.5\" y=\"13.5\" width=\"7\" height=\"7\" rx=\"1\" />\n <rect x=\"13.5\" y=\"13.5\" width=\"7\" height=\"7\" rx=\"1\" />\n </svg>\n Exposé\n </button>\n )}\n {hoveredItems && hoveredAnchor && (\n <TaskbarTabPreview\n items={hoveredItems}\n anchorEl={hoveredAnchor}\n onActivate={(id) => { onActivateById(id); setHoveredItems(null); setHoveredAnchor(null); }}\n onClose={(id) => { onRemove(id); setHoveredItems(null); setHoveredAnchor(null); }}\n onMouseEnter={cancelLeave}\n onMouseLeave={handleLeave}\n />\n )}\n </>,\n target\n );\n}\n\nconst SESSION_KEY = 'erp_open_windows';\n\nfunction saveWindowState(windows: MinimizedItem[]) {\n try {\n const serializable = windows.map(w => ({ ...w, entitySnapshot: undefined }));\n localStorage.setItem(SESSION_KEY, JSON.stringify(serializable));\n } catch { /* storage full */ }\n}\n\nconst DEFAULT_WIDGETS: MinimizedItem[] = [\n { id: 'page:/weather', type: 'page', label: 'Weather', route: '/weather' },\n { id: 'page:/currency', type: 'page', label: 'Currency Converter', route: '/currency' },\n { id: 'page:/world-clock', type: 'page', label: 'World Clock', route: '/world-clock' },\n];\n\n/**\n * Lay the first-run default widgets out in a tidy top-left column — mirroring\n * the Widget Manager's placement — so a brand-new account opens with its widgets\n * stacked down the left edge instead of piled in the centre (which is what\n * Modal's `calcWindowed` no-saved-position fallback does). We seed the shared\n * window-position store *before* the widgets mount, so each Modal restores from\n * it on open. `setWindowDefaultPosition` is a no-op once a real saved position\n * exists, so this never disturbs a returning user who has dragged things around.\n *\n * Every default widget is `autoHeight`, so it re-measures to its content on open\n * — the heights here are only first-paint estimates for a non-overlapping stack.\n */\nfunction seedDefaultWidgetPositions(widgets: MinimizedItem[]) {\n const PAD = 20, GAP = 16, MAX_AUTO_H = 220;\n const cs = getComputedStyle(document.documentElement);\n const tbH = parseInt(cs.getPropertyValue('--taskbar-height')) || 0;\n const tbW = parseInt(cs.getPropertyValue('--taskbar-width')) || 0;\n const tbPos = cs.getPropertyValue('--taskbar-position').trim() || 'bottom';\n const sidebarW = parseInt(cs.getPropertyValue('--sidebar-width')) || 0;\n const leftStart = (tbPos === 'left' ? tbW : 0) + sidebarW + PAD;\n const topStart = (tbPos === 'top' ? tbH : 0) + PAD;\n const maxBottom = window.innerHeight - (tbPos === 'bottom' ? tbH : 0) - PAD;\n const rightLimit = window.innerWidth - PAD;\n\n let x = leftStart, y = topStart;\n for (const item of widgets) {\n if (!item.route) continue;\n const e = WINDOW_REGISTRY[item.route];\n if (!e || !isPageEntry(e)) continue;\n const entry = e as PageRegistryEntry;\n const w = entry.dimensions?.[0] ?? 320;\n const h = entry.dimensions?.[1] ?? 240;\n const stackH = entry.autoHeight ? Math.min(h, MAX_AUTO_H) : h;\n // Wrap to a fresh column when this one is full — but only if the next column\n // still fits on-screen, so a widget never gets pushed off the right edge.\n if (y > topStart && y + stackH > maxBottom && x + (w + GAP) + w <= rightLimit) {\n x += w + GAP;\n y = topStart;\n }\n setWindowDefaultPosition(item.id, { x, y, w, h });\n y += stackH + GAP;\n }\n}\n\n/** Heal a restored session against the legacy id-collision bug. Builds before\n * 3.14.1 derived a modal window's `id` from its (non-unique) label, so two\n * records sharing a label persisted with the same `id` — duplicate React keys\n * left one window un-closeable, and a plain reload restored it just as broken.\n * Re-key any collided modal to its stable entity identity (matching what\n * `openEntity` now emits) and drop any that still collide (the same entity\n * persisted twice), so a reload resolves a stuck pair instead of resurrecting\n * it. Non-collided windows keep their stored id so their saved box/z-order is\n * preserved. */\nfunction healWindowIds(items: MinimizedItem[]): MinimizedItem[] {\n const counts = new Map<string, number>();\n for (const it of items) counts.set(it.id, (counts.get(it.id) ?? 0) + 1);\n const seen = new Set<string>();\n const out: MinimizedItem[] = [];\n for (const it of items) {\n let id = it.id;\n if ((counts.get(it.id) ?? 0) > 1 && it.type === 'modal' && it.entityType && it.entityId) {\n id = `${it.entityType}:${it.entityId}`;\n }\n if (seen.has(id)) continue;\n seen.add(id);\n out.push(id === it.id ? it : { ...it, id });\n }\n return out;\n}\n\nfunction restoreWindowState(): MinimizedItem[] {\n try {\n if (window.location.pathname === '/login') return [];\n if (!localStorage.getItem('access_token')) return [];\n const stored = localStorage.getItem(SESSION_KEY);\n if (stored) return healWindowIds(JSON.parse(stored));\n } catch { /* corrupt data */ }\n // First run for this account — no saved session yet. Seed a top-left stack so\n // the default widgets don't open piled in the centre of the desktop.\n seedDefaultWidgetPositions(DEFAULT_WIDGETS);\n return DEFAULT_WIDGETS;\n}\n\nconst AUTH_PAGES = ['/login', '/forgot-password', '/reset-password', '/force-change-password'];\n\nexport function WindowManagerProvider({ children, windowAccentForRoute }: {\n children: ReactNode;\n /** SG#00372: optional per-section window accent. Called with each open\n * window's route ('/sales-orders', '/payments', …); return an `R G B`\n * triple (e.g. '91 141 190') to give that window a thin accent stripe\n * between its title bar and body (see Modal's `accentRgb`), or undefined\n * for no accent. The stripe is drawn only for users who have switched it\n * on in Customization → Windows; the mapping is still worth wiring\n * regardless, since it also publishes `--window-accent-rgb` per window.\n * The consumer owns the route→section→colour mapping; omitting the prop\n * keeps every window exactly as before. */\n windowAccentForRoute?: (route: string) => string | undefined;\n}) {\n const location = useLocation();\n const isAuthPage = AUTH_PAGES.some(p => location.pathname.startsWith(p));\n const [openWindows, setOpenWindows] = useState<MinimizedItem[]>(() => restoreWindowState());\n const openWindowsRef = useRef(openWindows);\n useLayoutEffect(() => { openWindowsRef.current = openWindows; }, [openWindows]);\n\n // Persist window state on every change — but don't save empty on initial mount (login page)\n const hasUserActed = useRef(false);\n useEffect(() => {\n if (openWindows.length > 0) hasUserActed.current = true;\n if (hasUserActed.current) saveWindowState(openWindows);\n\n // Mirror windowKey → route into the module-level map exported as\n // `getActiveWindowRoute()`. Snapshot semantics: we rebuild from\n // scratch on every change so closed windows drop out cleanly.\n routeByWindowKey.clear();\n for (const w of openWindows) {\n if (w.route) routeByWindowKey.set(w.id, w.route);\n }\n }, [openWindows]);\n\n // Modal calls this only after its own close guard has allowed the close.\n // Keep it private so public controls cannot bypass dirty confirmation, and\n // so a confirmed close cannot recurse back into requestClose.\n const forceRemoveWindow = useCallback((id: string) => {\n setOpenWindows(prev => prev.filter(m => m.id !== id));\n }, []);\n\n const requestClose = useCallback((id: string) => {\n // A mounted shell Modal owns the close decision, including dirty-state\n // confirmation. Windows that render no keyed Modal keep the legacy direct\n // removal fallback because there is no guard to ask.\n if (!findPanelByWindowKey(id)) {\n forceRemoveWindow(id);\n return;\n }\n requestModalClose(id);\n }, [forceRemoveWindow]);\n\n // Bring the just-spawned window with `windowKey` to the front after React\n // renders its panel. Without this, mountModal would slot the new modal into\n // its previously-saved z-order (from localStorage), placing it behind the\n // currently active window — wrong for user-initiated opens.\n const activateAfterMount = (windowKey: string) => {\n setTimeout(() => {\n const panel = document.querySelector(`[data-modal-panel][data-window-key=\"${windowKey}\"]`);\n const mid = panel?.getAttribute('data-modal-id');\n if (mid) activateModal(mid);\n }, 50);\n };\n\n const openEntity = useCallback((entityType: string, entityId: string, snapshot?: any, label?: string, route?: string) => {\n if (!WINDOW_REGISTRY[entityType] || !isEntityEntry(WINDOW_REGISTRY[entityType])) return;\n // The window's identity must equal the dedup identity (entityType + entityId),\n // NOT the human `label`. Two different records that share a label — e.g. two\n // wheel finishes on the same design (\"Yakama\") — would otherwise both get\n // `id = label`, so they collided: duplicate React keys in the render map and a\n // shared `windowKey`/`boxKey`. Closing one then filtered both out of state but\n // left the other's portal panel stranded, its close button a no-op. Keying by\n // the entity identity guarantees no two live windows can share an id (that's\n // exactly what the `existing` dedup below already enforces).\n const id = `${entityType}:${entityId}`;\n const openedFrom = currentlyActiveWindowKey();\n // If already open, just activate it\n setOpenWindows(prev => {\n // Compare entityId as a string so a numeric id from one call site and the\n // string form from another (`42` vs '42') still dedup to one window — and\n // stay consistent with `id` above, which coerces both to the same string.\n const existing = prev.find(m => m.entityType === entityType && String(m.entityId) === String(entityId));\n if (existing) {\n activateAfterMount(existing.id);\n return prev;\n }\n activateAfterMount(id);\n return [...prev, {\n id, type: 'modal' as const, label: label || entityId,\n route: route || window.location.pathname,\n entityType, entityId, entitySnapshot: snapshot,\n openedFrom,\n }];\n });\n }, []);\n\n /** Open a page as a window — reuse if already open */\n const openPage = useCallback((path: string) => {\n if (!WINDOW_REGISTRY[path] || !isPageEntry(WINDOW_REGISTRY[path])) return;\n const entry = WINDOW_REGISTRY[path] as PageRegistryEntry;\n if (entry.widget) {\n const existing = openWindowsRef.current.find(m => m.type === 'page' && m.route === path);\n if (existing) {\n requestClose(existing.id);\n return;\n }\n }\n const openedFrom = currentlyActiveWindowKey();\n setOpenWindows(prev => {\n // Multi-instance pages always spawn a new window with a unique id.\n // The window is identified by `id`, never by label — so every instance\n // keeps the plain registry label. The instance count surfaces only as the\n // taskbar group's blue count badge (derived live at render). Baking a\n // `${label} N` ordinal into the stored label used to strand a stale\n // number on a lone leftover window (close #1 of two, and #2's tab still\n // read \"Designs 2\" with no badge, since a single window never groups).\n if (entry.multiInstance) {\n const id = `page:${path}:${Math.random().toString(36).slice(2, 8)}`;\n activateAfterMount(id);\n return [...prev, {\n id, type: 'page' as const,\n label: entry.label,\n route: path,\n openedFrom,\n }];\n }\n const existing = prev.find(m => m.type === 'page' && m.route === path);\n if (existing) {\n // A same-tick duplicate widget open may reach this updater before the\n // latest committed state reaches openWindowsRef. Do not turn that race\n // into an unguarded toggle; the next explicit call uses requestClose.\n if (entry.widget) return prev;\n activateAfterMount(existing.id);\n return prev;\n }\n const id = `page:${path}`;\n activateAfterMount(id);\n return [...prev, {\n id, type: 'page' as const, label: entry.label,\n route: path,\n openedFrom,\n }];\n });\n }, [requestClose]);\n\n // Backward compat stubs\n const minimize = useCallback(() => {}, []);\n const restore = useCallback(() => {}, []);\n const closeEntity = requestClose;\n const remove = requestClose;\n const restoreIfMinimized = () => false;\n\n return (\n <MinimizedContext.Provider value={{ openWindows, openEntity, openPage, closeEntity, minimize, items: [], openItems: openWindows, restore, remove, restoreIfMinimized }}>\n {children}\n\n {/* Taskbar windows */}\n <TaskbarWindows\n openWindows={openWindows}\n onRemove={requestClose}\n onSplitView={triggerSplitView}\n onActivate={(label) => {\n const panels = document.querySelectorAll('[data-modal-panel]');\n panels.forEach(p => {\n const titleEl = p.querySelector('[data-window-title]');\n if (titleEl?.textContent?.includes(label)) {\n const mid = p.getAttribute('data-modal-id');\n if (mid) activateModal(mid);\n }\n });\n }}\n onActivateById={(id) => {\n const panel = document.querySelector(`[data-modal-panel][data-window-key=\"${id}\"]`) as HTMLElement | null;\n if (!panel) return;\n // Focusing a window you can't see achieves nothing — fetch it back\n // first. `revealWindow` activates it as part of the rescue.\n if (!isPanelFullyVisible(panel)) { revealWindow(id); return; }\n const mid = panel.getAttribute('data-modal-id');\n if (mid) activateModal(mid);\n }}\n />\n\n {/* Exposé backdrop — singleton overlay shown when exposé mode is on. */}\n <ExposeBackdrop />\n\n {/* All open windows — pages and entities (hidden on auth pages).\n Modal already guards its body content; this outer boundary is the\n last resort for crashes outside the body — a registry title()/footer()\n throwing on malformed data, or a rendersOwnModal component dying\n before its Modal mounts — so one bad window can never unmount the\n desktop. The fallback swaps the window for a plain Modal carrying the\n same crash state; its close button still removes the window. */}\n {!isAuthPage && openWindows.map(item => {\n // SG#00372: resolve the window's per-section accent from its route.\n const accentRgb = item.route ? windowAccentForRoute?.(item.route) : undefined;\n return (\n <WindowErrorBoundary\n key={item.id}\n fallback={(error, reset) => (\n <Modal open={true} onClose={() => forceRemoveWindow(item.id)} title={item.label} size=\"md\" autoHeight windowKey={item.id}>\n <WindowCrashedFallback error={error} onReload={reset} />\n </Modal>\n )}\n >\n <WindowShortcutProvider spec={shortcutSpecFor(item)}>\n {/* One undo stack per open window. Mounting it here rather than in\n each form means every window has one without asking, and it is\n torn down with the window — history is the unsaved edit, and a\n closed window has none. Costs nothing until something registers\n through useUndoable/useUndoableState. A read-only form nests its\n own <UndoProvider canEdit={false}> to shadow this one.\n\n `windowId` is what keeps the stacks apart. The provider sits\n above the <Modal> and so cannot see it, and its ⌘Z listener is\n on `window` and so hears every press in every window; the id is\n how this one recognises a press as its own. It is the same\n value the Modal gets as `windowKey` below. */}\n <UndoProvider windowId={item.id}>\n {item.type === 'page' ? (\n <PageWindow item={item} onClose={() => forceRemoveWindow(item.id)} accentRgb={accentRgb} />\n ) : (\n <RestoredRegistryModal\n item={item}\n onClose={() => forceRemoveWindow(item.id)}\n onMinimize={() => {}}\n accentRgb={accentRgb}\n />\n )}\n </UndoProvider>\n </WindowShortcutProvider>\n </WindowErrorBoundary>\n );\n })}\n </MinimizedContext.Provider>\n );\n}\n","/**\n * Module-level state shared by all <Modal> instances on mobile during a\n * swipe-to-back gesture. The swiping window publishes its parent windowKey\n * here when the gesture starts; the parent Modal reads it (via\n * `useSyncExternalStore`) and renders itself visible underneath the sliding\n * panel even though it isn't the active window. When the gesture ends or\n * cancels, the parent key is cleared and the parent goes back to hidden.\n */\n\nlet _parentKey: string | null = null;\nconst subs = new Set<() => void>();\n\nexport function getSwipingParentKey(): string | null {\n return _parentKey;\n}\n\nexport function setSwipingParentKey(key: string | null): void {\n if (_parentKey === key) return;\n _parentKey = key;\n for (const cb of subs) cb();\n}\n\nexport function subscribeSwipingParentKey(cb: () => void): () => void {\n subs.add(cb);\n return () => { subs.delete(cb); };\n}\n","/**\n * Shell interaction marks, folded into every perf-log record.\n *\n * The HUD can see that frames were dropped and it can see that the pointer\n * moved, but \"the pointer moved\" covers wandering across the desktop and\n * opening a third-level flyout, and only one of those repaints a frosted\n * surface. The first version of the log conflated them, so the readings that\n * mattered most — the frame the start menu opened on, the frame a window was\n * dragged across — arrived indistinguishable from an idle mouse. A report full\n * of anonymous samples points at nothing.\n *\n * So the places that do the expensive things say so. Menus mark themselves when\n * they open; window drags and resizes mark themselves for as long as they run.\n * Everything here is a plain counter drained once per flush interval — no\n * subscriptions, no allocation per event, nothing that would make marking an\n * event cost more than the event.\n *\n * Marks accumulate only while the HUD is mounted (`setPerfCollecting`). That is\n * not really about cost — incrementing a number is free — but about honesty: a\n * counter that had been climbing since page load would attribute a morning's\n * worth of menu opens to whichever 500ms interval happened to drain it first.\n */\n\n/** Which menu layer opened. The distinction is the point: the root menu is one\n * surface appearing, a flyout is a second one appearing *over* it, and the\n * cost of the second is what people report. */\nexport type MenuLayer = 'menu' | 'submenu';\n\n/** One flush interval's worth of marks. */\nexport interface PerfEventCounts {\n /** Root start-menu opens. */\n menus: number;\n /** Flyout opens — the 2nd- and 3rd-level menus. */\n submenus: number;\n /** The last menu or flyout opened, so a slow one can be named rather than\n * merely counted. Null when no menu opened during the interval. */\n menuKey: string | null;\n /** Milliseconds spent dragging a window by its title bar. */\n moveMs: number;\n /** Milliseconds spent dragging a window's resize handle. */\n resizeMs: number;\n}\n\nconst empty = (): PerfEventCounts => ({ menus: 0, submenus: 0, menuKey: null, moveMs: 0, resizeMs: 0 });\n\nlet collecting = false;\nlet counts = empty();\n\n/** Shared no-op, so a gesture that starts while the HUD is closed allocates\n * nothing at all. */\nconst NOOP = () => {};\n\n/** Start or stop accumulating. Both directions reset — see the module\n * docstring on why a stale count is worse than no count. */\nexport function setPerfCollecting(on: boolean): void {\n collecting = on;\n counts = empty();\n}\n\n/** Record that a menu surface opened. `key` names it (a section label, a route)\n * so the summary can rank flyouts against each other. */\nexport function markMenuOpen(layer: MenuLayer, key: string): void {\n if (!collecting) return;\n if (layer === 'submenu') counts.submenus++;\n else counts.menus++;\n counts.menuKey = key;\n}\n\n/**\n * Record a window drag or resize for as long as it runs. Returns the end\n * function; calling it twice adds the span once.\n *\n * Duration rather than a count because these are the gestures whose *cost is\n * their length* — a drag that stutters for four seconds and a drag that lasted\n * one frame are the same event and very different reports. The span is credited\n * to the interval it ends in, which can straddle a flush boundary; that is\n * accepted rather than apportioned, because a drag long enough to straddle two\n * intervals is already the thing being investigated.\n */\nexport function beginWindowGesture(kind: 'move' | 'resize'): () => void {\n if (!collecting) return NOOP;\n const startedAt = performance.now();\n let ended = false;\n return () => {\n if (ended) return;\n ended = true;\n // The HUD may have been closed mid-gesture, which reset the counters.\n // Adding to them now would seed the next session with a stale span.\n if (!collecting) return;\n const elapsed = performance.now() - startedAt;\n if (kind === 'move') counts.moveMs += elapsed;\n else counts.resizeMs += elapsed;\n };\n}\n\n/** Take the accumulated marks and start a fresh interval. */\nexport function drainPerfEvents(): PerfEventCounts {\n const drained = counts;\n counts = empty();\n return drained;\n}\n","/**\n * Work-area geometry — the rectangle a maximized window occupies.\n *\n * Layout owns the chrome (taskbar, sidebar strip) and publishes its sizes as\n * CSS custom properties on <html>; everything here derives from those, so the\n * maths has a single input and no React dependency. Modal reads them live\n * rather than through context, which is what lets an open window react to a\n * preference change without remounting.\n */\n\n/** Width of the persistent left strip that sidebar layout mode reserves. */\nexport const SIDEBAR_STRIP_W = 280;\n\nexport interface Box { x: number; y: number; w: number; h: number }\n\n/** The viewport minus the taskbar, and minus the sidebar strip when one is reserved. */\nexport function computeMaximizedBox(): Box {\n const cs = getComputedStyle(document.documentElement);\n const taskbarH = parseInt(cs.getPropertyValue('--taskbar-height')) || 0;\n const taskbarW = parseInt(cs.getPropertyValue('--taskbar-width')) || 0;\n const tbPos = cs.getPropertyValue('--taskbar-position')?.trim() || 'bottom';\n const sidebarW = parseInt(cs.getPropertyValue('--sidebar-width')) || 0;\n return {\n x: (tbPos === 'left' ? taskbarW : 0) + sidebarW,\n y: tbPos === 'top' ? taskbarH : 0,\n w: window.innerWidth - (tbPos === 'left' || tbPos === 'right' ? taskbarW : 0) - sidebarW,\n h: window.innerHeight - (tbPos === 'top' || tbPos === 'bottom' ? taskbarH : 0),\n };\n}\n\n/**\n * Is this saved box really \"the whole work area\" — i.e. was it saved by a\n * maximized window rather than chosen by the user?\n *\n * Both axes must fill, which is what separates a maximized box from the\n * dangerous near-misses: a half-screen snap fills the height only, a short\n * full-width window fills the width only. The tolerance absorbs sub-pixel\n * rects and browser zoom, where an exact match would miss the real boxes.\n *\n * Widths are matched against the work area both with and without the sidebar\n * strip, because a box saved in sidebar mode has to be recognised from classic\n * mode — and vice versa, since the caller may run either side of Layout\n * releasing the strip.\n */\nexport function boxFillsWorkArea(box: Box, workArea: Box, sidebarReserved: boolean): boolean {\n const TOL = 4;\n const otherW = sidebarReserved ? workArea.w + SIDEBAR_STRIP_W : workArea.w - SIDEBAR_STRIP_W;\n const fillsWidth = Math.abs(box.w - workArea.w) <= TOL || Math.abs(box.w - otherW) <= TOL;\n return Math.abs(box.h - workArea.h) <= TOL && fillsWidth;\n}\n\n/** Whether sidebar layout mode currently reserves its left strip. */\nexport function isSidebarStripReserved(): boolean {\n return (parseInt(getComputedStyle(document.documentElement).getPropertyValue('--sidebar-width')) || 0) > 0;\n}\n\n/**\n * Sidebar layout mode locks every non-widget window to the maximized box.\n * Published by Layout as `--layout-mode` on <html>.\n */\nexport function readAlwaysMaximizedFlag(): boolean {\n if (typeof document === 'undefined') return false;\n return getComputedStyle(document.documentElement).getPropertyValue('--layout-mode')?.trim() === 'sidebar';\n}\n","import { useEffect, useLayoutEffect, useCallback, useMemo, useRef, useState, createContext, useContext, useSyncExternalStore, cloneElement, isValidElement, type ReactNode, type ReactElement } from 'react';\nimport { createPortal } from 'react-dom';\nimport { XMarkIcon } from '@heroicons/react/24/outline';\nimport { confirm } from './ConfirmDialog';\nimport { useWindowManager } from './WindowManager';\nimport { glassStyle as getGlassStyle } from '../utils/glass';\nimport { PopupMenu, PopupMenuItem, PopupMenuDivider } from './PopupMenu';\nimport { useShellStrings } from './strings';\nimport { useIsMobile } from './useIsMobile';\nimport { getSwipingParentKey, setSwipingParentKey, subscribeSwipingParentKey } from './mobileSwipeStore';\nimport { beginWindowGesture } from './perfEvents';\nimport WindowErrorBoundary from './WindowErrorBoundary';\nimport { useShellPrefs } from './ShellPrefs';\nimport { boxFillsWorkArea, computeMaximizedBox, isSidebarStripReserved, readAlwaysMaximizedFlag } from './workArea';\nimport { runEscapeInterceptors } from './escapeInterceptors';\n\n/** Context that passes the modal's unique ID to children */\nconst ModalIdContext = createContext<string>('');\n\n/** Desktop-shortcut spec for the window menu's \"Add to Desktop\" item —\n * the shape saved into `prefs.favorite_documents` (what <Desktop> renders\n * as icons). Pages use entityType 'page' keyed by route; entities use\n * their registry key + id. */\nexport interface WindowShortcutSpec {\n entityType: string;\n entityId: string;\n label: string;\n}\n\nconst WindowShortcutContext = createContext<WindowShortcutSpec | null>(null);\n\n/** Wraps each top-level app window (see WindowManagerProvider) so its Modal\n * can offer \"Add to Desktop\" — including consumer components that render\n * their own Modal, which a child-component approach can't reach. The\n * outermost Modal consumes the spec and re-provides null, so nested\n * dialogs don't repeat the item. */\nexport function WindowShortcutProvider({ spec, children }: { spec: WindowShortcutSpec | null; children: ReactNode }) {\n return <WindowShortcutContext.Provider value={spec}>{children}</WindowShortcutContext.Provider>;\n}\n\n/**\n * Extract just the text from a title ReactNode for non-interactive\n * contexts like the expose-mode tile header — strips buttons, inputs,\n * kbd hints, and SVG decorations so only the document/page name shows.\n *\n * The title can be anything from a plain string to a flex row with an\n * inline edit button and a copy icon. Tiles in expose mode are scaled\n * down and not interactive (clicking focuses the window), so rendering\n * the whole tree is at best ugly and at worst clipped.\n */\nconst TITLE_STRIP_TYPES = new Set(['button', 'input', 'textarea', 'select', 'kbd', 'svg']);\n\n/**\n * What Cmd/Ctrl+Enter clicks when a window has no `<form>` to `requestSubmit()`.\n *\n * Two kinds of entry, in descending order of how much we trust them:\n *\n * - **Explicit** — `type=\"submit\"`, the bare `data-submit` attribute, and the\n * `.btn-submit` utility class. These are how a consumer *declares* \"this is\n * the submit\", so they are the ones to reach for in new markup.\n * - **Legacy colour heuristic** — `.bg-green-600` / `.bg-blue-600`. From before\n * the explicit opt-ins existed, when the submit button was identified by\n * being the blue (or green, for approve/post) one. Kept because consumers\n * still ship plenty of it; do not add more colours here.\n *\n * `.btn-submit` was missing from this list until 4.76.0, which made converting a\n * button from a hardcoded `bg-blue-600` fill to the themable `.btn-submit`\n * utility silently drop it out of the selector — Cmd+Enter stopped working while\n * the button's own ⌘⏎ badge went on advertising it. The admin portal hit this\n * across ~26 buttons and worked around it by also adding `data-submit`.\n *\n * NOTE: a comma-separated `querySelector` returns the first match in **document\n * order**, not the first *selector* that matches — so the order of the entries\n * below is documentation, not precedence. When a panel holds several candidates,\n * the earliest one in the DOM wins.\n */\nexport const MODAL_SUBMIT_SELECTOR =\n 'button[type=\"submit\"], button[data-submit], button.btn-submit, button.bg-green-600, button.bg-blue-600';\nfunction extractTitleText(node: ReactNode): string {\n if (node == null || typeof node === 'boolean') return '';\n if (typeof node === 'string') return node;\n if (typeof node === 'number') return String(node);\n if (Array.isArray(node)) return node.map(extractTitleText).join('');\n if (isValidElement(node)) {\n const el = node as ReactElement<{ children?: ReactNode }>;\n const tag = typeof el.type === 'string' ? el.type : '';\n if (TITLE_STRIP_TYPES.has(tag)) return '';\n return extractTitleText(el.props?.children);\n }\n return '';\n}\n\n/** Hook for widget components to register a settings handler for the right-click menu. */\nexport function useWidgetSettings(handler: () => void) {\n const id = useContext(ModalIdContext);\n useEffect(() => {\n if (!id) return;\n const listener = (e: Event) => { if ((e as CustomEvent).detail === id) handler(); };\n window.addEventListener('widget-open-settings', listener);\n return () => window.removeEventListener('widget-open-settings', listener);\n }, [handler, id]);\n}\n\n/** Registry for extra window menu items added by child components */\nconst _extraMenuItems: Record<string, { label: string; icon?: React.ReactNode; onClick: () => void }[]> = {};\n\n/** Hook to add custom items to the window title menu from inside a modal */\nexport function useWindowMenuItem(label: string, onClick: () => void, icon?: React.ReactNode) {\n const id = useContext(ModalIdContext);\n useEffect(() => {\n if (!id) return;\n if (!_extraMenuItems[id]) _extraMenuItems[id] = [];\n const item = { label, icon, onClick };\n _extraMenuItems[id].push(item);\n return () => { _extraMenuItems[id] = (_extraMenuItems[id] || []).filter(i => i !== item); };\n }, [id, label, onClick, icon]);\n}\n\n/** Component that updates the surrounding window's title bar. Render anywhere\n * inside a Modal-rendered page. Cross-bundle safe (uses DOM traversal rather\n * than React Context, which has separate instances in each bundle). */\nexport function WindowTitle({ title }: { title: string }) {\n const ref = useRef<HTMLSpanElement>(null);\n useEffect(() => {\n const handle = setTimeout(() => {\n const panel = ref.current?.closest('[data-modal-id]');\n const id = panel?.getAttribute('data-modal-id');\n if (id) window.dispatchEvent(new CustomEvent('window-title-update', { detail: { id, title } }));\n }, 0);\n return () => clearTimeout(handle);\n }, [title]);\n return <span ref={ref} style={{ display: 'none' }} aria-hidden=\"true\" />;\n}\n\n/** @deprecated Use <WindowTitle> instead — the hook variant doesn't work\n * across bundle boundaries (apps barrel has its own ModalIdContext). */\nexport function useWindowTitle(_title: string) {\n // Intentionally a no-op now. Kept for type compatibility during migration.\n}\n\n/**\n * Portal component — renders children into the nearest Modal's footer actions area.\n * position=\"left\" for destructive actions (Delete), default is right for primary actions.\n */\nexport function CopyButton({ text }: { text: string }) {\n const [copied, setCopied] = useState(false);\n const handleCopy = (e: React.MouseEvent) => {\n e.stopPropagation();\n navigator.clipboard.writeText(text).then(() => {\n setCopied(true);\n setTimeout(() => setCopied(false), 1500);\n });\n };\n return (\n <button onClick={handleCopy} title={copied ? 'Copied!' : `Copy ${text}`}\n className=\"shrink-0 text-gray-400 hover:text-gray-600 transition-colors\">\n {copied ? (\n <svg className=\"w-4 h-4 text-green-600\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" /></svg>\n ) : (\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\" /></svg>\n )}\n </button>\n );\n}\n\n// Context to pass action container refs from Modal to ModalActions\ninterface ModalActionsCtx {\n rightRef: React.RefObject<HTMLDivElement | null>;\n leftRef: React.RefObject<HTMLDivElement | null>;\n notify: () => void;\n active: boolean;\n isDirty: boolean;\n}\nconst ModalActionsContext = createContext<ModalActionsCtx | null>(null);\n\n/**\n * The id of the `<Modal>` this component is rendered inside, or `''` outside one.\n *\n * This is the PRIVATE per-mount id (`modal-xxxxxx`) that `activationOrder` and\n * the window-scoped CustomEvents carry — not the caller-supplied `windowKey`.\n * Same context `useWindowMenuItem` and `useWidgetSettings` already read, and it\n * reaches portal window content the same way theirs does.\n *\n * Use it to answer \"was this event meant for MY window?\", which\n * {@link useModalActive} cannot: that asks \"is the frontmost modal mine\", and\n * every nested dialog a form opens pushes itself onto `activationOrder`, so a\n * form with a child dialog open reads as inactive.\n */\nexport function useEnclosingModalId(): string {\n return useContext(ModalIdContext);\n}\n\n/** Hook to check if the current modal is active (frontmost) */\nexport function useModalActive(): boolean {\n const activeId = useSyncExternalStore(subscribeActive, getActiveModalId);\n const ctx = useContext(ModalActionsContext);\n return ctx?.active ?? (activationOrder.length <= 1 || activeId != null);\n}\n\nexport function ModalActions({ children, position = 'right' }: { children: React.ReactNode; position?: 'left' | 'right' }) {\n const ctx = useContext(ModalActionsContext);\n const [target, setTarget] = useState<HTMLElement | null>(null);\n\n useEffect(() => {\n if (!ctx) return;\n const ref = position === 'left' ? ctx.leftRef : ctx.rightRef;\n const check = () => {\n if (ref.current) { setTarget(ref.current); ctx.notify(); return true; }\n return false;\n };\n if (check()) return;\n // Ref might not be set yet — retry\n const t = setInterval(() => { if (check()) clearInterval(t); }, 50);\n const cleanup = setTimeout(() => clearInterval(t), 2000);\n return () => { clearInterval(t); clearTimeout(cleanup); };\n }, [ctx, position]);\n\n if (!target) return null;\n return createPortal(children, target);\n}\n\n/**\n * Cancel button that checks for unsaved changes before calling onClick.\n * Automatically detects dirty state from the nearest Modal context.\n */\nexport function CancelButton({ onClick, children, className }: { onClick: () => void; children?: React.ReactNode; className?: string }) {\n const ctx = useContext(ModalActionsContext);\n\n const handleClick = async () => {\n if (ctx?.isDirty) {\n const { confirm } = await import('./ConfirmDialog');\n const ok = await confirm({\n title: 'Discard changes?',\n message: 'You have unsaved changes. Are you sure you want to cancel? All changes will be lost.',\n confirmLabel: 'Discard',\n cancelLabel: 'Keep Editing',\n variant: 'warning',\n });\n if (!ok) return;\n }\n onClick();\n };\n\n return (\n <button type=\"button\" onClick={handleClick}\n className={className || 'bg-white text-gray-700 border border-gray-300 px-4 py-2 text-sm font-medium rounded-lg hover:bg-gray-50'}>\n {children || 'Cancel'}\n </button>\n );\n}\n\n// ── Window position persistence ──\nconst WP_KEY = 'erp_window_positions';\nlet _windowPositions: Record<string, { x: number; y: number; w: number; h: number }> = {};\ntry {\n const stored = localStorage.getItem(WP_KEY);\n if (stored) _windowPositions = JSON.parse(stored);\n} catch {}\nlet _saveTimer: ReturnType<typeof setTimeout> | null = null;\nfunction _savePositionsDebounced() {\n if (_saveTimer) clearTimeout(_saveTimer);\n _saveTimer = setTimeout(() => {\n try { localStorage.setItem(WP_KEY, JSON.stringify(_windowPositions)); } catch {}\n }, 500);\n}\n\n// ── Window activation (z-order) persistence ──\nconst AO_KEY = 'erp_activation_order';\nlet _activationOrderKeys: string[] = [];\ntry {\n const stored = localStorage.getItem(AO_KEY);\n const parsed = stored ? JSON.parse(stored) : null;\n if (Array.isArray(parsed) && parsed.every(k => typeof k === 'string')) _activationOrderKeys = parsed;\n} catch {}\nlet _saveOrderTimer: ReturnType<typeof setTimeout> | null = null;\nfunction _saveOrderDebounced() {\n if (_saveOrderTimer) clearTimeout(_saveOrderTimer);\n _saveOrderTimer = setTimeout(() => {\n try { localStorage.setItem(AO_KEY, JSON.stringify(_activationOrderKeys)); } catch {}\n }, 500);\n}\n\n/**\n * Seed an initial position for a window — applied only when no saved\n * position already exists for the given key. Use this from the consumer\n * to lay out the first-run desktop without overwriting whatever the user\n * has subsequently dragged the windows to.\n *\n * The key matches the window's `windowKey` — for `openPage('/weather')`\n * that's `'page:/weather'`.\n */\nexport function setWindowDefaultPosition(key: string, pos: { x: number; y: number; w: number; h: number }) {\n if (_windowPositions[key]) return;\n _windowPositions[key] = pos;\n _savePositionsDebounced();\n}\n\n/** Read the saved box for a window key (viewport-relative px), or null. */\nexport function getWindowPosition(key: string): { x: number; y: number; w: number; h: number } | null {\n return _windowPositions[key] ? { ..._windowPositions[key] } : null;\n}\n\n/**\n * Force a window's saved position — unlike `setWindowDefaultPosition` this\n * overwrites any existing entry. Use when the consumer wants to deliberately\n * (re)place a window, e.g. the Widget Manager dropping a freshly-added widget\n * into a tidy top-left slot regardless of where it last sat. For `autoHeight`\n * windows the `h` here is only a first-paint placeholder — the window\n * re-measures its content height on open.\n */\nexport function setWindowPosition(key: string, pos: { x: number; y: number; w: number; h: number }) {\n _windowPositions[key] = pos;\n _savePositionsDebounced();\n}\n\n/**\n * Forget every saved box that is really \"the whole work area\".\n *\n * A window that was maximized persists its full-screen geometry under its\n * `windowKey`, so it reopens filling the screen even after the shell is back\n * in windowed mode — the box outlives the setting that produced it. Layout\n * Mode → Classic calls this so those windows fall back to the normal size\n * ladder on their next open. `boxFillsWorkArea` is what keeps it from\n * forgetting a window the user sized and placed by hand.\n */\nexport function forgetMaximizedWindowBoxes() {\n const workArea = computeMaximizedBox();\n const sidebarReserved = isSidebarStripReserved();\n let changed = false;\n for (const key of Object.keys(_windowPositions)) {\n if (boxFillsWorkArea(_windowPositions[key], workArea, sidebarReserved)) {\n delete _windowPositions[key];\n changed = true;\n }\n }\n if (changed) _savePositionsDebounced();\n}\n\ninterface ModalProps {\n open: boolean;\n onClose: () => void;\n title: React.ReactNode;\n /** Window icon — shown before title, clicking it opens window menu */\n icon?: React.ReactNode;\n /** Text to copy when the copy icon in the header is clicked (e.g. entity number) */\n copyText?: string;\n size?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl';\n dirty?: boolean | 'auto';\n onNext?: () => void;\n onPrev?: () => void;\n footer?: React.ReactNode;\n /** When true, body uses overflow-hidden — child content manages its own scrolling */\n bodyScroll?: false;\n /** Custom minimize handler — called instead of the default global minimize */\n onMinimize?: (savedBox: { x: number; y: number; w: number; h: number; maximized: boolean }) => void;\n /** Restore to a previously saved position/size */\n initialBox?: { x: number; y: number; w: number; h: number; maximized: boolean };\n /** Footer actions (right side) — alternative to ModalActions portal */\n actions?: React.ReactNode;\n /** Footer actions (left side) — alternative to ModalActions portal */\n actionsLeft?: React.ReactNode;\n /** Allow the window to be pinned on top of all others */\n allowPinOnTop?: boolean;\n /** Initial position hint */\n initialPosition?: 'top-right' | 'top-left';\n /** Widget mode: no title/footer, drag anywhere, right-click context menu */\n widget?: boolean;\n /** Compact title bar: smaller header with title + close only, no minimize/maximize */\n compact?: boolean;\n /** App-style window: full title bar but body uses no padding so the app's own\n * chrome (toolbars, menus) sits flush against the window frame. For\n * self-chromed apps like Preview, Files, Browser. Implies `bodyScroll: false`\n * — apps manage their own scrolling internally. */\n appStyle?: boolean;\n /** Flush body: keeps the STANDARD full title bar and footer, but drops the\n * body padding so the content sits flush to the window edges (e.g. a\n * `<SidebarLayout>`). Implies `bodyScroll: false`. */\n flushBody?: boolean;\n /** Auto-size height based on content. Window's height adapts to whatever the\n * body renders; floored by `autoMinHeight` and capped to the available\n * viewport so nothing overflows the screen. Naturally-flowing content (a\n * form, a table) shrinks the window to hug it; a fill-height root (`h-full` /\n * `flex-1` between a fixed header and footer) keeps the normal size-ladder\n * height and scrolls internally rather than collapsing. */\n autoHeight?: boolean;\n /** Minimum height (px) when `autoHeight` is on. Defaults to 240. */\n autoMinHeight?: number;\n /** Custom menu items for widget right-click context menu */\n widgetMenu?: React.ReactNode;\n /** Custom window dimensions [width, height] in pixels */\n dimensions?: [number, number];\n /** Stable key for persisting window position to sessionStorage */\n windowKey?: string;\n /** windowKey of whichever window was active when this one opened. On\n * mobile, swipe-to-back broadcasts this value so the parent window can\n * un-hide itself underneath the sliding panel. */\n openedFromKey?: string;\n /** Per-section window accent (SG#00372): an `R G B` triple (e.g.\n * '91 141 190'). When set, the panel publishes it as the\n * `--window-accent-rgb` CSS custom property, and — if the user has turned\n * the `window_accent_stripe` preference on — renders a thin accent stripe\n * between the title bar and the body, so overlapping windows from\n * different app sections are distinguishable at a glance. The header\n * itself stays theme-neutral — themes and the user's custom header\n * colour are untouched. Absent = exactly the previous rendering.\n *\n * The CSS custom property is published whenever `accentRgb` is passed,\n * independent of the preference, so consumer CSS can key off the section\n * accent even with the stripe switched off. */\n accentRgb?: string;\n children: React.ReactNode;\n}\n\nconst sizeDefaults: Record<string, number> = {\n sm: 384, md: 512, lg: 672, xl: 896, '2xl': 1152, '3xl': 1408,\n};\n\n// The user's \"Default window size\" preference (Settings → Behavior). Layout\n// publishes it as the `--default-window-size` CSS var; here it scales a\n// freshly-opened window's initial height. 'large' is the default and opens\n// windows taller than 'medium' (the old fixed ladder), 'small' opens them\n// shorter, and 'maximized' opens non-widget windows filling the work area\n// (handled separately via the maximized state). Widgets ignore the pref —\n// they're content-sized utilities. Windows with explicit `dimensions` keep\n// their height for small/medium/large.\ntype WindowSizePref = 'small' | 'medium' | 'large' | 'maximized';\nconst readDefaultWindowSize = (): WindowSizePref => {\n if (typeof document === 'undefined') return 'large';\n const v = getComputedStyle(document.documentElement).getPropertyValue('--default-window-size')?.trim();\n return v === 'small' || v === 'medium' || v === 'maximized' ? v : 'large';\n};\n// Multiplier applied to the per-size open-height ladder. 'medium' reproduces\n// the previous fixed heights; 'large' (the default) opens 25 % taller.\nconst windowHeightScale: Record<WindowSizePref, number> = {\n small: 0.8, medium: 1, large: 1.25, maximized: 1.25,\n};\n\n// Track modal depth for stacking z-index and ESC handling\nexport let modalDepth = 0;\nexport const modalStack: string[] = [];\nexport const modalDepthRef = { get: () => modalDepth, inc: () => ++modalDepth, dec: () => --modalDepth };\n\n// Activation order — last element is the frontmost modal\nconst activationOrder: string[] = [];\nconst activeListeners = new Set<() => void>();\n\n// Bumped by every change to the activation order, and read as the snapshot by\n// `useIsActiveWindow`. The frontmost modal id is not enough on its own: a\n// window can mount *behind* the active one (a restored z-order slots it into\n// the middle of the stack), which changes the answer for that window without\n// changing the frontmost id — and `useSyncExternalStore` compares snapshots,\n// so an unchanged id means no re-render and a stale reading.\nlet _activeVersion = 0;\nfunction getActiveVersion() { return _activeVersion; }\nfunction notifyActive() {\n _activeVersion++;\n activeListeners.forEach(fn => fn());\n}\n// Bi-directional map between live (random per-mount) modalIds and stable\n// window keys (`windowKey || copyText`). Stable keys outlive page refreshes\n// and let us slot remounted modals back into their previous z-order.\nconst _modalIdByKey = new Map<string, string>();\nconst _keyByModalId = new Map<string, string>();\n\nfunction _insertModalIdForKey(modalId: string, key: string) {\n const savedIdx = _activationOrderKeys.indexOf(key);\n if (savedIdx === -1) { activationOrder.push(modalId); return; }\n let insertAt = activationOrder.length;\n for (let i = 0; i < activationOrder.length; i++) {\n const otherKey = _keyByModalId.get(activationOrder[i]);\n if (!otherKey) continue;\n const otherIdx = _activationOrderKeys.indexOf(otherKey);\n if (otherIdx > savedIdx) { insertAt = i; break; }\n }\n activationOrder.splice(insertAt, 0, modalId);\n}\n\n/**\n * The one outstanding \"bring this window to the front\" ask — a window key, or\n * null when nothing has been asked for.\n *\n * There is only one front, so there is only one ask: a second one REPLACES the\n * first, and the window the user asked for LAST is the one that rises rather\n * than whichever of them happens to mount first, which is not something the\n * user can see or control.\n *\n * The ask is SPENT by the mount that honours it. That is the whole lifetime:\n * an ask is a single \"show me this\", not a standing instruction, and a flag\n * that outlives its own fulfilment cannot be told apart from one that is still\n * live — so the window would come forward again, minutes later, on a remount\n * nobody asked for.\n *\n * Spending it immediately is safe for React's StrictMode remount (mount, tear\n * down, mount again) even though the second mount finds nothing to claim:\n * honouring the first one called `activateModal`, which moved this key to the\n * top of `_activationOrderKeys` — the SAVED order that `_insertModalIdForKey`\n * restores from. So the remount lands in front on its own, with no request\n * left over. Verified by mutation: removing every trace of a re-claim leaves\n * the StrictMode spec green.\n */\nlet _frontRequest: string | null = null;\n\n/**\n * Raise the mount that is claiming the outstanding ask, and spend the ask.\n *\n * Cleared BEFORE the activation, so the \"some other window took the front\"\n * expiry inside `activateModal` has nothing left to react to.\n */\nfunction _honourFrontRequest(modalId: string) {\n _frontRequest = null;\n activateModal(modalId);\n}\n\n/**\n * Bring the window with this stable key to the front — now if it is mounted,\n * or the moment it mounts if it is not.\n *\n * This is the shell's answer to \"the user asked for this window\", and it is\n * deliberately the ONLY way a window rises without the user touching the\n * window itself. Nothing about rendering reaches this function: a background\n * window that refetches, re-renders, or receives a push cannot call it, so it\n * cannot jump in front of whoever is typing. Somebody has to ASK.\n *\n * The deferred half is not an edge case, it is the common one. A window that\n * is closed has no modal to raise, so the very first \"open this\" arrives\n * before React has rendered anything — the request waits here and `mountModal`\n * claims it below. That makes first-open and re-open one code path instead of\n * two, which is the whole point: the second one is what used to be missing.\n *\n * An outstanding request is SPENT by the mount that honours it — see\n * {@link _frontRequest} for why that is safe for a StrictMode remount. It also\n * expires unhonoured when the user puts a different window in front (see\n * `activateModal`), or when the ask is withdrawn.\n */\nexport function requestWindowFront(windowKey: string) {\n // A newer ask replaces an older one outright: the user asked for THIS window\n // most recently, so this is the one that should end up in front.\n _frontRequest = windowKey;\n const modalId = _modalIdByKey.get(windowKey);\n if (modalId) _honourFrontRequest(modalId);\n}\n\n/** Drop a front request that was never claimed — the ask was withdrawn (the\n * window was closed again) before anything mounted to honour it. Without this\n * the stale request would raise the window the NEXT time it opened for an\n * unrelated reason. */\nexport function cancelWindowFront(windowKey: string) {\n if (_frontRequest === windowKey) _frontRequest = null;\n}\n\nexport function mountModal(modalId: string, key: string | null) {\n if (!key) {\n activationOrder.push(modalId);\n } else {\n _modalIdByKey.set(key, modalId);\n _keyByModalId.set(modalId, key);\n _insertModalIdForKey(modalId, key);\n if (_activationOrderKeys.indexOf(key) === -1) {\n _activationOrderKeys.push(key);\n _saveOrderDebounced();\n }\n }\n notifyActive();\n window.dispatchEvent(new CustomEvent('modal-reorder'));\n // Honour an open request that arrived before this window existed. Must come\n // AFTER the insert above, which deliberately slots a keyed modal back into\n // its saved z-order — behind the active window, which for an open the user\n // just asked for reads as \"nothing happened\".\n if (key && _frontRequest === key) _honourFrontRequest(modalId);\n}\n\n/**\n * Take a window out of the activation order — the counterpart of `mountModal`,\n * called by `Modal` as it unmounts.\n *\n * Deliberately leaves the key in `_activationOrderKeys`: that is the SAVED\n * order, which is what lets a window that closes and opens again come back\n * where the user left it rather than on top of everything.\n *\n * Extracted from the unmount effect it used to be written inline in, so the two\n * halves of the mapping are one symmetric pair — and so a spec can close a\n * window without rendering one.\n */\nexport function unmountModal(modalId: string) {\n const idx = activationOrder.indexOf(modalId);\n if (idx !== -1) { activationOrder.splice(idx, 1); notifyActive(); }\n const key = _keyByModalId.get(modalId);\n if (key) { _keyByModalId.delete(modalId); _modalIdByKey.delete(key); }\n}\n\nexport function activateModal(id: string) {\n const idx = activationOrder.indexOf(id);\n if (idx !== -1) activationOrder.splice(idx, 1);\n activationOrder.push(id);\n const key = _keyByModalId.get(id);\n if (key) {\n const kidx = _activationOrderKeys.indexOf(key);\n if (kidx !== -1) _activationOrderKeys.splice(kidx, 1);\n _activationOrderKeys.push(key);\n _saveOrderDebounced();\n // Some OTHER window is now in front, so an ask still WAITING to be honoured\n // has been overtaken — its window was slow to render, the user moved on,\n // and letting it arrive in front now would be the jump-in-front-of-you\n // behaviour `requestWindowFront` exists to avoid. (An ask that has already\n // been honoured is gone by this point; it is spent on the way in.) Only a\n // keyed activation counts as moving on: an inline dialog raising itself at\n // mount is part of the window it belongs to, not a different window\n // winning focus.\n if (_frontRequest && _frontRequest !== key) _frontRequest = null;\n }\n notifyActive();\n window.dispatchEvent(new CustomEvent('modal-reorder'));\n}\n\nfunction _minimizeModal(modalId: string) {\n const idx = activationOrder.indexOf(modalId);\n if (idx !== -1) activationOrder.splice(idx, 1);\n const key = _keyByModalId.get(modalId);\n if (key) {\n const kidx = _activationOrderKeys.indexOf(key);\n if (kidx !== -1) { _activationOrderKeys.splice(kidx, 1); _saveOrderDebounced(); }\n }\n notifyActive();\n window.dispatchEvent(new CustomEvent('modal-reorder'));\n}\n\n// Track which modal IDs belong to widget windows; widgets stay visible when\n// the user double-clicks the desktop (\"show desktop\"), only regular windows\n// are hidden.\nconst widgetIds = new Set<string>();\nexport function deactivateAllModals() {\n for (let i = activationOrder.length - 1; i >= 0; i--) {\n if (!widgetIds.has(activationOrder[i])) activationOrder.splice(i, 1);\n }\n _activationOrderKeys = _activationOrderKeys.filter(k => {\n const mid = _modalIdByKey.get(k);\n return mid != null && widgetIds.has(mid);\n });\n _saveOrderDebounced();\n notifyActive();\n window.dispatchEvent(new CustomEvent('modal-reorder'));\n}\n// ── Window snapping ──────────────────────────────────────────────────────\n// Aero/Magnet-style edge snapping. The drag handler watches the cursor\n// position and calls into these helpers. A single translucent preview\n// element is reused across drags (lazily created, kept around in body).\n\ntype SnapZone = 'top' | 'left' | 'right' | 'tl' | 'tr' | 'bl' | 'br';\nconst EDGE_THRESHOLD = 8; // px from edge to trigger half-screen snap\nconst CORNER_THRESHOLD = 32; // px square at each corner for quarter-screen snap\n\ninterface Box { x: number; y: number; w: number; h: number; }\n\nfunction workArea(): Box {\n const taskbarH = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--taskbar-height')) || 0;\n const taskbarW = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--taskbar-width')) || 0;\n const tbPos = getComputedStyle(document.documentElement).getPropertyValue('--taskbar-position')?.trim() || 'bottom';\n const x = tbPos === 'left' ? taskbarW : 0;\n const y = tbPos === 'top' ? taskbarH : 0;\n const w = window.innerWidth - (tbPos === 'left' || tbPos === 'right' ? taskbarW : 0);\n const h = window.innerHeight - (tbPos === 'top' || tbPos === 'bottom' ? taskbarH : 0);\n return { x, y, w, h };\n}\n\n// ── Keeping windows reachable ────────────────────────────────────────────\n// A window may be parked mostly off-screen on purpose — macOS allows it, and\n// so do we. What neither macOS nor Windows allows is a window you can no\n// longer grab: Windows pins the caption inside the work area, macOS forbids\n// going under the menu bar. We enforce the same invariant, which is also the\n// only defence against the browser viewport shrinking out from under a window.\nconst CAPTION_H = 40; // title-bar height that must stay inside the work area\nconst MIN_VISIBLE_X = 80; // horizontal strip that must stay grabbable\n\n// Smallest size a user gesture may leave a window at — shared by the pointer\n// resize and the keyboard resize so the two paths cannot disagree about it.\nconst MIN_W = 384;\nconst MIN_H = 400;\n\n/** Smallest move that keeps `box` grabbable. Never resizes. Returns `box`\n * itself when nothing moved, so callers can `setBox(clampReachable)` without\n * forcing a re-render or re-persisting an untouched window. */\nfunction clampReachable(box: Box, a: Box = workArea()): Box {\n const x = Math.min(Math.max(box.x, a.x + MIN_VISIBLE_X - box.w), a.x + a.w - MIN_VISIBLE_X);\n const y = Math.min(Math.max(box.y, a.y), a.y + a.h - CAPTION_H);\n return x === box.x && y === box.y ? box : { ...box, x, y };\n}\n\n/** Smallest move that brings the whole window back on screen. Shrinks it only\n * when it is larger than the work area. */\nfunction clampFullyVisible(box: Box, a: Box = workArea()): Box {\n const w = Math.min(box.w, a.w);\n const h = Math.min(box.h, a.h);\n return {\n w, h,\n x: Math.min(Math.max(box.x, a.x), a.x + a.w - w),\n y: Math.min(Math.max(box.y, a.y), a.y + a.h - h),\n };\n}\n\n/** Does every edge of this window sit inside the work area? A hidden panel\n * (minimised, or hidden by show-desktop) measures 0×0 and is never reported\n * off-screen — there is nothing to rescue. */\nexport function isPanelFullyVisible(panel: HTMLElement): boolean {\n const r = panel.getBoundingClientRect();\n if (r.width === 0 || r.height === 0) return true;\n const a = workArea();\n const EPS = 1;\n return r.left >= a.x - EPS && r.top >= a.y - EPS\n && r.right <= a.x + a.w + EPS && r.bottom <= a.y + a.h + EPS;\n}\n\n/** Bearing in degrees from the work-area centre toward an off-screen window\n * (0 = right, 90 = down), for the taskbar's off-screen chevron. Null when the\n * window is fully visible. */\nexport function panelOffscreenBearing(panel: HTMLElement): number | null {\n if (isPanelFullyVisible(panel)) return null;\n const r = panel.getBoundingClientRect();\n const a = workArea();\n const dx = (r.left + r.width / 2) - (a.x + a.w / 2);\n const dy = (r.top + r.height / 2) - (a.y + a.h / 2);\n return Math.atan2(dy, dx) * 180 / Math.PI;\n}\n\n/** Ask the window owning `windowKey` to slide fully back into the work area\n * and take focus. Handled by the `modal-reveal` listener each Modal installs.\n * Unlike `modal-center` this keeps the window's size and roughly its position\n * — it is a rescue, not a re-layout. */\nexport function revealWindow(windowKey: string) {\n window.dispatchEvent(new CustomEvent('modal-reveal', { detail: { windowKey } }));\n}\n\nfunction calcSnapBox(zone: SnapZone): Box {\n const a = workArea();\n const halfW = Math.floor(a.w / 2);\n const halfH = Math.floor(a.h / 2);\n switch (zone) {\n case 'top': return { x: a.x, y: a.y, w: a.w, h: a.h };\n case 'left': return { x: a.x, y: a.y, w: halfW, h: a.h };\n case 'right': return { x: a.x + halfW, y: a.y, w: a.w - halfW, h: a.h };\n case 'tl': return { x: a.x, y: a.y, w: halfW, h: halfH };\n case 'tr': return { x: a.x + halfW, y: a.y, w: a.w - halfW, h: halfH };\n case 'bl': return { x: a.x, y: a.y + halfH, w: halfW, h: a.h - halfH };\n case 'br': return { x: a.x + halfW, y: a.y + halfH, w: a.w - halfW, h: a.h - halfH };\n }\n}\n\nfunction detectSnapZone(clientX: number, clientY: number): SnapZone | null {\n const a = workArea();\n const nearLeft = clientX <= a.x + EDGE_THRESHOLD;\n const nearRight = clientX >= a.x + a.w - EDGE_THRESHOLD;\n const nearTop = clientY <= a.y + EDGE_THRESHOLD;\n const nearBottom = clientY >= a.y + a.h - EDGE_THRESHOLD;\n // Corners take priority over edges (larger detection square).\n const cornerLeft = clientX <= a.x + CORNER_THRESHOLD;\n const cornerRight = clientX >= a.x + a.w - CORNER_THRESHOLD;\n const cornerTop = clientY <= a.y + CORNER_THRESHOLD;\n const cornerBottom = clientY >= a.y + a.h - CORNER_THRESHOLD;\n if (nearTop && cornerLeft) return 'tl';\n if (nearTop && cornerRight) return 'tr';\n if (nearBottom && cornerLeft) return 'bl';\n if (nearBottom && cornerRight)return 'br';\n if (cornerTop && nearLeft) return 'tl';\n if (cornerTop && nearRight) return 'tr';\n if (cornerBottom && nearLeft) return 'bl';\n if (cornerBottom && nearRight)return 'br';\n if (nearTop) return 'top';\n if (nearLeft) return 'left';\n if (nearRight) return 'right';\n return null;\n}\n\nlet snapPreviewEl: HTMLDivElement | null = null;\nfunction getSnapPreviewEl(): HTMLDivElement {\n if (!snapPreviewEl) {\n snapPreviewEl = document.createElement('div');\n snapPreviewEl.style.cssText = [\n 'position: fixed',\n 'pointer-events: none',\n 'z-index: 40',\n 'border-radius: 8px',\n 'background: rgba(59, 130, 246, 0.18)',\n 'border: 2px solid rgb(59, 130, 246)',\n 'transition: left 120ms ease, top 120ms ease, width 120ms ease, height 120ms ease, opacity 120ms ease',\n 'opacity: 0',\n 'display: none',\n ].join(';');\n document.body.appendChild(snapPreviewEl);\n }\n return snapPreviewEl;\n}\nfunction showSnapPreview(box: Box) {\n const el = getSnapPreviewEl();\n el.style.display = 'block';\n el.style.left = `${box.x}px`;\n el.style.top = `${box.y}px`;\n el.style.width = `${box.w}px`;\n el.style.height = `${box.h}px`;\n el.style.opacity = '1';\n}\nfunction hideSnapPreview() {\n if (!snapPreviewEl) return;\n snapPreviewEl.style.opacity = '0';\n snapPreviewEl.style.display = 'none';\n}\n\n// ── Snap layouts picker ──────────────────────────────────────────────────\n// Windows-11-style: rest on (or focus) the maximize button and a small\n// palette of the snap zones appears — the halves and quarters the drag-to-\n// edge gesture and Ctrl/Cmd+arrows already reach, as click targets. Pure UI\n// over calcSnapBox; the zones and their geometry are the snapping module's.\nconst SNAP_PICKER_ZONES: { zone: SnapZone; labelKey: 'snapLeft' | 'snapRight' | 'snapTopLeft' | 'snapTopRight' | 'snapBottomLeft' | 'snapBottomRight'; region: string }[] = [\n { zone: 'left', labelKey: 'snapLeft', region: 'inset-y-0 left-0 w-1/2' },\n { zone: 'right', labelKey: 'snapRight', region: 'inset-y-0 right-0 w-1/2' },\n { zone: 'tl', labelKey: 'snapTopLeft', region: 'top-0 left-0 h-1/2 w-1/2' },\n { zone: 'tr', labelKey: 'snapTopRight', region: 'top-0 right-0 h-1/2 w-1/2' },\n { zone: 'bl', labelKey: 'snapBottomLeft', region: 'bottom-0 left-0 h-1/2 w-1/2' },\n { zone: 'br', labelKey: 'snapBottomRight', region: 'bottom-0 right-0 h-1/2 w-1/2' },\n];\nconst SNAP_PICKER_OPEN_MS = 350;\nconst SNAP_PICKER_CLOSE_MS = 200;\n\nfunction SnapLayoutsButton({ maximized, onToggleMax, onSnap, buttonClassName, strings }: {\n maximized: boolean;\n onToggleMax: () => void;\n onSnap: (zone: SnapZone) => void;\n buttonClassName: string;\n strings: { maximize: string; windowed: string; snapLayouts: string } & Record<'snapLeft' | 'snapRight' | 'snapTopLeft' | 'snapTopRight' | 'snapBottomLeft' | 'snapBottomRight', string>;\n}) {\n const [open, setOpen] = useState(false);\n const openTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n const closeTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n useEffect(() => () => { clearTimeout(openTimer.current); clearTimeout(closeTimer.current); }, []);\n const armOpen = () => { clearTimeout(closeTimer.current); openTimer.current = setTimeout(() => setOpen(true), SNAP_PICKER_OPEN_MS); };\n const armClose = () => { clearTimeout(openTimer.current); closeTimer.current = setTimeout(() => setOpen(false), SNAP_PICKER_CLOSE_MS); };\n\n return (\n <span className=\"relative inline-flex\" onMouseEnter={armOpen} onMouseLeave={armClose}>\n <button\n onClick={onToggleMax}\n onFocus={armOpen}\n onBlur={armClose}\n title={maximized ? strings.windowed : strings.maximize}\n className={buttonClassName}\n >\n {maximized ? '❐' : '⤢'}\n </button>\n {open && (\n <div\n role=\"group\"\n aria-label={strings.snapLayouts}\n onMouseEnter={() => clearTimeout(closeTimer.current)}\n onMouseLeave={armClose}\n className=\"absolute right-0 top-full z-30 mt-1 grid w-max grid-cols-2 gap-1 rounded-lg border border-gray-200 bg-white p-1.5 shadow-lg\"\n >\n {SNAP_PICKER_ZONES.map(({ zone, labelKey, region }) => (\n <button\n key={zone}\n type=\"button\"\n aria-label={strings[labelKey]}\n title={strings[labelKey]}\n onClick={() => { setOpen(false); onSnap(zone); }}\n onFocus={() => clearTimeout(closeTimer.current)}\n onBlur={armClose}\n className=\"relative h-7 w-11 rounded border border-gray-300 bg-gray-50 hover:border-blue-400 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-400\"\n >\n <span aria-hidden=\"true\" className={`absolute rounded-sm bg-blue-500/70 ${region}`} style={{ margin: 2 }} />\n </button>\n ))}\n </div>\n )}\n </span>\n );\n}\n\n// ── Pointer-gesture shield (drag/resize) ──────────────────────────────\n// A window drag/resize must keep receiving pointer events for the WHOLE\n// gesture. The move/up listeners live on `window`, which only sees events\n// dispatched within this document. Without pointer capture, the instant the\n// cursor crosses an overlapping window whose body is an <iframe> (e.g. an\n// embedded editor preview), the browser routes pointermove/pointerup into that\n// iframe's own document — the parent listeners fall silent, so the drag freezes\n// and can stick to the cursor (\"the background window interferes with the\n// active window\"). For the gesture's duration we therefore:\n// 1. capture the pointer on the grabbed handle so events stay in this doc;\n// 2. mount a transparent full-viewport shield so the pointer never reaches a\n// background iframe even if capture is unavailable, and background windows\n// don't react to the moving cursor; and\n// 3. flag <body> so every window is promoted to its own compositor layer,\n// so moving the foreground window doesn't repaint the windows behind it.\n// Backdrop-blur is intentionally KEPT on every window for the gesture's\n// duration so the frosted \"wallpaper-through-glass\" look never flickers\n// off while dragging. Only the grabbed (top) window re-samples its blur\n// per frame — its backdrop shifts as it moves; the static windows below\n// it don't, so the cost is a single moving glass surface.\nconst GESTURE_STYLE_ID = 'rosh-gesture-style';\nfunction ensureGestureStyle() {\n if (typeof document === 'undefined' || document.getElementById(GESTURE_STYLE_ID)) return;\n const style = document.createElement('style');\n style.id = GESTURE_STYLE_ID;\n style.textContent =\n // Promote every window to its own compositor layer for the gesture so\n // dragging the foreground window doesn't repaint the ones behind it. We do\n // NOT drop backdrop-blur — every window keeps its frosted glass while a\n // drag/resize is in progress (only the grabbed window re-samples, cheaply).\n 'body.rosh-gesturing [data-modal-panel]{will-change:transform}';\n document.head.appendChild(style);\n}\n\nconst RESIZE_CURSOR: Record<'se' | 'sw' | 'ne' | 'nw' | 'n' | 's' | 'e' | 'w', string> = {\n se: 'nwse-resize', nw: 'nwse-resize', sw: 'nesw-resize', ne: 'nesw-resize',\n n: 'ns-resize', s: 'ns-resize', e: 'ew-resize', w: 'ew-resize',\n};\n\n// Pointer travel (px) before a title-bar / resize press counts as a real\n// drag. Below this a press-and-hold (or a plain click) is NOT a gesture, so\n// `beginPointerGesture` (pointer capture, drag shield, compositor-layer\n// promotion) never engages — a press/click that isn't a drag leaves the\n// windows completely untouched.\nconst DRAG_THRESHOLD = 4;\n\n/** Begin a drag/resize pointer gesture on `handle`: capture the pointer, mount\n * a transparent shield with `cursor`, and promote windows to their own\n * compositor layers. Returns an idempotent cleanup for the pointerup handler.\n *\n * `kind` exists only for the perf log. Both gestures funnel through here, and\n * they are the two heaviest things the compositor is ever asked to do in this\n * shell — a move translates a promoted layer, a resize relayouts the window's\n * whole subtree per frame — so the log times them apart rather than recording\n * an anonymous pointer drag. */\nfunction beginPointerGesture(\n handle: HTMLElement,\n pointerId: number,\n cursor: string,\n kind: 'move' | 'resize',\n): () => void {\n ensureGestureStyle();\n try { handle.setPointerCapture(pointerId); } catch { /* capture unsupported for this input */ }\n document.body.classList.add('rosh-gesturing');\n const shield = document.createElement('div');\n shield.setAttribute('data-drag-shield', '');\n shield.style.cssText = `position:fixed;inset:0;z-index:2147483647;cursor:${cursor};background:transparent;touch-action:none`;\n document.body.appendChild(shield);\n const endMark = beginWindowGesture(kind);\n let done = false;\n return () => {\n if (done) return;\n done = true;\n endMark();\n try { handle.releasePointerCapture(pointerId); } catch { /* already released on pointerup */ }\n shield.remove();\n document.body.classList.remove('rosh-gesturing');\n };\n}\n\n// Listen for deactivate-all event from taskbar. Guarded like ensureGestureStyle\n// above: this runs at IMPORT time, so without the check merely importing any\n// component that reaches Modal — FilterBar does, for the Esc interceptor —\n// throws \"window is not defined\" outside a browser (SSR, or a node:test spec).\nif (typeof window !== 'undefined') window.addEventListener('deactivate-all-modals', deactivateAllModals);\nfunction getZForModal(id: string): number {\n const idx = activationOrder.indexOf(id);\n if (idx === -1) return -1; // Behind everything — hidden below listing page\n return 50 + idx * 10;\n}\nexport function getActiveModalId() {\n return activationOrder[activationOrder.length - 1] || null;\n}\nexport function subscribeActive(cb: () => void) {\n activeListeners.add(cb);\n return () => { activeListeners.delete(cb); };\n}\n\n// ── Escape interceptors ────────────────────────────────────────────────────\n// The registry itself lives in `./escapeInterceptors`, a leaf that imports\n// nothing, so `forms/Select` can register one without pulling this file — and\n// the window manager behind it — into a bundle. Re-exported here (and so from\n// the package root) with the same binding identity: the import path and\n// behaviour are unchanged for every consumer. See that file for the contract.\nexport { registerModalEscapeInterceptor } from './escapeInterceptors';\n\nconst MODAL_CLOSE_REQUEST_EVENT = 'modal-close-request';\ninterface ModalCloseRequestDetail { windowKey: string }\n\n/** Route shell-chrome close controls back to the keyed Modal that owns the\n * close guard. Internal to the shell; consumers close through their manager. */\nexport function requestModalClose(windowKey: string): void {\n window.dispatchEvent(new CustomEvent<ModalCloseRequestDetail>(MODAL_CLOSE_REQUEST_EVENT, {\n detail: { windowKey },\n }));\n}\n\n/** Hook: returns true if this modal ID is the frontmost */\nfunction useIsActiveModal(modalId: string): boolean {\n const activeId = useSyncExternalStore(subscribeActive, getActiveModalId);\n return activationOrder.length <= 1 || activeId === modalId;\n}\n\n/**\n * Is the window identified by `windowKey` the frontmost one?\n *\n * For anything that binds a global shortcut from *outside* the `<Modal>` it\n * belongs to — `UndoProvider` is mounted a level above `PageWindow`, so it has\n * no `ModalActionsContext` to read and cannot use {@link useModalActive}, whose\n * fallback path is made of module globals and therefore answers identically for\n * every caller. That fallback is fine for \"is any window active\"; it is useless\n * for \"is *mine* active\", and a per-window listener that asks the wrong\n * question fires in every window at once.\n *\n * `windowKey` is the stable key a window passes to `<Modal windowKey=...>` —\n * `WindowManager`'s `item.id` — not the private per-mount `modalId` that\n * `activationOrder` actually holds. The two are mapped by `mountModal`, and\n * resolving through that map is the whole point: `useIsActiveModal(item.id)`\n * would compare a window key against a `modal-xxxxxx` id and be false for every\n * window rather than true for every window.\n *\n * Omit `windowKey` — or pass one no mounted modal has claimed, which is the\n * case for a `rendersOwnModal` window whose inner `<Modal>` sets no\n * `windowKey` — and this degrades to {@link useModalActive}: the enclosing\n * `<ModalActions>` context if there is one, the global test if there is not.\n */\nexport function useIsActiveWindow(windowKey?: string | null): boolean {\n // Subscribed for invalidation only. The reading below is computed from the\n // live module state, which this version stamp tracks in full.\n useSyncExternalStore(subscribeActive, getActiveVersion);\n const ctx = useContext(ModalActionsContext);\n if (activationOrder.length <= 1) return true;\n if (windowKey) {\n const modalId = _modalIdByKey.get(windowKey);\n if (modalId != null) return getActiveModalId() === modalId;\n }\n return ctx?.active ?? getActiveModalId() != null;\n}\n\n// ── Exposé / Mission-Control mode ─────────────────────────────────────────\n//\n// Module-level toggle that, when on, visually scales every open modal\n// down into a non-overlapping grid (CSS transform; the modals stay where\n// they are layout-wise, so exiting just clears the transform). Each\n// scaled tile renders the live modal content as a thumbnail, plus a\n// label below; clicking a tile activates that modal and exits exposé;\n// clicking the backdrop (or pressing Escape, or the taskbar button\n// again) exits without changing the active modal.\nlet _exposeOn = false;\nconst _exposeListeners = new Set<() => void>();\nfunction _notifyExpose() { _exposeListeners.forEach((fn) => fn()); }\nfunction subscribeExpose(fn: () => void) { _exposeListeners.add(fn); return () => _exposeListeners.delete(fn); }\nfunction getExposeState() { return _exposeOn; }\nfunction setExposeState(v: boolean) {\n if (_exposeOn === v) return;\n _exposeOn = v;\n _notifyExpose();\n}\nexport function toggleExposeMode() { setExposeState(!_exposeOn); }\nexport function exitExposeMode() { setExposeState(false); }\n\n// When the user clicks a thumbnail to leave exposé, we publish that modal's\n// id here so all panels know which one is the \"spotlight\" pick. The picked\n// panel animates from its tile back to its real box; unpicked panels stay\n// pinned in their tile and fade out so the picked window has a clean stage.\nlet _exposeExitFocusId: string | null = null;\nconst _exposeExitListeners = new Set<() => void>();\nfunction subscribeExposeExitFocus(fn: () => void) {\n _exposeExitListeners.add(fn); return () => _exposeExitListeners.delete(fn);\n}\nfunction getExposeExitFocus() { return _exposeExitFocusId; }\nfunction setExposeExitFocus(id: string | null) {\n if (_exposeExitFocusId === id) return;\n _exposeExitFocusId = id;\n _exposeExitListeners.forEach(fn => fn());\n}\n\n// Keyboard-driven cycling through expose tiles (e.g. an ⌥⇧W shortcut in\n// the host app). The highlight is purely visual feedback while the user\n// browses; only commitExposeHighlight() actually focuses a window. The\n// distinction matters because a host that pre-selects a window on every\n// keystroke would otherwise rapidly thrash window state.\nlet _exposeHighlightId: string | null = null;\nconst _exposeHighlightListeners = new Set<() => void>();\nfunction subscribeExposeHighlight(fn: () => void) {\n _exposeHighlightListeners.add(fn);\n return () => _exposeHighlightListeners.delete(fn);\n}\nfunction getExposeHighlight() { return _exposeHighlightId; }\nexport function setExposeHighlight(id: string | null) {\n if (_exposeHighlightId === id) return;\n _exposeHighlightId = id;\n _exposeHighlightListeners.forEach(fn => fn());\n}\n/**\n * Commit the current keyboard highlight: focus the highlighted window\n * and exit exposé with the standard \"picked tile glides back\" animation.\n * No-op when no highlight is set.\n */\nexport function commitExposeHighlight() {\n if (!_exposeHighlightId) {\n setExposeState(false);\n return;\n }\n const id = _exposeHighlightId;\n // Set exit-focus BEFORE flipping expose off, so panels see the picked\n // id on their first exit-render and pick the right role (matches the\n // mouse-click path at the bottom of this file).\n setExposeExitFocus(id);\n setExposeHighlight(null);\n setExposeState(false);\n}\nexport { getExposeHighlight, subscribeExposeHighlight };\n\n// Backwards-compat — old taskbar wiring fires this event; treat it as a toggle.\nfunction triggerSplitView() {\n setExposeState(!_exposeOn);\n window.dispatchEvent(new CustomEvent('modal-split-view'));\n}\nexport { triggerSplitView };\n\n// Escape exits exposé. Also clear the highlight so a re-entry starts fresh.\n// Import-time, so guarded like the deactivate-all listener above.\nif (typeof window !== 'undefined') {\n window.addEventListener('keydown', (e) => {\n if (_exposeOn && e.key === 'Escape') {\n setExposeHighlight(null);\n setExposeState(false);\n }\n });\n}\n\ninterface ExposeTile { x: number; y: number; w: number; h: number; }\n\n/**\n * Compute the grid cell rectangle for a given modal id when exposé is on.\n * Returns null when the modal isn't tileable (utility / widget / pinned).\n *\n * Layout: roughly-square grid (cols=ceil(sqrt(N)), rows=ceil(N/cols)).\n * Tiles in the last row are centred when the row is short. The grid\n * uses the document work-area minus the taskbar.\n */\nfunction computeExposeTile(modalId: string): ExposeTile | null {\n if (typeof document === 'undefined') return null;\n const allPanels = Array.from(document.querySelectorAll('[data-modal-panel]'));\n // Skip utility, widget, and panels that have been hidden via display:none.\n const tileable: HTMLElement[] = allPanels.filter((p) => {\n const el = p as HTMLElement;\n if (el.hasAttribute('data-utility') || el.hasAttribute('data-widget')) return false;\n if (el.style.display === 'none') return false;\n return true;\n }) as HTMLElement[];\n // Stable ordering by data-modal-id so the same window lands in the same\n // tile each time exposé is opened — avoids visual reshuffling.\n tileable.sort((a, b) => (a.getAttribute('data-modal-id') || '').localeCompare(b.getAttribute('data-modal-id') || ''));\n const myIdx = tileable.findIndex((p) => p.getAttribute('data-modal-id') === modalId);\n const count = tileable.length;\n if (myIdx < 0 || count < 1) return null;\n\n const cols = Math.ceil(Math.sqrt(count));\n const rows = Math.ceil(count / cols);\n const myRow = Math.floor(myIdx / cols);\n const myCol = myIdx % cols;\n const lastRowCount = count - cols * (rows - 1);\n const isLastRow = myRow === rows - 1 && lastRowCount < cols;\n\n const taskbarH = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--taskbar-height')) || 0;\n const taskbarW = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--taskbar-width')) || 0;\n const tbPos = (getComputedStyle(document.documentElement).getPropertyValue('--taskbar-position') || 'bottom').trim();\n const xOffset = tbPos === 'left' ? taskbarW : 0;\n const xRight = tbPos === 'right' ? taskbarW : 0;\n const yOffset = tbPos === 'top' ? taskbarH : 0;\n const yBottom = (tbPos === 'top' || tbPos === 'left' || tbPos === 'right') ? 0 : taskbarH;\n const a = {\n x: xOffset, y: yOffset,\n w: window.innerWidth - xOffset - xRight,\n h: window.innerHeight - yOffset - yBottom,\n };\n // Layout constants. Generous gaps + label space below each tile so the\n // grid reads as separate windows the way macOS Exposé does.\n const gapX = 20;\n const gapY = 14;\n const labelH = 22;\n const cellW = (a.w - gapX * (cols + 1)) / cols;\n const cellH = (a.h - gapY * (rows + 1) - labelH * rows) / rows;\n\n const lastRowOffsetX = isLastRow ? ((cols - lastRowCount) * (cellW + gapX)) / 2 : 0;\n const tileX = a.x + gapX + myCol * (cellW + gapX) + lastRowOffsetX;\n const tileY = a.y + gapY + myRow * (cellH + gapY + labelH);\n return { x: tileX, y: tileY, w: cellW, h: cellH };\n}\n\n/**\n * Singleton backdrop that's shown while exposé mode is on. Click anywhere\n * (outside a window thumbnail) to exit exposé. Should be mounted exactly\n * once, near the root — typically by WindowManager.\n *\n * Fades in when exposé opens and out over the same window the panels use\n * to settle back, so the user sees a single coordinated transition rather\n * than the dim disappearing the instant a tile is clicked.\n */\nexport function ExposeBackdrop() {\n const on = useSyncExternalStore(subscribeExpose, getExposeState);\n const [mounted, setMounted] = useState(on);\n const [visible, setVisible] = useState(on);\n useEffect(() => {\n if (on) {\n setMounted(true);\n // Next frame so the opacity:0 → opacity:1 transition kicks in.\n const id = requestAnimationFrame(() => setVisible(true));\n return () => cancelAnimationFrame(id);\n }\n setVisible(false);\n const t = setTimeout(() => setMounted(false), 280);\n return () => clearTimeout(t);\n }, [on]);\n if (!mounted || typeof document === 'undefined') return null;\n return createPortal(\n <div\n onMouseDown={(e) => { e.stopPropagation(); setExposeState(false); }}\n style={{\n position: 'fixed', inset: 0,\n background: 'rgba(0,0,0,0.55)',\n backdropFilter: 'blur(2px)',\n WebkitBackdropFilter: 'blur(2px)',\n zIndex: 2000,\n cursor: 'pointer',\n opacity: visible ? 1 : 0,\n transition: 'opacity 260ms cubic-bezier(0.2, 0.8, 0.2, 1)',\n pointerEvents: visible ? 'auto' : 'none',\n }}\n />,\n document.body\n );\n}\n\n\nexport default function Modal({ open, onClose, title, icon, copyText, size = 'lg', dirty = false, onNext, onPrev, footer, bodyScroll, onMinimize, initialBox, actions, actionsLeft, allowPinOnTop, initialPosition, widget, compact, appStyle, flushBody, autoHeight, autoMinHeight, widgetMenu, dimensions, windowKey, openedFromKey, accentRgb, children }: ModalProps) {\n const isMobile = useIsMobile();\n // Mobile swipe-from-left-edge gesture: track horizontal offset of the panel.\n // 0 = at rest. While the user is dragging from the left edge, this grows\n // with the finger. On release, if past the threshold the panel slides off\n // and `onClose` fires; otherwise it animates back to 0.\n const [swipeX, setSwipeX] = useState(0);\n const [swipeDragging, setSwipeDragging] = useState(false);\n const swipeStartRef = useRef<{ startX: number; startY: number; pointerId: number } | null>(null);\n const swipeXRef = useRef(0);\n useEffect(() => { swipeXRef.current = swipeX; }, [swipeX]);\n\n const handleEdgePointerDown = useCallback((e: React.PointerEvent) => {\n if (!isMobile) return;\n swipeStartRef.current = { startX: e.clientX, startY: e.clientY, pointerId: e.pointerId };\n setSwipeDragging(true);\n // Tell sibling Modals which window's parent should reveal itself behind\n // this swipe — `null` (no `openedFromKey`) means \"this is a top-level\n // app, fall back to the home wallpaper\".\n setSwipingParentKey(openedFromKey ?? null);\n }, [isMobile, openedFromKey]);\n\n // Subscribe to the swipe store so non-active panels can render themselves\n // visible underneath a sibling that's currently being swiped to its parent.\n const swipingParentKey = useSyncExternalStore(subscribeSwipingParentKey, getSwipingParentKey);\n\n // Move + release wired globally during a swipe so the panel keeps tracking\n // the finger even if it leaves the edge zone (e.g. the user drags clear\n // across the screen).\n useEffect(() => {\n if (!swipeDragging) return;\n const onMove = (ev: PointerEvent) => {\n if (!swipeStartRef.current) return;\n const dx = ev.clientX - swipeStartRef.current.startX;\n const dy = Math.abs(ev.clientY - swipeStartRef.current.startY);\n if (dy > Math.abs(dx) + 12) {\n // Vertical movement dominates — abandon the gesture so the user can\n // scroll content normally.\n swipeStartRef.current = null;\n setSwipeDragging(false);\n setSwipeX(0);\n setSwipingParentKey(null);\n return;\n }\n setSwipeX(Math.max(0, dx));\n };\n const onUp = () => {\n if (!swipeStartRef.current) return;\n const threshold = window.innerWidth * 0.3;\n const past = swipeXRef.current > threshold;\n swipeStartRef.current = null;\n setSwipeDragging(false);\n if (past) {\n // Swipe-from-edge closes the current window so whatever was opened\n // before it (the parent list, or the desktop underneath a top-level\n // app) becomes visible.\n setSwipeX(window.innerWidth);\n setTimeout(() => {\n onClose();\n setSwipeX(0);\n setSwipingParentKey(null);\n }, 180);\n } else {\n setSwipeX(0);\n setSwipingParentKey(null);\n }\n };\n window.addEventListener('pointermove', onMove);\n window.addEventListener('pointerup', onUp);\n window.addEventListener('pointercancel', onUp);\n return () => {\n window.removeEventListener('pointermove', onMove);\n window.removeEventListener('pointerup', onUp);\n window.removeEventListener('pointercancel', onUp);\n };\n }, [swipeDragging]);\n const [displayTitle, setDisplayTitle] = useState<React.ReactNode>(title);\n // Window-control labels come from the shell catalog (see strings.tsx).\n const shellStrings = useShellStrings();\n const winStr = shellStrings.window;\n useEffect(() => { setDisplayTitle(title); }, [title]);\n /** Native tooltip so a title truncated by CSS can still be read in full. Undefined when the\n * title carries no plain text (icon-only nodes), so no empty tooltip is attached. */\n const titleTooltip = useMemo(() => extractTitleText(displayTitle).trim() || undefined, [displayTitle]);\n const [touched, setTouched] = useState(false);\n const [pinnedOnTop, setPinnedOnTop] = useState(false);\n const [windowMenu, setWindowMenu] = useState<{ x: number; y: number } | null>(null);\n // \"Add to Desktop\" — spec provided by the WindowManager around each open\n // window; null for nested dialogs (the outermost Modal re-provides null\n // below) and for Modals used outside the window system.\n const shortcutSpec = useContext(WindowShortcutContext);\n const { prefs: shellPrefs, save: saveShellPrefs } = useShellPrefs();\n // SG#00372: the per-section accent stripe is opt-in — plenty of users read a\n // coloured band under the title bar as status rather than as \"which section\n // this window belongs to\", so it stays off until asked for. Consumers that\n // pass `accentRgb` still publish the CSS custom property either way.\n const accentStripeOn = !!shellPrefs.window_accent_stripe;\n const favDocs: WindowShortcutSpec[] = shellPrefs.favorite_documents || [];\n const isOnDesktop = !!shortcutSpec && favDocs.some(d => d.entityType === shortcutSpec.entityType && d.entityId === shortcutSpec.entityId);\n const toggleDesktopShortcut = useCallback(() => {\n if (!shortcutSpec) return;\n const next = isOnDesktop\n ? favDocs.filter(d => !(d.entityType === shortcutSpec.entityType && d.entityId === shortcutSpec.entityId))\n : [...favDocs, { entityType: shortcutSpec.entityType, entityId: shortcutSpec.entityId, label: shortcutSpec.label }];\n saveShellPrefs({ favorite_documents: next });\n }, [shortcutSpec, isOnDesktop, favDocs, saveShellPrefs]);\n const [ctxMenu, setCtxMenu] = useState<{ x: number; y: number } | null>(null);\n // Widget anchoring: 'left' or 'right' — determines which edge the widget is fixed to\n const [widgetAnchor, setWidgetAnchor] = useState<'left' | 'right'>(initialPosition === 'top-right' ? 'right' : 'left');\n const closingRef = useRef(false);\n const panelRef = useRef<HTMLDivElement>(null);\n // SG#00372: publish the per-section accent as a CSS custom property on the\n // panel element (same setProperty convention as the theme vars in\n // Layout/useTheme). The accent stripe below and any theme CSS read it via\n // `var(--window-accent-rgb)`. React never manages this key in the panel's\n // `style` prop, so the two can't fight over it.\n useLayoutEffect(() => {\n const el = panelRef.current;\n if (!el) return;\n if (accentRgb) el.style.setProperty('--window-accent-rgb', accentRgb);\n else el.style.removeProperty('--window-accent-rgb');\n }, [accentRgb]);\n // SG#00391: set when a mousedown on an INACTIVE window's interactive element\n // was swallowed to raise-only — the paired click (which is what would\n // navigate an <a> or fire a button's onClick) must be eaten too.\n const swallowInactiveClickRef = useRef(false);\n const bodyRef = useRef<HTMLDivElement>(null);\n const actionsRef = useRef<HTMLDivElement>(null);\n const actionsLeftRef = useRef<HTMLDivElement>(null);\n const [hasActions, setHasActions] = useState(false);\n const footerRef = useRef<HTMLDivElement>(null);\n // One boolean for \"the footer has anything to show\" — drives both the\n // footer's `hidden` class and the autoHeight re-measure below, so the two\n // can't drift apart. Presence booleans rather than the nodes themselves:\n // consumer JSX props get a new identity every render and would thrash the\n // measurement effect's dependency array.\n const hasFooterContent = !!(footer || actions || actionsLeft) || hasActions;\n // Every window must surface a clickable icon — it's the only entry point\n // to the window menu. Fall back to a generic \"window\" glyph when the\n // consumer hasn't supplied one. Consumer icons rarely include explicit\n // size classes (the start menu adds them via cloneElement), so we also\n // size them here to keep the title bar layout stable.\n const fallbackIcon = (\n <svg className=\"h-4 w-4 text-gray-400\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M3.75 6.75A2.25 2.25 0 016 4.5h12a2.25 2.25 0 012.25 2.25v10.5A2.25 2.25 0 0118 19.5H6a2.25 2.25 0 01-2.25-2.25V6.75z M3.75 9h16.5\" />\n </svg>\n );\n const effectiveIcon = icon && isValidElement(icon)\n ? cloneElement(icon as React.ReactElement, {\n className: `h-4 w-4 ${(icon as React.ReactElement).props?.className ?? ''}`.trim(),\n } as any)\n : (icon ?? fallbackIcon);\n const renderIconButton = () => (\n <button\n onPointerDown={e => e.stopPropagation()}\n onClick={e => {\n e.stopPropagation();\n const rect = e.currentTarget.getBoundingClientRect();\n setWindowMenu(prev => prev ? null : { x: rect.left, y: rect.bottom + 4 });\n }}\n className=\"shrink-0 p-0.5 rounded hover:bg-gray-200/50 transition-colors\"\n title=\"Window menu\"\n >\n {effectiveIcon}\n </button>\n );\n const padding = 40;\n const { minimize: globalMinimize, items: minimizedItems, restoreIfMinimized } = useWindowManager();\n const modalId = useRef(`modal-${Math.random().toString(36).slice(2, 8)}`).current;\n\n // Mark widget windows so deactivate-all (show desktop) skips them.\n useEffect(() => {\n if (widget) {\n widgetIds.add(modalId);\n return () => { widgetIds.delete(modalId); };\n }\n }, [widget, modalId]);\n\n useEffect(() => {\n const handler = (e: Event) => {\n const detail = (e as CustomEvent).detail;\n if (detail?.id === modalId) setDisplayTitle(detail.title);\n };\n window.addEventListener('window-title-update', handler);\n return () => window.removeEventListener('window-title-update', handler);\n }, [modalId]);\n const [zIndex, setZIndex] = useState(50);\n const isActive = useIsActiveModal(modalId);\n\n // Exposé: when enabled, every tileable modal scales down via CSS\n // transform into its grid cell. Utility, widget, and pinned panels\n // sit out — they keep their normal layout.\n const exposeOn = useSyncExternalStore(subscribeExpose, getExposeState);\n const exposeExitFocusId = useSyncExternalStore(subscribeExposeExitFocus, getExposeExitFocus);\n const exposeHighlightId = useSyncExternalStore(subscribeExposeHighlight, getExposeHighlight);\n const isExposeTileable = !allowPinOnTop && !widget;\n const exposeActive = exposeOn && isExposeTileable;\n // Hover highlight for the thumbnail while in exposé.\n const [exposeHovered, setExposeHovered] = useState(false);\n // Keyboard-driven highlight (set externally via setExposeHighlight). Same\n // glow as hover so cycling visually matches what a mouse user sees.\n const exposeKeyboardHighlight = exposeActive && exposeHighlightId === modalId;\n // Exit-animation window: keep `transition: transform` on the panel for ~320ms\n // after exposé closes so the panel slides smoothly back to its real box\n // instead of snapping. Without this, removing `exposeStyle` drops the\n // transition prop instantly and the browser sees no animatable change.\n // The window the user clicked (when leaving via thumbnail) becomes the\n // \"picked\" one: same glide-home animation as everyone else, but with a\n // spring-y curve and elevated z-index so it reads as the focal point.\n const [exposeExiting, setExposeExiting] = useState(false);\n const exposeExitRole = (exposeExiting && isExposeTileable && exposeExitFocusId === modalId)\n ? 'picked' as const\n : null;\n const prevExposeActiveRef = useRef(exposeActive);\n useEffect(() => {\n if (prevExposeActiveRef.current && !exposeActive) {\n setExposeExiting(true);\n // Wait long enough for the picked window's spring (640 ms) to settle\n // before stripping the transition rule, otherwise the late-overshoot\n // tail snaps to the final position.\n const t = setTimeout(() => {\n setExposeExiting(false);\n // Only the picked modal resets the global focus; other panels read\n // it from the store during the whole window so no race.\n if (_exposeExitFocusId === modalId) setExposeExitFocus(null);\n }, 700);\n prevExposeActiveRef.current = exposeActive;\n return () => clearTimeout(t);\n }\n prevExposeActiveRef.current = exposeActive;\n }, [exposeActive, modalId]);\n // Reset hover whenever exposé toggles off so the highlight ring doesn't\n // linger past the transition.\n useEffect(() => { if (!exposeActive) setExposeHovered(false); }, [exposeActive]);\n\n\n // Track whether ModalActions portal has content (either left or right)\n useEffect(() => {\n const r = actionsRef.current;\n const l = actionsLeftRef.current;\n if (!r && !l) return;\n const check = () => setHasActions((r?.childElementCount ?? 0) + (l?.childElementCount ?? 0) > 0);\n check();\n const obs = new MutationObserver(check);\n if (r) obs.observe(r, { childList: true });\n if (l) obs.observe(l, { childList: true });\n return () => obs.disconnect();\n }, [open]);\n\n // Forward submit-button clicks from portaled actions to the form\n // (React onClick won't fire for portal children — must use native listener)\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n const btn = (e.target as HTMLElement).closest('button[type=\"submit\"]');\n if (btn && panelRef.current) {\n const form = panelRef.current.querySelector('form');\n if (form) { e.preventDefault(); form.requestSubmit(); }\n }\n };\n const r = actionsRef.current;\n const l = actionsLeftRef.current;\n if (r) r.addEventListener('click', handler);\n if (l) l.addEventListener('click', handler);\n return () => { if (r) r.removeEventListener('click', handler); if (l) l.removeEventListener('click', handler); };\n }, [open]);\n\n // ── Draggable/resizable state ──\n const isNested = useRef(false);\n\n const calcMaximized = useCallback(computeMaximizedBox, []);\n\n const calcWindowed = useCallback(() => {\n const sw = 0;\n const taskbarH = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--taskbar-height')) || 0;\n const taskbarW = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--taskbar-width')) || 0;\n const tbPos = getComputedStyle(document.documentElement).getPropertyValue('--taskbar-position')?.trim() || 'bottom';\n const leftOffset = tbPos === 'left' ? taskbarW : 0;\n const rightOffset = tbPos === 'right' ? taskbarW : 0;\n const targetW = dimensions ? dimensions[0] : (sizeDefaults[size] || 672);\n const availW = window.innerWidth - sw - leftOffset - rightOffset - padding * 2;\n const availH = window.innerHeight - taskbarH - padding * 2;\n const w = Math.min(targetW, availW);\n // Initial-open height ladder. 320 px is the open-time floor — the CSS\n // minHeight (~240 px at line ~1500) stays in place as the manual-resize\n // floor, so users can still drag a window smaller. xl/2xl previously had\n // no cap and ballooned to fill the entire viewport on tall screens;\n // they're now bounded at 800 / 920 px. The ladder is then scaled by the\n // user's \"Default window size\" preference — 'large' (the default) opens\n // 25 % taller than the old fixed values, 'small' shorter, 'medium' keeps\n // them. All caps are further clamped to the available viewport, so small\n // screens still get a window that fits.\n const heightScale = windowHeightScale[readDefaultWindowSize()];\n const h = dimensions\n ? Math.min(dimensions[1], availH)\n : (() => { const minH = 320; const maxH = (size === 'sm' ? 500 : size === 'md' ? 600 : size === 'lg' ? 700 : size === 'xl' ? 800 : 920) * heightScale; return Math.max(minH, Math.min(maxH, window.innerHeight - taskbarH - 80)); })();\n // Window position mode\n const posMode = getComputedStyle(document.documentElement).getPropertyValue('--window-position')?.trim() || 'cascade';\n const offset = posMode === 'cascade' ? (activationOrder.length - 1) * 30 : 0;\n const maxOffsetX = availW - w;\n const maxOffsetY = availH - h;\n // Position hints\n if (initialPosition === 'top-right') {\n return { x: window.innerWidth - w - padding, y: padding, w, h };\n }\n if (initialPosition === 'top-left') {\n return { x: sw + padding, y: padding, w, h };\n }\n return {\n x: sw + Math.max(padding, (availW - w) / 2 + padding) + Math.min(offset, Math.max(0, maxOffsetX)),\n y: Math.max(padding, (availH - h) / 2) + Math.min(offset, Math.max(0, maxOffsetY)),\n w, h,\n };\n }, [size]);\n\n const interceptedRef = useRef(false);\n if (!open) interceptedRef.current = false;\n\n const boxKey = windowKey || copyText || null;\n\n useEffect(() => {\n if (!open) return;\n modalDepthRef.inc();\n modalStack.push(modalId);\n mountModal(modalId, boxKey);\n // Inline dialogs (a list's detail Modal, a confirm) have no `windowKey`, so\n // they never pass through WindowManager's `activateAfterMount` and never\n // survive a refresh. mountModal would otherwise slot them into a stale\n // saved z-order (from a prior open, keyed by `copyText`) — dropping them\n // BEHIND the window they were opened from, which reads as \"nothing opened\".\n // A user-initiated open must come to the front, so raise keyless modals\n // here. WindowManager-managed windows (windowKey set) are fronted by\n // activateAfterMount instead and must keep their restored order on refresh.\n if (!windowKey) activateModal(modalId);\n isNested.current = false; // All modals are independent top-level windows\n setZIndex(getZForModal(modalId));\n // Listen for reorder events to update z-index\n const onReorder = () => {\n setZIndex(getZForModal(modalId));\n };\n // The old \"split view\" handler used to setBox to tile windows side\n // by side. Exposé replaces that with a non-destructive overlay\n // (CSS transform on the panel, see further down) — so this handler\n // is now a no-op. Kept around as an event listener target only so\n // the prior wiring keeps working until every consumer migrates.\n const onSplitView = () => { /* no-op: exposé toggle handled by setExposeState */ };\n\n // Center window on double-click from taskbar\n const onCenter = (e: Event) => {\n const label = (e as CustomEvent).detail?.label;\n if (!label) return;\n const titleEl = panelRef.current?.querySelector('[data-window-title]');\n if (!titleEl?.textContent?.includes(label)) return;\n activateModal(modalId);\n const taskbarH = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--taskbar-height')) || 0;\n const taskbarW = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--taskbar-width')) || 0;\n const tbPos = getComputedStyle(document.documentElement).getPropertyValue('--taskbar-position')?.trim() || 'bottom';\n const leftOff = tbPos === 'left' ? taskbarW : 0;\n const rightOff = tbPos === 'right' ? taskbarW : 0;\n const availW = window.innerWidth - leftOff - rightOff;\n const availH = window.innerHeight - taskbarH;\n // Clamp size to viewport if bigger\n const w = Math.min(boxRef.current.w, availW - 40);\n const h = Math.min(boxRef.current.h, availH - 40);\n const x = leftOff + (availW - w) / 2;\n const y = (tbPos === 'top' ? taskbarH : 0) + (availH - h) / 2;\n setBox({ x, y, w, h });\n setMaximized(false);\n };\n // Context menu from taskbar right-click\n const onCtxMenu = (e: Event) => {\n const { label, x, y } = (e as CustomEvent).detail || {};\n if (!label) return;\n const titleEl = panelRef.current?.querySelector('[data-window-title]');\n if (!titleEl?.textContent?.includes(label)) return;\n activateModal(modalId);\n setWindowMenu({ x, y });\n };\n\n // Rescue a window the user can't reach: the smallest move that puts it\n // fully back inside the work area, shrinking it only if it is bigger than\n // the work area. Fired when the taskbar's off-screen thumbnail is clicked.\n // Deliberately narrower than `onCenter` — the window keeps its size and\n // roughly its place, because a rescue shouldn't re-layout your desktop.\n const onReveal = (e: Event) => {\n if ((e as CustomEvent).detail?.windowKey !== windowKey) return;\n activateModal(modalId);\n const cur = boxRef.current;\n const next = clampFullyVisible(cur);\n if (next.x === cur.x && next.y === cur.y && next.w === cur.w && next.h === cur.h) return;\n const panel = panelRef.current;\n const stillness = typeof window.matchMedia === 'function'\n && window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n if (panel && !stillness) {\n // Animate it home so the user sees where it came from. Mid-slide the\n // panel's rect still measures as off-screen, so the taskbar marker\n // would survive its own rescue — re-poll once the window has landed.\n // `transitionend` is the honest signal; the timer is a fallback,\n // because a slide with no movement on any axis never fires one.\n let settled = false;\n const done = () => {\n if (settled) return;\n settled = true;\n panel.style.transition = '';\n window.dispatchEvent(new CustomEvent('modal-geometry'));\n };\n panel.style.transition = 'left .28s ease, top .28s ease, width .28s ease, height .28s ease';\n panel.addEventListener('transitionend', done, { once: true });\n window.setTimeout(done, 400);\n }\n setBox(next);\n };\n\n window.addEventListener('modal-reorder', onReorder);\n window.addEventListener('modal-split-view', onSplitView);\n window.addEventListener('modal-center', onCenter);\n window.addEventListener('modal-reveal', onReveal);\n window.addEventListener('modal-context-menu', onCtxMenu);\n return () => {\n modalDepthRef.dec();\n const idx = modalStack.indexOf(modalId);\n if (idx !== -1) modalStack.splice(idx, 1);\n unmountModal(modalId);\n window.removeEventListener('modal-reorder', onReorder);\n window.removeEventListener('modal-split-view', onSplitView);\n window.removeEventListener('modal-center', onCenter);\n window.removeEventListener('modal-reveal', onReveal);\n window.removeEventListener('modal-context-menu', onCtxMenu);\n // Notify remaining modals to recalc z-index\n window.dispatchEvent(new CustomEvent('modal-reorder'));\n };\n }, [open, modalId, boxKey, calcMaximized]);\n\n // 'Maximized' default-window-size preference: a freshly-opened non-widget\n // window fills the work area. Widgets (small content-sized utilities) and\n // windows restored from a saved/explicit box are exempt.\n const openMaximized = !widget && readDefaultWindowSize() === 'maximized';\n\n // Restore saved position from window position store\n const [box, setBox] = useState(() => {\n if (boxKey && _windowPositions[boxKey]) {\n const saved = { ..._windowPositions[boxKey] };\n // If dimensions are specified, enforce them (override cached size but keep position)\n if (dimensions) { saved.w = dimensions[0]; if (!autoHeight) saved.h = dimensions[1]; }\n // A box saved on a larger screen must not reopen out of reach.\n return clampReachable(saved);\n }\n if (initialBox) return { x: initialBox.x, y: initialBox.y, w: initialBox.w, h: initialBox.h };\n return openMaximized ? calcMaximized() : calcWindowed();\n });\n // `autoHeight` is a *one-shot* \"size to content at open time\" hint, not a\n // continuous CSS rule. The panel always renders at a *definite* height\n // (`box.h`, seeded from the normal windowed size ladder), and the layout\n // effect below measures the content and adjusts `box.h` to hug it — then\n // freezes, so the window behaves as a normal fixed-size window from there\n // on (drag/resize don't re-shrink it). `autoHeight` windows always\n // re-measure on open so they stay content-aware; the saved box restores\n // position + width but its `h` is only a placeholder.\n //\n // Crucially we measure against a definite panel height rather than\n // `height: auto`. A naturally-flowing detail (a table, a form) hugs its\n // content either way, but content whose root fills its parent — the common\n // `header / flex-1 scroll region / footer` detail layout — collapses to\n // nothing under a content-sized parent and used to freeze at the\n // `autoMinHeight` floor (a useless ~240px sliver). Keeping the panel\n // definite lets such content fill the ladder height; the measurement only\n // shrinks the window when the content genuinely *doesn't* fill it.\n const [autoHeightResolved, setAutoHeightResolved] = useState(() => !autoHeight);\n // Always-maximized layout: when the Layout sets `--layout-mode: sidebar`\n // on <html>, every non-widget Modal becomes immovable and locked to\n // calcMaximized() — no windowed state, no drag-to-restore, no maximize\n // toggle button. Layout dispatches a custom event whenever the pref\n // flips so already-mounted windows refresh without needing to remount.\n const [alwaysMaximizedRaw, setAlwaysMaximizedRaw] = useState<boolean>(() => readAlwaysMaximizedFlag());\n useEffect(() => {\n const refresh = () => setAlwaysMaximizedRaw(readAlwaysMaximizedFlag());\n window.addEventListener('react-os-shell:layout-mode-changed', refresh);\n return () => window.removeEventListener('react-os-shell:layout-mode-changed', refresh);\n }, []);\n const alwaysMaximized = alwaysMaximizedRaw && !widget;\n const [maximized, setMaximized] = useState(() => {\n // Saved positions and explicit restore boxes keep their own state (the\n // open effect below restores `initialBox.maximized`); a fresh window\n // honours the 'maximized' default-window-size preference.\n if ((boxKey && _windowPositions[boxKey]) || initialBox) return alwaysMaximized;\n return alwaysMaximized || openMaximized;\n });\n const boxRef = useRef(box);\n boxRef.current = box;\n\n // autoHeight measurement. The panel renders at a definite height the whole\n // time; here we measure the body's content and nudge `box.h` so the window\n // hugs it. A single first-paint measurement is unreliable — the open\n // animation, the lazy/Suspense body, and async data each settle over\n // several frames, so we track the body with a ResizeObserver:\n // • Widgets stay content-sized for their whole life (never freeze), so a\n // widget grows/shrinks with its content — a World Clock gains height as\n // each city's weather loads or when the user adds a city, a Currency\n // widget hugs its rows. This holds only while a widget's root is\n // naturally-flowing: a fill-height widget root (`h-full` / `flex-1`)\n // would still trip the fill-detection below and pin to the ladder\n // height, so widget roots must hug their own content rather than fill.\n // Widgets aren't user-resizable, so there's nothing to preserve by\n // freezing.\n // • Other autoHeight windows (e.g. settings dialogs, entity details)\n // measure-then-freeze once the height holds steady, then behave as\n // normal fixed-size windows (draggable/resizable, no further reactivity).\n //\n // The measurement distinguishes content that *fills* its container from\n // content that doesn't, so it never collapses a fill-height layout:\n // 1. With the body temporarily content-sized, read its natural outer\n // height (`bodyNatural`) and the content root's own height.\n // 2. Restore the body to its definite flex height and re-read the content\n // root. If the content root grew, it's a fill-height layout (flex-1 /\n // h-full) — keep the ladder height so it doesn't collapse. Otherwise\n // the content is naturally-flowing — size the window to chrome +\n // `bodyNatural`, clamped between the floor and the viewport.\n //\n // Two things make this robust against content that arrives *after* the first\n // paint — the common case where a detail component fetches its own data and\n // renders a small spinner before swapping in the real, taller content:\n // • We freeze (commit the height and stop reacting) only once we've\n // measured real content — a height *above the floor*. While the body\n // still measures at the floor (a loading spinner / pre-data placeholder)\n // we keep observing, so the window grows to the loaded content instead of\n // locking at a collapsed sliver. Without this, a fetch slower than the\n // freeze delay froze the window at the spinner height on first open\n // (a reopen, with the data cached, rendered tall content immediately and\n // looked fine — the tell-tale of this race).\n // • The ResizeObserver tracks the live *content root*, not the body (which\n // is a fixed flex height and so never resizes when content changes\n // inside it). That catches async rows, late images, and font swaps; a\n // MutationObserver on the body re-points it when the root element itself\n // is replaced (spinner → content).\n useLayoutEffect(() => {\n if (autoHeightResolved) return;\n const panel = panelRef.current;\n const body = bodyRef.current;\n if (!panel || !body) return;\n const floor = autoMinHeight ?? (widget ? 0 : 240);\n const taskbarH = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--taskbar-height')) || 0;\n let lastH = 0;\n let freezeTimer: ReturnType<typeof setTimeout> | null = null;\n let observed: Element | null = null;\n const measure = () => {\n const content = body.firstElementChild as HTMLElement | null;\n if (!content || panel.offsetHeight <= 0) return;\n // Keep the ResizeObserver pointed at the current content root so growth\n // inside the fixed-height body (data swapping in, images/fonts loading)\n // re-triggers measurement.\n if (content !== observed) {\n if (observed) ro.unobserve(observed);\n ro.observe(content);\n observed = content;\n }\n const chrome = panel.offsetHeight - body.offsetHeight; // title bar + footer\n // Pass 1: let the body size to its content and note the natural heights.\n const prevFlex = body.style.flex, prevOverflow = body.style.overflowY, prevHeight = body.style.height;\n body.style.flex = '0 0 auto';\n body.style.height = 'auto';\n body.style.overflowY = 'visible';\n const bodyNatural = body.offsetHeight;\n const contentNatural = content.offsetHeight;\n // Pass 2: restore the definite flex height and see if the content grew.\n body.style.flex = prevFlex;\n body.style.height = prevHeight;\n body.style.overflowY = prevOverflow;\n const contentFilled = content.offsetHeight;\n const fillsContainer = contentFilled > contentNatural + 4;\n const viewportCap = Math.max(floor, window.innerHeight - taskbarH - Math.max(0, boxRef.current.y) - 24);\n const target = fillsContainer\n ? Math.min(boxRef.current.h, viewportCap)\n : Math.min(Math.max(floor, chrome + bodyNatural), viewportCap);\n const changed = Math.abs(target - lastH) > 1;\n if (changed) {\n lastH = target;\n setBox(prev => (Math.abs(prev.h - target) > 1 ? { ...prev, h: target } : prev));\n }\n // Freeze (commit the height and stop reacting) only once real content —\n // taller than the floor — has settled. Re-evaluated on every measure so\n // the freeze is *disarmed* whenever the body sits at the floor (a loading\n // spinner / pre-data placeholder, or a brief open-animation transient).\n // Otherwise an early transient above the floor could arm the timer and\n // lock the window at the collapsed floor height before the real, taller\n // content arrives — the bug where a detail window opened as a sliver on\n // first (uncached) open but was fine on reopen. Fill-height content\n // reports the ladder height (> floor), so it still freezes promptly.\n if (!widget) {\n if (target <= floor) {\n if (freezeTimer) { clearTimeout(freezeTimer); freezeTimer = null; }\n } else if (changed || freezeTimer === null) {\n if (freezeTimer) clearTimeout(freezeTimer);\n freezeTimer = setTimeout(() => {\n // One last look before freezing: anything that moved in the very\n // frame the timer fired (a footer un-hiding, a straggling image)\n // would otherwise be missed forever. An unchanged measure\n // confirms stability and freezes; a changed one re-armed this\n // timer above, so the next stable window freezes instead.\n const before = lastH;\n measure();\n if (lastH === before) setAutoHeightResolved(true);\n }, 160);\n }\n }\n };\n const ro = new ResizeObserver(measure);\n measure();\n // The footer sits OUTSIDE the body, so neither observer here sees it: it\n // mounts `hidden` and un-hides only when a portalled <ModalActions> flips\n // `hasActions` from a passive effect — after this layout effect's first\n // measure. Without watching it, `chrome` under-counts by exactly the\n // footer height and the window opens one footer too short (last row cut\n // off behind a scrollbar). Observing it re-measures on the un-hide and on\n // any later footer re-wrap while still unresolved.\n if (footerRef.current) ro.observe(footerRef.current);\n const mo = new MutationObserver(measure);\n mo.observe(body, { childList: true, subtree: true, characterData: true });\n return () => { ro.disconnect(); mo.disconnect(); if (freezeTimer) clearTimeout(freezeTimer); };\n // `hasFooterContent` re-runs the effect in the same commit that un-hides\n // the footer — one layout pass ahead of the ResizeObserver above, so the\n // corrected height paints together with the footer, not one frame late.\n }, [autoHeightResolved, widget, autoMinHeight, hasFooterContent]);\n\n // The measurement stops reacting once resolved, but the footer can still\n // (dis)appear afterwards — a <ModalActions> inside a lazy/slow body flips\n // `hasActions` after the freeze, and a consumer can conditionally render\n // `footer`/`actions` at any time. That changes the chrome under a frozen\n // window, silently costing the body the footer's height. Re-opening the\n // measurement would stomp a deliberate user resize, so keep the BODY height\n // invariant instead: nudge `box.h` by exactly the delta of a visibility\n // flip. Footer re-wraps without a flip stay absorbed by the body, as on any\n // fixed-size window; maximized boxes are never touched.\n useLayoutEffect(() => {\n if (!autoHeight || !autoHeightResolved || widget || !open) return;\n const footerEl = footerRef.current;\n if (!footerEl) return;\n let lastFooterH = footerEl.offsetHeight;\n const ro = new ResizeObserver(() => {\n if (!footerEl.isConnected) return; // close teardown, not a real flip\n const h = footerEl.offsetHeight;\n const delta = h - lastFooterH;\n const flipped = (h > 0) !== (lastFooterH > 0);\n lastFooterH = h;\n if (!flipped || delta === 0 || maximized) return;\n if (document.body.classList.contains('rosh-gesturing')) return;\n const floor = autoMinHeight ?? 240;\n const taskbarH = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--taskbar-height')) || 0;\n const viewportCap = Math.max(floor, window.innerHeight - taskbarH - Math.max(0, boxRef.current.y) - 24);\n setBox(prev => ({ ...prev, h: Math.min(Math.max(floor, prev.h + delta), viewportCap) }));\n });\n ro.observe(footerEl);\n return () => ro.disconnect();\n }, [autoHeight, autoHeightResolved, widget, open, maximized, autoMinHeight]);\n\n // When sidebar mode is toggled at runtime, snap existing windows to the\n // maximized box so they instantly fill the new work area.\n useEffect(() => {\n if (alwaysMaximized) {\n setMaximized(true);\n setBox(calcMaximized());\n }\n }, [alwaysMaximized, calcMaximized]);\n\n // Picking 'Classic' in Layout Mode means \"windowed\": every non-widget window\n // drops out of maximized and back onto the normal size ladder, whether it was\n // maximized by sidebar mode, by the default-window-size preference, or by\n // hand. Widgets are content-sized and never maximized, so they're exempt.\n // Layout Mode fires this on every Classic click — not only on a sidebar →\n // classic transition — so a shell already stuck full-screen can be recovered\n // without hunting through Behavior.\n //\n // The handler deliberately does *not* re-read `--layout-mode`: Layout writes\n // that var in an effect that lands after the click handler, so a guard here\n // would still see the outgoing 'sidebar' and skip the restore. Un-maximizing\n // unconditionally is safe either way — if the shell really is still in\n // sidebar mode, the alwaysMaximized effect above puts the window straight\n // back.\n useEffect(() => {\n if (widget) return;\n const restore = () => { setMaximized(false); setBox(calcWindowed()); };\n window.addEventListener('react-os-shell:restore-windowed', restore);\n return () => window.removeEventListener('react-os-shell:restore-windowed', restore);\n }, [widget, calcWindowed]);\n\n // Persist box position on changes (debounced to localStorage)\n useEffect(() => {\n if (open && boxKey) {\n _windowPositions[boxKey] = box;\n _savePositionsDebounced();\n }\n // Let the taskbar recompute its off-screen markers. `box` only changes on a\n // settled gesture (drag/resize commit, snap, reveal) — never per frame.\n if (open) window.dispatchEvent(new CustomEvent('modal-geometry'));\n }, [box, open, boxKey]);\n\n // Sync on viewport resize: refit a maximized window, and rescue a windowed\n // one the viewport has shrunk out from under.\n useEffect(() => {\n if (!open) return;\n const sync = () => {\n if (maximized) { setBox(calcMaximized()); return; }\n // Mid-gesture the panel is driven by inline styles, not `box` — leave it.\n if (document.body.classList.contains('rosh-gesturing')) return;\n // `clampReachable` returns the same object when nothing moved, so a\n // window that is already reachable neither re-renders nor re-persists.\n setBox(clampReachable);\n };\n window.addEventListener('resize', sync);\n // Only observe DOM changes when maximized — avoids unnecessary re-renders\n let observer: MutationObserver | null = null;\n if (maximized) {\n observer = new MutationObserver(sync);\n observer.observe(document.body, { childList: true, subtree: false, attributes: true, attributeFilter: ['class'] });\n }\n return () => { window.removeEventListener('resize', sync); observer?.disconnect(); };\n }, [open, maximized, calcMaximized]);\n\n // Reset when modal opens — skip if we have a saved position\n useEffect(() => {\n if (!open) return;\n setTouched(false);\n closingRef.current = false;\n // If we have a saved position in the store, restore it instead of resetting.\n // For `autoHeight` windows the stored `h` is only a placeholder — height is\n // owned by live measurement — so keep the currently-measured `h` rather\n // than clobbering it back to the (stale/seeded) saved value.\n if (boxKey && _windowPositions[boxKey]) {\n const saved = _windowPositions[boxKey];\n setBox(prev => clampReachable(autoHeight ? { ...saved, h: prev.h } : { ...saved }));\n return;\n }\n if (initialBox) {\n setBox({ x: initialBox.x, y: initialBox.y, w: initialBox.w, h: initialBox.h });\n setMaximized(initialBox.maximized);\n }\n // Don't call calcWindowed() here — useState already set the initial position\n }, [open]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Auto-detect dirty\n useEffect(() => {\n if (!open || dirty !== 'auto') return;\n const handler = (e: Event) => { if (panelRef.current?.contains(e.target as HTMLElement)) setTouched(true); };\n document.addEventListener('input', handler, true);\n document.addEventListener('change', handler, true);\n return () => { document.removeEventListener('input', handler, true); document.removeEventListener('change', handler, true); };\n }, [open, dirty]);\n\n const isDirty = dirty === 'auto' ? touched : dirty === true;\n\n const guardedClose = useCallback(async () => {\n if (closingRef.current) return;\n if (isDirty) {\n closingRef.current = true;\n const ok = await confirm({ title: 'Discard changes?', message: 'You have unsaved changes. Are you sure you want to close? All changes will be lost.', confirmLabel: 'Discard', cancelLabel: 'Keep Editing', variant: 'warning' });\n closingRef.current = false;\n if (!ok) return;\n }\n onClose();\n }, [isDirty, onClose]);\n\n // Shell chrome outside the panel (taskbar tabs and their previews) cannot\n // call this Modal's guardedClose directly. Route keyed close requests back\n // through the same decision so every close surface shares one guard, copy,\n // and in-flight lock instead of growing a second confirmation path.\n useLayoutEffect(() => {\n if (!open || !windowKey) return;\n const handler = (event: Event) => {\n if ((event as CustomEvent<ModalCloseRequestDetail>).detail?.windowKey === windowKey) guardedClose();\n };\n window.addEventListener(MODAL_CLOSE_REQUEST_EVENT, handler);\n return () => window.removeEventListener(MODAL_CLOSE_REQUEST_EVENT, handler);\n }, [open, windowKey, guardedClose]);\n\n // Pre-snap box: if the user drags a window that's currently snapped to an\n // edge, restore it to its previous \"natural\" size so dragging it across\n // the screen feels right. Set on snap-drop, consumed on next drag start.\n const preSnapBoxRef = useRef<Box | null>(null);\n\n // ── Drag ──\n const startDrag = useCallback((e: React.PointerEvent) => {\n if (e.button !== 0) return;\n if ((e.target as HTMLElement).closest('button, input, a, kbd, select, textarea')) return;\n setWindowMenu(null);\n activateModal(modalId);\n // In sidebar layout mode the window is locked to the work area —\n // the title bar still activates the window but doesn't drag it.\n if (alwaysMaximized) { e.preventDefault(); return; }\n e.preventDefault();\n // The gesture (pointer capture, drag shield, compositor-layer promotion)\n // is deferred until the pointer actually moves past DRAG_THRESHOLD — a\n // press-and-hold or a plain click on the title bar must not engage any of\n // it. `null` until the first real move; started in `move`, ended in `up`.\n const dragHandle = e.currentTarget as HTMLElement;\n const dragPointerId = e.pointerId;\n let endGesture: (() => void) | null = null;\n const sx = e.clientX, sy = e.clientY;\n const panel = panelRef.current;\n const rect = panel?.getBoundingClientRect();\n\n // If this window is currently snapped, restore its pre-snap dimensions\n // and reposition so the cursor lands roughly in the title bar.\n let ox: number, oy: number, actualH: number, actualW: number;\n if (preSnapBoxRef.current) {\n const restore = preSnapBoxRef.current;\n preSnapBoxRef.current = null;\n actualW = restore.w;\n actualH = restore.h;\n // Center the restored window horizontally on the cursor; keep title\n // bar at cursor Y.\n const offsetX = rect ? Math.min(Math.max(20, e.clientX - rect.left), restore.w - 20) : restore.w / 2;\n ox = e.clientX - offsetX;\n oy = e.clientY - 12;\n if (panel) {\n panel.style.width = `${actualW}px`;\n panel.style.height = `${actualH}px`;\n panel.style.left = `${ox}px`;\n panel.style.top = `${oy}px`;\n }\n } else {\n ox = rect ? rect.left : boxRef.current.x;\n oy = rect ? rect.top : boxRef.current.y;\n actualH = rect ? rect.height : boxRef.current.h;\n actualW = rect ? rect.width : boxRef.current.w;\n }\n setMaximized(false);\n setBox(b => ({ ...b, x: ox, y: oy, w: actualW, h: actualH }));\n\n // Snap zone tracking — only re-render preview when zone CHANGES.\n let currentZone: SnapZone | null = null;\n\n const move = (ev: PointerEvent) => {\n // Promote to a real drag gesture on the first move past the threshold.\n if (!endGesture) {\n if (Math.abs(ev.clientX - sx) < DRAG_THRESHOLD && Math.abs(ev.clientY - sy) < DRAG_THRESHOLD) return;\n endGesture = beginPointerGesture(dragHandle, dragPointerId, 'move', 'move');\n // The exposé exit path leaves `transition: transform` on the panel for\n // ~320ms — a drag starting inside that window would animate/lag every\n // frame's translate below, so pin transitions off for the gesture.\n if (panel) panel.style.transition = 'none';\n }\n const nx = ox + ev.clientX - sx;\n const ny = Math.max(0, oy + ev.clientY - sy);\n // Move via transform, NOT left/top: mutating left/top invalidates layout\n // of the whole window subtree every frame — reflowing a heavy list at\n // pointer rate is what made drags stutter on older machines. translate()\n // runs on the compositor against the will-change:transform layer the\n // gesture style promotes, so the window's contents are never re-laid-out\n // or repainted mid-drag. Inline left/top stay pinned at the gesture\n // origin (matching the `box` state set above), so a mid-drag React\n // re-render re-applies the same origin and can't fight the transform —\n // with left/top writes it would snap the window back for a frame.\n if (panel) panel.style.transform = `translate(${nx - ox}px, ${ny - oy}px)`;\n boxRef.current = { ...boxRef.current, x: nx, y: ny };\n\n // Snap detection: ignore for widgets so they keep free-positioning.\n if (!widget) {\n const zone = detectSnapZone(ev.clientX, ev.clientY);\n if (zone !== currentZone) {\n currentZone = zone;\n if (zone) showSnapPreview(calcSnapBox(zone));\n else hideSnapPreview();\n }\n }\n };\n const up = () => {\n window.removeEventListener('pointermove', move);\n window.removeEventListener('pointerup', up);\n endGesture?.();\n hideSnapPreview();\n // Commit the drag through the reachability clamp — the pointer can leave\n // the viewport, so without this a window can be shoved past the right or\n // bottom edge and never grabbed again.\n const finalBox = clampReachable({ ...boxRef.current });\n boxRef.current = finalBox;\n\n // Snap drop: lock to the snap target, save the pre-snap size for next drag.\n if (!widget && currentZone) {\n preSnapBoxRef.current = { x: ox, y: oy, w: actualW, h: actualH };\n const snapped = calcSnapBox(currentZone);\n // Commit the snap target inline in the same frame the transform is\n // cleared, so the panel never flashes back to the gesture origin.\n if (panel) {\n panel.style.left = `${snapped.x}px`;\n panel.style.top = `${snapped.y}px`;\n panel.style.width = `${snapped.w}px`;\n panel.style.height = `${snapped.h}px`;\n panel.style.transform = '';\n panel.style.transition = '';\n }\n setBox(snapped);\n return;\n }\n\n // For widgets, determine anchor side based on center position vs viewport midpoint\n if (widget) {\n const centerX = finalBox.x + finalBox.w / 2;\n const mid = window.innerWidth / 2;\n setWidgetAnchor(centerX > mid ? 'right' : 'left');\n }\n // Commit the drag delta into inline left/top and clear the transform in\n // one style pass, then sync React state once — the inline position holds\n // the window in place until the re-render lands.\n if (panel) {\n panel.style.left = `${finalBox.x}px`;\n panel.style.top = `${finalBox.y}px`;\n panel.style.transform = '';\n panel.style.transition = '';\n }\n setBox(finalBox);\n };\n window.addEventListener('pointermove', move);\n window.addEventListener('pointerup', up);\n }, []);\n\n // ── Resize ──\n const startResizeCorner = useCallback((e: React.PointerEvent, corner: 'se' | 'sw' | 'ne' | 'nw' | 'n' | 's' | 'e' | 'w') => {\n if (e.button !== 0) return;\n e.preventDefault(); e.stopPropagation();\n // Deferred until the pointer moves past DRAG_THRESHOLD (see startDrag) so a\n // stray press on a resize edge doesn't flatten every frosted window.\n const resizeHandle = e.currentTarget as HTMLElement;\n const resizePointerId = e.pointerId;\n let endGesture: (() => void) | null = null;\n const sx = e.clientX, sy = e.clientY;\n const panel = panelRef.current;\n // Always use the live rendered rect as the origin so we don't drift\n // when the panel was previously maximised or pinned.\n const rect = panel?.getBoundingClientRect();\n const ox = rect ? rect.left : boxRef.current.x;\n const oy = rect ? rect.top : boxRef.current.y;\n const ow = rect ? rect.width : boxRef.current.w;\n const oh = rect ? rect.height : boxRef.current.h;\n const isWest = corner === 'sw' || corner === 'nw' || corner === 'w';\n const isNorth = corner === 'ne' || corner === 'nw' || corner === 'n';\n const isEast = corner === 'se' || corner === 'ne' || corner === 'e';\n const isSouth = corner === 'se' || corner === 'sw' || corner === 's';\n setMaximized(false);\n // Pin the box to the actual rendered coordinates immediately so the\n // panel does not jump if it was previously maximised.\n setBox({ x: ox, y: oy, w: ow, h: oh });\n boxRef.current = { x: ox, y: oy, w: ow, h: oh };\n\n const compute = (dx: number, dy: number) => {\n let nx = ox, ny = oy, nw = ow, nh = oh;\n if (isEast) nw = Math.max(MIN_W, ow + dx);\n if (isSouth) nh = Math.max(MIN_H, oh + dy);\n if (isWest) {\n const targetW = Math.max(MIN_W, ow - dx);\n // Anchor the east edge: as W grows/shrinks, x moves opposite so the\n // east edge (ox + ow) stays fixed.\n nx = ox + ow - targetW;\n nw = targetW;\n }\n if (isNorth) {\n const targetH = Math.max(MIN_H, oh - dy);\n ny = oy + oh - targetH;\n nh = targetH;\n }\n return { x: nx, y: ny, w: nw, h: nh };\n };\n\n let raf = 0;\n let pending: { x: number; y: number; w: number; h: number } | null = null;\n const flush = () => {\n raf = 0;\n if (!pending) return;\n const next = pending; pending = null;\n boxRef.current = next;\n // Write straight to the DOM per frame. Routing every frame through\n // setBox re-rendered the whole window — reflowing a heavy <iframe> body\n // on each animation frame. React state is synced once on pointer-up\n // (mirrors the drag path, which also keeps inline styles mid-gesture).\n if (panel) {\n panel.style.left = `${next.x}px`;\n panel.style.top = `${next.y}px`;\n panel.style.width = `${next.w}px`;\n panel.style.height = `${next.h}px`;\n }\n };\n const move = (ev: PointerEvent) => {\n // Promote to a real resize gesture on the first move past the threshold.\n if (!endGesture) {\n if (Math.abs(ev.clientX - sx) < DRAG_THRESHOLD && Math.abs(ev.clientY - sy) < DRAG_THRESHOLD) return;\n endGesture = beginPointerGesture(resizeHandle, resizePointerId, RESIZE_CURSOR[corner], 'resize');\n }\n pending = compute(ev.clientX - sx, ev.clientY - sy);\n if (!raf) raf = requestAnimationFrame(flush);\n };\n const up = () => {\n window.removeEventListener('pointermove', move);\n window.removeEventListener('pointerup', up);\n if (raf) cancelAnimationFrame(raf);\n flush();\n endGesture?.();\n setBox({ ...boxRef.current });\n };\n window.addEventListener('pointermove', move);\n window.addEventListener('pointerup', up);\n }, []);\n\n // ── Keyboard window management ──\n // The title bar is the pointer's move handle, so it is also the keyboard's:\n // a tab stop whose arrows move the window, WCAG 2.1.1 for the window itself.\n // Plain arrows move, Shift+arrows resize from the bottom-right corner,\n // Ctrl/Cmd+arrows snap (left/right half, maximize, restore/minimize) and\n // Enter mirrors the maximize button. Discrete steps go through setBox — the\n // compositor-layer machinery above exists for pointer-rate updates, which a\n // keypress is not.\n const KEY_STEP = 24;\n const onTitleBarKeyDown = useCallback((e: React.KeyboardEvent) => {\n // Keys pressed on the bar's own controls stay theirs — Enter on the close\n // button must close, not toggle maximize.\n if ((e.target as HTMLElement).closest('button, input, a, kbd, select, textarea')) return;\n const arrows: Record<string, [number, number]> = {\n ArrowLeft: [-1, 0], ArrowRight: [1, 0], ArrowUp: [0, -1], ArrowDown: [0, 1],\n };\n const dir = arrows[e.key];\n if (!dir && e.key !== 'Enter') return;\n e.preventDefault();\n e.stopPropagation();\n activateModal(modalId);\n\n if (e.key === 'Enter') {\n if (maximized) { setMaximized(false); setBox(calcWindowed()); } else { setMaximized(true); setBox(calcMaximized()); }\n return;\n }\n const [dx, dy] = dir!;\n if (e.ctrlKey || e.metaKey) {\n // Snap. Save the pre-snap box exactly like a snap-drop does, so the next\n // drag (or Ctrl+Down) restores the window's natural size.\n const savePreSnap = () => { if (!preSnapBoxRef.current) preSnapBoxRef.current = { ...boxRef.current }; };\n if (dy < 0) { savePreSnap(); setMaximized(true); setBox(calcMaximized()); return; }\n if (dy > 0) {\n if (maximized) { setMaximized(false); setBox(calcWindowed()); return; }\n if (preSnapBoxRef.current) {\n const restore = clampReachable(preSnapBoxRef.current);\n preSnapBoxRef.current = null;\n boxRef.current = restore;\n setBox(restore);\n return;\n }\n _minimizeModal(modalId);\n return;\n }\n savePreSnap();\n setMaximized(false);\n const snapped = calcSnapBox(dx < 0 ? 'left' : 'right');\n boxRef.current = snapped;\n setBox(snapped);\n return;\n }\n if (maximized) return; // a maximized window is pinned, same as the pointer path\n const b = boxRef.current;\n const next = e.shiftKey\n ? { ...b, w: Math.max(MIN_W, b.w + dx * KEY_STEP), h: Math.max(MIN_H, b.h + dy * KEY_STEP) }\n : clampReachable({ ...b, x: b.x + dx * KEY_STEP, y: Math.max(0, b.y + dy * KEY_STEP) });\n boxRef.current = next;\n setBox(next);\n }, [modalId, maximized, calcWindowed, calcMaximized]);\n // Shared by the snap-layouts picker: same pre-snap save as a snap-drop and\n // the keyboard path, so Ctrl+Down / the next drag restores the natural box.\n const applySnapZone = useCallback((zone: SnapZone) => {\n if (!preSnapBoxRef.current) preSnapBoxRef.current = { ...boxRef.current };\n setMaximized(false);\n const snapped = calcSnapBox(zone);\n boxRef.current = snapped;\n setBox(snapped);\n activateModal(modalId);\n }, [modalId]);\n\n // Spread onto each desktop title-bar variant. Locked layouts (sidebar mode)\n // and exposé get no tab stop — there is nothing the keys could do there.\n const titleBarKeyProps = alwaysMaximized || exposeActive ? {} : {\n tabIndex: 0,\n role: 'group',\n 'aria-label': titleTooltip ? `${titleTooltip} — ${winStr.windowSuffix}` : winStr.windowSuffix,\n 'aria-keyshortcuts': 'ArrowUp ArrowDown ArrowLeft ArrowRight Shift+ArrowUp Shift+ArrowDown Shift+ArrowLeft Shift+ArrowRight Control+ArrowUp Control+ArrowDown Control+ArrowLeft Control+ArrowRight Enter',\n onKeyDown: onTitleBarKeyDown,\n } as const;\n\n const reset = () => { setMaximized(true); setBox(calcMaximized()); };\n const handleMinimize = () => {\n const saved = { ...boxRef.current, maximized };\n if (onMinimize) {\n onMinimize(saved);\n } else {\n const label = typeof title === 'string' ? title : (panelRef.current?.querySelector('[data-window-title]')?.textContent || 'Window');\n const route = window.location.pathname;\n globalMinimize({\n id: copyText || label || modalId, type: 'modal', label, route, savedBox: saved,\n });\n onClose();\n }\n };\n\n // ── Submit modal ──\n const submitModal = useCallback(() => {\n const panel = panelRef.current;\n if (!panel) return;\n const form = panel.querySelector('form');\n if (form) { form.requestSubmit(); } else {\n const btn = panel.querySelector<HTMLButtonElement>(MODAL_SUBMIT_SELECTOR);\n if (btn && !btn.disabled) btn.click();\n }\n }, []);\n\n // Cmd+Enter submits, bare Enter prevented — only for topmost modal\n useEffect(() => {\n if (!open) return;\n const handler = (e: KeyboardEvent) => {\n if (activationOrder[activationOrder.length - 1] !== modalId) return;\n if (e.key === 'Enter') {\n const target = e.target as HTMLElement;\n if (target.tagName === 'TEXTAREA' || target.isContentEditable) return;\n if (e.metaKey || e.ctrlKey) { e.preventDefault(); submitModal(); }\n else if (target.tagName === 'INPUT' && target.closest('form')) {\n // Let Enter submit the form naturally (e.g. password fields)\n return;\n }\n else { e.preventDefault(); }\n }\n };\n window.addEventListener('keydown', handler, true);\n return () => window.removeEventListener('keydown', handler, true);\n }, [open, submitModal, modalId]);\n\n // Cmd+S save-and-stay, Alt+Shift+D duplicate — only for topmost modal\n useEffect(() => {\n if (!open) return;\n const handler = (e: KeyboardEvent) => {\n if (activationOrder[activationOrder.length - 1] !== modalId) return;\n // `detail.modalId` is LOAD-BEARING, not diagnostic. The dispatch is\n // correctly restricted to the topmost modal by the line above, but the\n // event itself was identity-free and went to `document` — so every\n // mounted window's receiver answered it, and one Cmd+S saved (or\n // duplicated) every open form at once. Receivers match on this id; see\n // useModalSave / useModalDuplicate.\n if ((e.metaKey || e.ctrlKey) && e.key === 's') { e.preventDefault(); document.dispatchEvent(new CustomEvent('modal-save', { detail: { modalId } })); setTouched(false); }\n else if (e.altKey && e.shiftKey && (e.code === 'KeyD' || e.key === 'D' || e.key === 'd')) { e.preventDefault(); document.dispatchEvent(new CustomEvent('modal-duplicate', { detail: { modalId } })); }\n };\n window.addEventListener('keydown', handler, true);\n return () => window.removeEventListener('keydown', handler, true);\n }, [open]);\n\n // ESC → close only the topmost modal (with dirty guard)\n useEffect(() => {\n if (!open) return;\n // Widgets (Calculator, Weather, Currency, Pomodoro, World Clock, etc.) are\n // ambient — ESC shouldn't close them. They have their own right-click Close.\n if (widget) return;\n const handler = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && activationOrder[activationOrder.length - 1] === modalId) {\n // Window content gets first refusal (measure tools, command bars…).\n if (runEscapeInterceptors(e)) { e.preventDefault(); e.stopPropagation(); return; }\n e.preventDefault(); e.stopPropagation(); guardedClose();\n }\n };\n window.addEventListener('keydown', handler, true);\n return () => window.removeEventListener('keydown', handler, true);\n }, [open, guardedClose, modalId, widget]);\n\n // J/K navigation\n const hasNav = open && (onNext !== undefined || onPrev !== undefined);\n const showBoundaryToast = useCallback((edge: 'top' | 'bottom') => {\n const existing = document.getElementById('nav-boundary-toast');\n if (existing) existing.remove();\n const lines = edge === 'bottom'\n ? [\"That's the last one, chief.\", \"You've hit rock bottom... of the list.\", \"End of the line, buddy.\", \"Nothing left. Go outside.\", \"Congratulations, you scrolled to the void.\", \"There's no more. I checked.\", \"You've reached the edge of the known universe.\", \"Plot twist: there is no next one.\", \"Even scrolling has limits. Unlike your ambition.\", \"Last one. Time to touch grass.\"]\n : [\"Already at the top. Overachiever.\", \"There is no item above this. Trust me.\", \"You're #1. Literally.\", \"Can't go higher. You've peaked.\", \"This is it. The summit. The top.\", \"First item. No VIP lounge above this.\", \"Going up? Nope. Elevator's broken.\", \"You want negative indexes? Bold.\", \"Top of the list. Top of the world.\", \"The only way is down from here.\"];\n const msg = lines[Math.floor(Math.random() * lines.length)];\n const toast = document.createElement('div');\n toast.id = 'nav-boundary-toast';\n toast.className = 'fixed bottom-6 left-1/2 -translate-x-1/2 z-[9999] bg-gray-900 text-white px-5 py-2.5 rounded-lg shadow-lg text-sm font-medium transition-opacity duration-300';\n toast.textContent = msg;\n document.body.appendChild(toast);\n setTimeout(() => { toast.style.opacity = '0'; setTimeout(() => toast.remove(), 300); }, 2000);\n }, []);\n\n useEffect(() => {\n if (!open) return;\n const handler = (e: KeyboardEvent) => {\n if (activationOrder[activationOrder.length - 1] !== modalId) return;\n const tag = (e.target as HTMLElement).tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return;\n if ((e.target as HTMLElement).isContentEditable) return;\n if (e.key === 'j' && hasNav) { e.preventDefault(); if (onNext) onNext(); else showBoundaryToast('bottom'); }\n if (e.key === 'k' && hasNav) { e.preventDefault(); if (onPrev) onPrev(); else showBoundaryToast('top'); }\n };\n window.addEventListener('keydown', handler);\n return () => window.removeEventListener('keydown', handler);\n }, [open, onNext, onPrev, hasNav, showBoundaryToast, modalId]);\n\n // When minimized, stay mounted but hidden (preserves all state)\n if (!open || interceptedRef.current) return null;\n\n // ── Full window — render via portal when nested to escape parent overflow:hidden ──\n const exposeTile = exposeActive ? computeExposeTile(modalId) : null;\n // Factor that shrinks a full-size window into its exposé tile. Hoisted so the\n // hover close-button can counter-scale (1/exposeScale) back to a real,\n // clickable on-screen size no matter how small the tile is.\n const exposeScale = exposeActive && exposeTile\n ? Math.min(exposeTile.w / box.w, exposeTile.h / box.h)\n : 1;\n const exposeStyle = (() => {\n if (exposeActive && exposeTile) {\n const scale = exposeScale;\n const scaledW = box.w * scale;\n const scaledH = box.h * scale;\n const tx = exposeTile.x + (exposeTile.w - scaledW) / 2 - box.x;\n const ty = exposeTile.y + (exposeTile.h - scaledH) / 2 - box.y;\n // Hover and keyboard-cycle both light the tile up. They share the\n // same glow so a mouse user and a keyboard user are always looking\n // at the same visual cue. When both apply (mouse hovering the\n // currently-keyboard-highlighted tile), hover wins z-index-wise so\n // the hover ring stays readable above neighbours.\n const lit = exposeHovered || exposeKeyboardHighlight;\n return {\n transform: `translate(${tx}px, ${ty}px) scale(${scale})`,\n transformOrigin: 'top left' as const,\n transition: 'transform 280ms cubic-bezier(0.2, 0.8, 0.2, 1), box-shadow 280ms',\n cursor: 'pointer',\n // Lifted tile sits above its neighbours so the glow isn't clipped.\n zIndex: lit ? 2020 : 2010,\n boxShadow: lit\n ? '0 24px 72px rgba(0,0,0,0.6), 0 0 0 2px rgba(255,255,255,0.55), 0 0 36px 12px rgba(96,165,250,0.85), 0 0 96px 28px rgba(96,165,250,0.55)'\n : '0 16px 48px rgba(0,0,0,0.55)',\n pointerEvents: 'auto' as const,\n };\n }\n if (exposeExiting && isExposeTileable) {\n // All tileable windows glide from their thumbnail back to their real\n // position simultaneously — preserve the transition rule so the\n // transform-from-tile animates instead of snapping. The \"picked\" one\n // (when the user clicked a thumbnail to leave) gets a spring-y curve\n // and an elevated z-index so it reads as the focal point of the move.\n // Durations are deliberately on the slow side (~600 ms) so the user\n // can read the choreography as every window slides back home.\n const picked = exposeExitRole === 'picked';\n return {\n transition: picked\n ? 'transform 640ms cubic-bezier(0.34, 1.42, 0.64, 1), box-shadow 600ms'\n : 'transform 600ms cubic-bezier(0.2, 0.8, 0.2, 1), box-shadow 600ms',\n ...(picked ? { zIndex: 2030 } : {}),\n };\n }\n return null;\n })();\n\n const content = (\n <div>\n {/* Window */}\n {/* `data-utility` marks a window that *may* be pinned on top; `data-pinned-top`\n marks one that currently *is*, and so is riding the 999 lane rather than the\n activation-order ladder. The taskbar's peek needs the latter to know which\n windows it must not restack. */}\n <div ref={panelRef} data-modal-panel data-modal-id={modalId} data-window-key={windowKey || undefined} {...(allowPinOnTop ? { 'data-utility': '' } : {})} {...(pinnedOnTop ? { 'data-pinned-top': '' } : {})} {...(widget ? { 'data-widget': '' } : {})}\n className={`fixed rounded-2xl flex flex-col overflow-hidden ${widget ? (isActive ? 'shadow-2xl' : 'shadow-lg') : `border ${isActive ? 'shadow-2xl border-gray-200' : 'shadow-lg border-gray-300'}`}`}\n onMouseDownCapture={(e) => {\n swallowInactiveClickRef.current = false;\n if (exposeActive) {\n // The exposé close button handles its own click — let it through so\n // the capture-phase \"select this window\" logic doesn't swallow it.\n if ((e.target as HTMLElement).closest('[data-expose-close]')) return;\n // In exposé mode, any click on a tileable window selects it.\n e.preventDefault();\n e.stopPropagation();\n // Publish the picked id BEFORE flipping exposeState off so all\n // panels see it on their first exit-render and pick the right\n // role (picked vs unpicked).\n setExposeExitFocus(modalId);\n setExposeState(false);\n activateModal(modalId);\n return;\n }\n // SG#00391: a primary-button press on an INACTIVE window's\n // interactive element raises the window and does nothing else — no\n // click-through (a link in a background tile used to navigate when\n // the user only meant to bring the window forward). Widgets and\n // pinned-on-top utility panels keep the pass-through; the active\n // window is untouched. Title-bar chrome ([data-window-chrome]:\n // close/minimize/maximize/pin/icon-menu) is exempt so a background\n // window still closes in ONE click. preventDefault here only affects\n // interactive targets, so text selection over background content is\n // unchanged.\n if (!isActive && !widget && !pinnedOnTop && e.button === 0) {\n const target = e.target as HTMLElement;\n // Ignore events bubbling out of a nested child modal's panel.\n if (target.closest('[data-modal-panel]') === panelRef.current\n && target.closest('button, input, a, select, textarea')\n && !target.closest('[data-window-chrome]')) {\n e.preventDefault();\n e.stopPropagation();\n swallowInactiveClickRef.current = true;\n setWindowMenu(null);\n activateModal(modalId);\n // If the mouseup lands OUTSIDE the panel (drag off the control),\n // no paired click reaches onClickCapture and the flag would eat\n // the next keyboard/programmatic click. mouseup fires before\n // click in the same task, so clear on the next tick — after the\n // paired click (if any) has been dispatched and consumed.\n window.addEventListener('mouseup', () => {\n setTimeout(() => { swallowInactiveClickRef.current = false; }, 0);\n }, { once: true });\n }\n }\n }}\n onClickCapture={(e) => {\n // Second half of the SG#00391 swallow: activation already happened\n // on mousedown; eat exactly the paired click so the control never\n // fires. The flag (not `isActive`, which is already true by now)\n // guards against double-activation and against eating later clicks.\n if (swallowInactiveClickRef.current) {\n swallowInactiveClickRef.current = false;\n e.preventDefault();\n e.stopPropagation();\n }\n }}\n onMouseDown={(e) => {\n if (exposeActive) return;\n setWindowMenu(null);\n // Only a press that landed inside THIS panel raises it. Two cases\n // are excluded, and both reach here because React bubbles portaled\n // events through the React tree, not the DOM tree — so every\n // ancestor window sees a press that is nowhere near its own panel:\n // • a nested child modal's panel — that press belongs to the child;\n // • no panel at all — a body-portaled popup (Select/SearchableSelect\n // option list, PopupMenu). The ancestors fire in child→parent\n // order, so the OUTERMOST window activated last and buried the\n // nested window the user was working in: picking a User Group in\n // admin's \"Edit User\" raised the parent user window over the form,\n // which reads as a new window opening on top of the one you're in.\n const targetPanel = (e.target as HTMLElement).closest('[data-modal-panel]');\n if (targetPanel !== panelRef.current) return;\n if (!(e.target as HTMLElement).closest('button, input, a, select, textarea')) {\n activateModal(modalId);\n }\n }}\n style={isMobile ? {\n // Mobile fullscreen: ignore stored box, fill viewport down to bottom\n // nav. Widgets stay hidden on mobile. Only the active window is\n // visible — all others hidden so swipe-right reveals the home\n // wallpaper backdrop. Exception: when a sibling Modal is being\n // swiped to-back and we're its `openedFrom` parent, un-hide so the\n // user sees their parent list during the slide instead of just the\n // wallpaper.\n zIndex: zIndex + 1,\n top: 0, left: 0, right: 0,\n bottom: 'var(--mobile-bottom-nav, 56px)',\n width: 'auto', height: 'auto',\n transform: `translateX(${swipeX}px)`,\n transition: swipeDragging ? 'none' : 'transform 180ms ease-out',\n ...(widget ? { display: 'none' } : {}),\n ...(zIndex < 0 ? { display: 'none' } : {}),\n ...((!isActive && !pinnedOnTop && !(swipingParentKey && windowKey === swipingParentKey)) ? { display: 'none' } : {}),\n } : {\n // The panel is always a definite height — even while an `autoHeight`\n // window is still measuring (box.h is seeded from the size ladder).\n // The measurement effect adjusts box.h to hug the content; rendering\n // at a definite height the whole way through means fill-height\n // content (flex-1 / h-full) never collapses to the floor.\n zIndex: pinnedOnTop ? 999 : zIndex + 1, width: box.w, height: box.h, top: box.y,\n ...(widget && widgetAnchor === 'right' ? { right: window.innerWidth - box.x - box.w } : { left: box.x }),\n ...(zIndex < 0 && !pinnedOnTop ? { display: 'none' } : {}),\n ...(exposeStyle ?? {}),\n }}\n >\n {/* Mobile swipe-from-left-edge gesture zone. Captures pointerdown only\n * in the leftmost 22px so it doesn't interfere with normal taps or\n * scrolls in the body. */}\n {isMobile && !widget && (\n <div\n onPointerDown={handleEdgePointerDown}\n className=\"absolute top-0 bottom-0 left-0 w-[22px] z-[5]\"\n style={{ touchAction: 'pan-y' }}\n aria-hidden=\"true\"\n />\n )}\n\n {/* HEADER — draggable on desktop, hidden on mobile (apps go fullscreen\n * with a swipe-from-left-edge gesture to close). */}\n {widget ? (\n /* Widget: no title bar — drag via body, close via right-click context menu */\n null\n ) : isMobile ? (\n null\n ) : compact ? (\n /* Compact: smaller title bar with title + close only */\n <div onPointerDown={startDrag} data-window-chrome=\"\" {...titleBarKeyProps}\n className={`flex items-center justify-between px-3 py-1.5 border-b border-gray-200 shrink-0 cursor-move select-none rounded-t-2xl focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-blue-400 ${isActive ? 'backdrop-blur-sm' : ''}`}\n style={{ touchAction: 'none', backgroundColor: isActive ? `rgb(var(--window-header-rgb) / var(--active-header-opacity, 0.8))` : `rgb(var(--window-header-rgb) / var(--inactive-header-opacity, 0.7))` }}>\n <div data-window-title title={titleTooltip} className=\"text-sm font-medium min-w-0 flex-1 truncate flex items-center gap-1.5\" style={{ color: isActive ? 'var(--window-title-active, rgb(17 24 39))' : 'var(--window-title-inactive, rgb(156 163 175))' }}>\n {!exposeActive && renderIconButton()}\n <span className=\"truncate\">{exposeActive ? extractTitleText(displayTitle) : displayTitle}</span>\n </div>\n {!exposeActive && (\n <div className=\"flex items-center gap-1 shrink-0 ml-2\">\n {allowPinOnTop && (\n <button onClick={() => setPinnedOnTop(p => !p)} title={pinnedOnTop ? winStr.unpin : winStr.pinOnTop}\n className={`p-0.5 rounded hover:bg-gray-200 ${pinnedOnTop ? 'text-blue-600' : 'text-gray-400 hover:text-gray-600'}`}>\n <svg className=\"h-3 w-3\" fill={pinnedOnTop ? 'currentColor' : 'none'} viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M16.5 3.75V16.5L12 14.25 7.5 16.5V3.75m9 0H18A2.25 2.25 0 0120.25 6v12A2.25 2.25 0 0118 20.25H6A2.25 2.25 0 013.75 18V6A2.25 2.25 0 016 3.75h1.5m9 0h-9\" /></svg>\n </button>\n )}\n <button type=\"button\" onClick={guardedClose} className=\"rounded p-0.5 text-gray-400 hover:text-gray-600 hover:bg-gray-200\">\n <XMarkIcon className=\"h-4 w-4\" />\n </button>\n </div>\n )}\n </div>\n ) : appStyle ? (\n /* App style: small title bar like compact, but keeps minimize/maximize for full window control. */\n <div onPointerDown={startDrag} data-window-chrome=\"\" {...titleBarKeyProps}\n className={`flex items-center justify-between px-3 py-1.5 border-b border-gray-200 shrink-0 cursor-move select-none rounded-t-2xl focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-blue-400 ${isActive ? 'backdrop-blur-sm' : ''}`}\n style={{ touchAction: 'none', backgroundColor: isActive ? `rgb(var(--window-header-rgb) / var(--active-header-opacity, 0.8))` : `rgb(var(--window-header-rgb) / var(--inactive-header-opacity, 0.7))` }}>\n <div data-window-title title={titleTooltip} className=\"text-sm font-medium min-w-0 flex-1 truncate flex items-center gap-1.5\" style={{ color: isActive ? 'var(--window-title-active, rgb(17 24 39))' : 'var(--window-title-inactive, rgb(156 163 175))' }}>\n {!exposeActive && renderIconButton()}\n <span className=\"truncate\">{exposeActive ? extractTitleText(displayTitle) : displayTitle}</span>\n </div>\n {!exposeActive && (\n <div className=\"flex items-center gap-0.5 shrink-0 ml-2\">\n {allowPinOnTop && (\n <button onClick={() => setPinnedOnTop(p => !p)} title={pinnedOnTop ? winStr.unpin : winStr.pinOnTop}\n className={`p-0.5 rounded hover:bg-gray-200 ${pinnedOnTop ? 'text-blue-600' : 'text-gray-400 hover:text-gray-600'}`}>\n <svg className=\"h-3 w-3\" fill={pinnedOnTop ? 'currentColor' : 'none'} viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M16.5 3.75V16.5L12 14.25 7.5 16.5V3.75m9 0H18A2.25 2.25 0 0120.25 6v12A2.25 2.25 0 0118 20.25H6A2.25 2.25 0 013.75 18V6A2.25 2.25 0 016 3.75h1.5m9 0h-9\" /></svg>\n </button>\n )}\n <button onClick={() => _minimizeModal(modalId)} title={winStr.minimize} className=\"text-gray-400 hover:text-gray-600 px-1 py-0.5 rounded hover:bg-gray-200 text-xs leading-none\">─</button>\n {!alwaysMaximized && (\n <SnapLayoutsButton\n maximized={maximized}\n onToggleMax={() => { if (maximized) { setMaximized(false); setBox(calcWindowed()); } else { reset(); } }}\n onSnap={applySnapZone}\n buttonClassName=\"text-gray-400 hover:text-gray-600 px-1 py-0.5 rounded hover:bg-gray-200 text-xs leading-none\"\n strings={winStr}\n />\n )}\n <button type=\"button\" onClick={guardedClose} className=\"rounded p-0.5 text-gray-400 hover:text-gray-600 hover:bg-gray-200\">\n <XMarkIcon className=\"h-4 w-4\" />\n </button>\n </div>\n )}\n </div>\n ) : (\n <div onPointerDown={startDrag} data-window-chrome=\"\" {...titleBarKeyProps}\n className={`flex items-center justify-between px-4 py-2.5 border-b border-gray-200 shrink-0 cursor-move select-none rounded-t-2xl focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-blue-400 ${isActive ? 'backdrop-blur-sm' : ''}`}\n style={{ touchAction: 'none', backgroundColor: isActive ? `rgb(var(--window-header-rgb) / var(--active-header-opacity, 0.8))` : `rgb(var(--window-header-rgb) / var(--inactive-header-opacity, 0.7))` }}>\n <div data-window-title title={titleTooltip} className=\"text-base font-medium min-w-0 flex-1 truncate flex items-center gap-2\" style={{ color: isActive ? 'var(--window-title-active, rgb(17 24 39))' : 'var(--window-title-inactive, rgb(156 163 175))' }}>\n {!exposeActive && renderIconButton()}\n <span className=\"truncate\">{exposeActive ? extractTitleText(displayTitle) : displayTitle}</span>\n </div>\n {!exposeActive && (\n <div className=\"flex items-center gap-1.5 shrink-0 ml-4\">\n {hasNav && (\n <span className=\"flex items-center gap-1 mr-1 text-[10px] text-gray-400\">\n <kbd className=\"rounded border border-gray-300 bg-gray-200 px-1.5 py-0.5 font-medium text-gray-500\">K</kbd><span>{winStr.prev}</span>\n <kbd className=\"rounded border border-gray-300 bg-gray-200 px-1.5 py-0.5 font-medium ml-1 text-gray-500\">J</kbd><span>{winStr.next}</span>\n </span>\n )}\n {allowPinOnTop && (\n <button onClick={() => setPinnedOnTop(p => !p)} title={pinnedOnTop ? winStr.unpin : winStr.pinOnTop}\n className={`text-xs px-2 py-1 rounded hover:bg-gray-200 ${pinnedOnTop ? 'text-blue-600' : 'text-gray-400 hover:text-gray-600'}`}>\n <svg className=\"h-3.5 w-3.5\" fill={pinnedOnTop ? 'currentColor' : 'none'} viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M16.5 3.75V16.5L12 14.25 7.5 16.5V3.75m9 0H18A2.25 2.25 0 0120.25 6v12A2.25 2.25 0 0118 20.25H6A2.25 2.25 0 013.75 18V6A2.25 2.25 0 016 3.75h1.5m9 0h-9\" /></svg>\n </button>\n )}\n <button onClick={() => _minimizeModal(modalId)} title={winStr.minimize} className=\"text-gray-400 hover:text-gray-600 text-xs px-2 py-1 rounded hover:bg-gray-200\">─</button>\n {!alwaysMaximized && (\n <SnapLayoutsButton\n maximized={maximized}\n onToggleMax={() => { if (maximized) { setMaximized(false); setBox(calcWindowed()); } else { reset(); } }}\n onSnap={applySnapZone}\n buttonClassName=\"text-gray-400 hover:text-gray-600 text-xs px-2 py-1 rounded hover:bg-gray-200\"\n strings={winStr}\n />\n )}\n <kbd className=\"rounded border border-gray-300 bg-gray-200 px-1.5 py-0.5 text-[10px] font-medium text-gray-400\">ESC</kbd>\n <button type=\"button\" onClick={guardedClose} className=\"rounded-md text-gray-400 hover:text-gray-600\">\n <XMarkIcon className=\"h-5 w-5\" />\n </button>\n </div>\n )}\n </div>\n )}\n\n {/* SG#00372: per-section accent stripe — a thin line between the title\n * bar and the body, painted from --window-accent-rgb (set by the\n * effect above when the consumer passes `accentRgb`). Overlapping\n * windows from different app sections become distinguishable while\n * the header itself stays theme-neutral. In flow rather than absolute\n * so it lands under whichever of the three title bars rendered\n * (compact / appStyle / full) without having to know its height.\n * pointer-events-none keeps the 3px band from swallowing a drag that\n * started on the header edge. Off by default — the user opts in via\n * the `window_accent_stripe` preference (Customization → Windows).\n * Widgets have no title bar and mobile windows are fullscreen, so\n * neither renders it. */}\n {accentRgb && accentStripeOn && !widget && !isMobile && (\n <div aria-hidden=\"true\"\n className=\"h-[3px] shrink-0 pointer-events-none\"\n style={{ backgroundColor: `rgb(var(--window-accent-rgb) / ${isActive ? 0.9 : 0.55})` }} />\n )}\n\n {/* BODY */}\n <ModalIdContext.Provider value={modalId}>\n <ModalActionsContext.Provider value={{ rightRef: actionsRef as React.RefObject<HTMLDivElement | null>, leftRef: actionsLeftRef as React.RefObject<HTMLDivElement | null>, notify: () => setHasActions(true), active: isActive, isDirty }}>\n <div\n ref={bodyRef}\n {...(widget ? { onPointerDown: startDrag, onContextMenu: (e: React.MouseEvent) => { e.preventDefault(); setCtxMenu({ x: e.clientX, y: e.clientY }); } } : {})}\n className={`flex-1 min-h-0 flex flex-col ${widget ? 'p-0 cursor-move' : appStyle ? 'p-0' : flushBody ? 'p-0' : compact ? 'p-2' : 'p-4'} ${widget ? '' : 'backdrop-blur-sm'} ${(bodyScroll === false || appStyle || flushBody) ? 'overflow-hidden' : 'overflow-y-auto overscroll-contain'} ${widget ? 'rounded-2xl select-none' : ''}`}\n style={{ ...(widget ? { touchAction: 'none' } : {}), backgroundColor: widget ? 'transparent' : (isActive ? `rgb(var(--window-content-rgb) / var(--active-content-opacity, 0.9))` : `rgb(var(--window-content-rgb) / var(--inactive-content-opacity, 0.8))`) }}>\n {/* A throwing page/entity component must not unmount the desktop —\n the boundary swaps the body for an inline crash state while the\n window chrome (close/minimize) and all other windows keep running. */}\n <WindowErrorBoundary>\n {children}\n </WindowErrorBoundary>\n </div>\n </ModalActionsContext.Provider>\n </ModalIdContext.Provider>\n\n {/* Widget right-click context menu */}\n {widget && ctxMenu && (\n <PopupMenu minWidth={160} style={{ left: ctxMenu.x, top: ctxMenu.y }} onClose={() => setCtxMenu(null)}>\n <PopupMenuItem onClick={() => { setCtxMenu(null); window.dispatchEvent(new CustomEvent('widget-open-settings', { detail: modalId })); }}>\n Settings\n </PopupMenuItem>\n <PopupMenuDivider />\n {widgetMenu && (\n <>\n {widgetMenu}\n <PopupMenuDivider />\n </>\n )}\n <PopupMenuItem onClick={() => { setCtxMenu(null); setPinnedOnTop(p => !p); }}>\n <span className=\"flex-1\">Always on Top</span>\n {pinnedOnTop && <svg className=\"h-4 w-4 text-blue-600 shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" /></svg>}\n </PopupMenuItem>\n <PopupMenuDivider />\n <PopupMenuItem onClick={() => { setCtxMenu(null); guardedClose(); }}>\n Close\n </PopupMenuItem>\n </PopupMenu>\n )}\n\n {/* FOOTER — always rendered; visible when footer prop or portal actions exist; hidden for widgets/compact */}\n <div onPointerDown={startDrag} ref={footerRef}\n className={`px-4 py-2 border-t border-gray-200 shrink-0 flex items-center justify-between text-xs select-none cursor-move${isActive ? ' backdrop-blur-sm' : ''}${widget || compact || appStyle || isMobile || !hasFooterContent ? ' hidden' : ''}`}\n style={{ touchAction: 'none', backgroundColor: isActive ? `rgb(var(--window-footer-rgb) / var(--active-header-opacity, 0.8))` : `rgb(var(--window-footer-rgb) / var(--inactive-header-opacity, 0.7))` }}>\n <div className=\"flex items-center gap-2 min-w-0\">\n {actionsLeft}\n <div ref={actionsLeftRef} data-modal-actions-left className=\"flex items-center gap-2\" />\n {footer}\n </div>\n <div className=\"flex items-center gap-2 ml-auto\">\n <div ref={actionsRef} data-modal-actions className=\"flex items-center gap-2\" />\n {actions}\n </div>\n </div>\n\n {/* RESIZE HANDLES — corners and edges (hidden in widget/mobile/exposé mode; only rendered when active to avoid z-index bleed on inactive windows) */}\n {!widget && !isMobile && !exposeActive && isActive && <>\n <div onPointerDown={e => startResizeCorner(e, 'se')} className=\"absolute bottom-0 right-0 w-3 h-3 cursor-nwse-resize z-10\" />\n <div onPointerDown={e => startResizeCorner(e, 'sw')} className=\"absolute bottom-0 left-0 w-3 h-3 cursor-nesw-resize z-10\" />\n <div onPointerDown={e => startResizeCorner(e, 'ne')} className=\"absolute top-0 right-0 w-3 h-3 cursor-nesw-resize z-10\" />\n <div onPointerDown={e => startResizeCorner(e, 'nw')} className=\"absolute top-0 left-0 w-3 h-3 cursor-nwse-resize z-10\" />\n <div onPointerDown={e => startResizeCorner(e, 'n')} className=\"absolute top-0 left-3 right-3 h-1 cursor-ns-resize\" />\n <div onPointerDown={e => startResizeCorner(e, 's')} className=\"absolute bottom-0 left-3 right-3 h-1 cursor-ns-resize\" />\n <div onPointerDown={e => startResizeCorner(e, 'e')} className=\"absolute top-3 bottom-3 right-0 w-1 cursor-ew-resize\" />\n <div onPointerDown={e => startResizeCorner(e, 'w')} className=\"absolute top-3 bottom-3 left-0 w-1 cursor-ew-resize\" />\n </>}\n {/* EXPOSÉ click capture — sits above all content so any click selects this window */}\n {exposeActive && (\n <div\n className=\"absolute inset-0\"\n style={{ zIndex: 9999, cursor: 'pointer', background: 'transparent' }}\n onMouseEnter={() => setExposeHovered(true)}\n onMouseLeave={() => setExposeHovered(false)}\n onMouseDown={(e) => {\n e.stopPropagation();\n e.preventDefault();\n // Activate the picked window first so its z-index lifts it\n // above the others while every panel animates back to its\n // real position. setExposeState(false) starts that exit\n // animation; the panel keeps `transition: transform` for\n // ~320ms via exposeExiting.\n activateModal(modalId);\n setExposeState(false);\n }}\n onClick={(e) => { e.stopPropagation(); e.preventDefault(); }}\n >\n {/* Close button — revealed while the tile is hovered, pinned to the\n * tile's top-right corner. It lives INSIDE the hover-capture layer\n * (not as a sibling) so sliding the pointer onto it doesn't fire a\n * mouseleave and flicker the hover off. Counter-scaled by\n * 1/exposeScale so it stays a real ~30px target however small the\n * tile is; honours the dirty-close confirm via `guardedClose`. */}\n {exposeHovered && (\n <button\n type=\"button\"\n data-expose-close\n aria-label={shellStrings.taskbar.closeWindow}\n title=\"Close\"\n className=\"absolute flex items-center justify-center rounded-full bg-black/55 text-white shadow-lg ring-1 ring-white/40 transition-colors hover:bg-red-500\"\n style={{\n top: 8,\n right: 8,\n width: 30,\n height: 30,\n transform: `scale(${1 / exposeScale})`,\n transformOrigin: 'top right',\n zIndex: 10000,\n }}\n onMouseDown={(e) => { e.stopPropagation(); e.preventDefault(); }}\n onClick={(e) => { e.stopPropagation(); e.preventDefault(); guardedClose(); }}\n >\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2.2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n )}\n </div>\n )}\n </div>\n {/* EXPOSÉ label — title under the thumbnail (no hover styling on the\n * text — the glow on the thumbnail itself is the affordance). */}\n {exposeActive && exposeTile && (\n <div\n className=\"fixed pointer-events-none select-none truncate text-center\"\n style={{\n left: exposeTile.x,\n top: exposeTile.y + exposeTile.h + 4,\n width: exposeTile.w,\n zIndex: exposeHovered ? 2021 : 2011,\n color: 'white',\n fontSize: 12,\n fontWeight: 500,\n textShadow: '0 1px 2px rgba(0,0,0,0.6)',\n }}\n >\n {extractTitleText(displayTitle)}\n </div>\n )}\n </div>\n );\n\n // Window context menu\n const windowMenuEl = windowMenu && (\n <PopupMenu style={{ left: windowMenu.x, top: windowMenu.y }} onClose={() => setWindowMenu(null)} minWidth={160}>\n {!widget && !compact && (<>\n <PopupMenuItem onClick={() => { _minimizeModal(modalId); setWindowMenu(null); }}>\n <svg className=\"h-4 w-4 text-gray-400\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19.5 12h-15\" /></svg>\n {winStr.minimize}\n </PopupMenuItem>\n {!alwaysMaximized && (maximized ? (\n <PopupMenuItem onClick={() => { setMaximized(false); setBox(calcWindowed()); setWindowMenu(null); }}>\n <svg className=\"h-4 w-4 text-gray-400\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 4.5v15m6-15v15M4.5 9h15M4.5 15h15\" /></svg>\n {winStr.windowed}\n </PopupMenuItem>\n ) : (\n <PopupMenuItem onClick={() => { reset(); setWindowMenu(null); }}>\n <svg className=\"h-4 w-4 text-gray-400\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15\" /></svg>\n {winStr.maximize}\n </PopupMenuItem>\n ))}\n\n </>)}\n {allowPinOnTop && (\n <PopupMenuItem onClick={() => { setPinnedOnTop(p => !p); setWindowMenu(null); }}>\n <svg className={`h-4 w-4 ${pinnedOnTop ? 'text-blue-600' : 'text-gray-400'}`} fill={pinnedOnTop ? 'currentColor' : 'none'} viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M16.5 3.75V16.5L12 14.25 7.5 16.5V3.75m9 0H18A2.25 2.25 0 0120.25 6v12A2.25 2.25 0 0118 20.25H6A2.25 2.25 0 013.75 18V6A2.25 2.25 0 016 3.75h1.5m9 0h-9\" /></svg>\n {pinnedOnTop ? winStr.unpin : winStr.pinOnTop}\n </PopupMenuItem>\n )}\n {shortcutSpec && (\n <PopupMenuItem onClick={() => { setWindowMenu(null); toggleDesktopShortcut(); }}>\n <svg className={`h-4 w-4 ${isOnDesktop ? 'text-yellow-500' : 'text-gray-400'}`} fill={isOnDesktop ? '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 {isOnDesktop ? shellStrings.taskbar.removeFromDesktop : shellStrings.taskbar.addToDesktop}\n </PopupMenuItem>\n )}\n {/* Custom menu items registered by child components */}\n {(_extraMenuItems[modalId] || []).length > 0 && (<>\n {(_extraMenuItems[modalId] || []).map((item, i) => (\n <PopupMenuItem key={i} onClick={() => { setWindowMenu(null); item.onClick(); }}>\n {item.icon}\n {item.label}\n </PopupMenuItem>\n ))}\n </>)}\n <PopupMenuDivider />\n <PopupMenuItem danger onClick={() => { setWindowMenu(null); guardedClose(); }}>\n <XMarkIcon className=\"h-4 w-4\" />\n {winStr.close}\n </PopupMenuItem>\n </PopupMenu>\n );\n\n // Always portal to body — ensures DOM persists when hidden/minimized.\n // Re-providing a null shortcut spec stops dialogs nested inside this\n // window from also offering \"Add to Desktop\" for it.\n return createPortal(\n <WindowShortcutContext.Provider value={null}>{content}{windowMenuEl}</WindowShortcutContext.Provider>,\n document.body,\n );\n}\n","/**\n * Undo/redo for one open form — the pure half.\n *\n * A form window owns a single stack covering everything in it: its fields, its\n * line-items table, a bulk import. One ⌘Z steps back the last thing the user\n * did, whatever part of the form it happened in.\n *\n * The stack holds snapshots, not diffs. A step stores the value of every\n * registered slice **as it was before the change**, so undoing restores the\n * whole form to a coherent moment rather than replaying one slice out of step\n * with the others. Forms are small — a few dozen fields and some line items —\n * so whole-form snapshots stay cheap and the logic stays honest.\n *\n * Scope is the unsaved edit. History lives with the open window and dies with\n * it; nothing here reverses a saved record.\n */\n\n/** Registered slice id → that slice's value at the time of the snapshot. */\nexport type UndoSnapshot = Record<string, unknown>;\n\nexport interface UndoStep {\n /** The form as it stood before this change. Undo restores exactly this. */\n values: UndoSnapshot;\n /** What the step was, for a button title: `\"qty\"`, `\"import of 5 lines\"`. */\n label: string;\n /**\n * Consecutive changes sharing a non-null key fold into one step — typing in\n * a field is one Undo, not one per keystroke. Null never folds.\n */\n coalesceKey: string | null;\n}\n\nexport interface UndoState {\n past: UndoStep[];\n future: UndoStep[];\n}\n\nexport type UndoAction =\n | { type: 'record'; step: UndoStep }\n | { type: 'undo'; redoStep: UndoStep }\n | { type: 'redo'; undoStep: UndoStep }\n | { type: 'clear' };\n\n/**\n * Depth. Higher than the import-only stack this replaces: typing produces a\n * step per field, so a long form fills it far faster than imports ever did.\n */\nexport const UNDO_LIMIT = 100;\n\nexport const emptyUndoState: UndoState = { past: [], future: [] };\n\nexport function undoReducer(state: UndoState, action: UndoAction): UndoState {\n switch (action.type) {\n case 'record': {\n const newest = state.past[state.past.length - 1];\n // Still the same run — the step already holds the value from before the\n // run started, which is what Undo should restore. Keep it and drop the\n // redo branch; recording again would give the value back a keystroke at\n // a time.\n if (\n action.step.coalesceKey !== null &&\n newest?.coalesceKey === action.step.coalesceKey\n ) {\n return state.future.length === 0 ? state : { ...state, future: [] };\n }\n const past = [...state.past, action.step];\n return {\n past: past.length > UNDO_LIMIT ? past.slice(past.length - UNDO_LIMIT) : past,\n future: [],\n };\n }\n case 'undo': {\n if (state.past.length === 0) return state;\n return {\n past: state.past.slice(0, -1),\n future: [action.redoStep, ...state.future],\n };\n }\n case 'redo': {\n if (state.future.length === 0) return state;\n return {\n past: [...state.past, action.undoStep],\n future: state.future.slice(1),\n };\n }\n case 'clear':\n // A save makes the current values the new baseline: there is no longer an\n // earlier state to go back to, because \"earlier\" is now on the server.\n return state.past.length === 0 && state.future.length === 0 ? state : emptyUndoState;\n }\n}\n\n/** The parts of a keydown the matcher reads. */\nexport interface UndoHotkeyEvent {\n key: string;\n metaKey: boolean;\n ctrlKey: boolean;\n shiftKey: boolean;\n altKey: boolean;\n target: { tagName?: string; isContentEditable?: boolean } | null;\n}\n\nconst TEXT_ENTRY = new Set(['INPUT', 'TEXTAREA', 'SELECT']);\n\n/**\n * Which action a keydown asks for, or null for none.\n *\n * ⌘Z / Ctrl+Z undoes, ⇧⌘Z / Ctrl+Shift+Z / Ctrl+Y redoes — except while the\n * caret is in a field. Inside an input, a textarea, or a grid cell, ⌘Z means\n * \"take back what I just typed\", and the browser does that better than we\n * could. Leaving the field ends that run and turns it into one step here, so\n * the next ⌘Z outside the field takes the whole edit back.\n */\nexport function matchUndoHotkey(e: UndoHotkeyEvent): 'undo' | 'redo' | null {\n if (!(e.metaKey || e.ctrlKey) || e.altKey) return null;\n\n const key = e.key.toLowerCase();\n const action = key === 'z' ? (e.shiftKey ? 'redo' : 'undo')\n // Ctrl+Y is the Windows redo. ⌘Y is Mac \"history\", so leave it alone.\n : key === 'y' && e.ctrlKey && !e.metaKey && !e.shiftKey ? 'redo'\n : null;\n if (!action) return null;\n\n const target = e.target;\n if (target?.isContentEditable) return null;\n if (target?.tagName && TEXT_ENTRY.has(target.tagName.toUpperCase())) return null;\n\n return action;\n}\n","import { createContext, useCallback, useContext, useEffect, useId, useMemo, useReducer, useRef, useState } from 'react';\nimport { useIsActiveWindow } from './Modal';\nimport { useShellAuth } from './ShellAuth';\nimport {\n undoReducer,\n emptyUndoState,\n matchUndoHotkey,\n type UndoSnapshot,\n type UndoHotkeyEvent,\n} from '../hooks/undoHistory';\n\ninterface Slice {\n /** The value as this slice last saw it — the \"before\" of a pending change. */\n getLast: () => unknown;\n /** Pre-arm the slice so a value it is about to receive is not recorded. */\n setLast: (v: unknown) => void;\n apply: (v: unknown) => void;\n}\n\ninterface UndoContextValue {\n register: (id: string, slice: Slice) => void;\n unregister: (id: string) => void;\n record: (label: string, coalesceKey: string | null) => void;\n undo: () => void;\n redo: () => void;\n clear: () => void;\n baseline: () => void;\n canUndo: boolean;\n canRedo: boolean;\n undoLabel: string | null;\n redoLabel: string | null;\n enabled: boolean;\n}\n\nconst UndoContext = createContext<UndoContextValue | null>(null);\n\n/**\n * Runaway detection: this many steps in a row, with no pause longer than\n * {@link RUNAWAY_QUIET_MS} between any two of them, is a render loop.\n *\n * Counting per fixed window would be the obvious thing and is the wrong one —\n * a loop slow enough to straddle the window resets the count on every pass and\n * never trips, which is precisely the machine where the hang is worst. A run\n * only resets on a genuine gap, so what trips it is a *sustained* rate rather\n * than a peak, and a slower machine takes longer to get there rather than\n * getting away with it.\n */\nconst RUNAWAY_LIMIT = 500;\nconst RUNAWAY_QUIET_MS = 250;\n\nexport interface UndoProviderProps {\n children: React.ReactNode;\n /**\n * Whether this user may edit the record. Undo is offered to everyone who\n * can — it is not gated on role or seniority — and withheld from a reader\n * only because they have nothing to take back. Defaults to true.\n */\n canEdit?: boolean;\n /**\n * Permission codes that count as \"may edit\", checked through\n * `ShellAuthProvider`. Combined with `canEdit`, so a form that already knows\n * it is read-only stays read-only whatever the codes say. Omit to rely on\n * `canEdit` alone.\n */\n perms?: string[];\n /**\n * The window this stack belongs to — the same stable key its `<Modal>` gets\n * as `windowKey`, which for a `WindowManager` window is `item.id`.\n *\n * This is what keeps ⌘Z inside the window the user is looking at. The\n * provider binds its hotkey on `window`, so every open window's provider sees\n * every keypress; the id is how one of them recognises the press as its own.\n * Without it there is no per-window identity to test and the best available\n * answer is \"is any window active\", which is true in all of them at once.\n *\n * Omit it for a provider nested inside a `<Modal>` — there the enclosing\n * modal's own context answers the question — or where there are no windows\n * at all.\n */\n windowId?: string;\n}\n\n/**\n * Undo/redo for everything in one open form.\n *\n * Wrap a form window in it, register each piece of its state with\n * {@link useUndoable}, and the whole form shares one stack: a field edit, a\n * line added, a bulk import are all steps in the same history, undone newest\n * first. Two open windows have two independent stacks, and passing\n * {@link UndoProviderProps.windowId} is what keeps them independent in\n * practice — see that prop.\n *\n * History is the unsaved edit only. It lives with the mounted provider and\n * dies with it. Both ends of the edit are the caller's to mark: `baseline()`\n * once the record has arrived, so the load is the starting point rather than\n * the first thing ⌘Z takes back, and `clear()` at a save, past which \"earlier\"\n * is on the server and not something a form can reach.\n *\n * Anyone who may edit the record gets it — it is not a privileged feature, and\n * the user most helped by an undo is the one least sure of what they just did.\n * A reader is the only one it is withheld from, and only because there is\n * nothing for them to take back. Note that `canEdit` is the caller's claim, and\n * the shell-level provider `WindowManager` mounts around every window has no\n * way to make it: it knows nothing about the record inside. That one defaults\n * to enabled, and a read-only form states the fact by nesting its own\n * `<UndoProvider canEdit={false}>`, which shadows it.\n */\nexport function UndoProvider({ children, canEdit = true, perms, windowId }: UndoProviderProps) {\n const [state, dispatch] = useReducer(undoReducer, emptyUndoState);\n const slices = useRef(new Map<string, Slice>());\n const { hasAnyPerm } = useShellAuth();\n\n // Read-only means nothing to take back. Gating here rather than on the\n // buttons keeps a stale ⌘Z from stepping a form the user may not change.\n const enabled = canEdit && (perms && perms.length > 0 ? hasAnyPerm(perms) : true);\n\n // One user action can move several slices in the same commit — a bulk import\n // fills the line items and resets the grid. Their effects all run before the\n // microtask, so the first one captures the snapshot and the rest join it,\n // making one step out of one action.\n const pending = useRef<{ values: UndoSnapshot; label: string; coalesceKey: string | null } | null>(null);\n\n // Set while a `baseline()` is settling — see it further down.\n const suspended = useRef(false);\n\n const snapshot = useCallback((): UndoSnapshot => {\n const values: UndoSnapshot = {};\n for (const [id, slice] of slices.current) values[id] = slice.getLast();\n return values;\n }, []);\n\n const register = useCallback((id: string, slice: Slice) => { slices.current.set(id, slice); }, []);\n const unregister = useCallback((id: string) => { slices.current.delete(id); }, []);\n\n // Runaway guard. A slice registered with a value that is freshly allocated\n // on every render — `useUndoable(rows.filter(r => r.on), ...)` rather than a\n // piece of state — has a new identity every time the provider re-renders,\n // and every recorded step re-renders the provider. That is a closed loop\n // running at render speed: it locks the tab rather than merely being slow,\n // and it presents as a browser hang with no clue as to which slice did it.\n // No sequence of human actions produces this many steps this fast, so the\n // rate is a sound tell. Trip once, say which slice and why, and stop\n // recording — a dead undo stack and a console error can be diagnosed.\n const runaway = useRef({ last: 0, count: 0, tripped: false });\n\n const record = useCallback((label: string, coalesceKey: string | null) => {\n if (!enabled || suspended.current || pending.current) return;\n const r = runaway.current;\n if (r.tripped) return;\n const now = Date.now();\n if (now - r.last > RUNAWAY_QUIET_MS) r.count = 0;\n r.last = now;\n if (++r.count > RUNAWAY_LIMIT) {\n r.tripped = true;\n console.error(\n `[react-os-shell] UndoProvider: \"${label}\" recorded ${RUNAWAY_LIMIT} undo steps with no ` +\n 'pause between them, which no user action can do. The value passed to useUndoable for ' +\n 'this slice is almost certainly rebuilt on every render (a .map/.filter/object literal ' +\n 'in the call) rather than held in state, so it reads as changed every time — and since ' +\n 'recording a step re-renders the form, that is a loop. Undo recording is now off for ' +\n 'this form to keep the tab responsive.',\n );\n return;\n }\n pending.current = { values: snapshot(), label, coalesceKey };\n queueMicrotask(() => {\n const step = pending.current;\n pending.current = null;\n if (step) dispatch({ type: 'record', step });\n });\n }, [enabled, snapshot]);\n\n /** Restore a snapshot, pre-arming each slice so the change is not recorded. */\n const applyValues = useCallback((values: UndoSnapshot) => {\n for (const [id, value] of Object.entries(values)) {\n const slice = slices.current.get(id);\n if (!slice) continue;\n slice.setLast(value);\n slice.apply(value);\n }\n }, []);\n\n const undo = useCallback(() => {\n const step = state.past[state.past.length - 1];\n if (!step) return;\n const redoStep = { values: snapshot(), label: step.label, coalesceKey: null };\n applyValues(step.values);\n dispatch({ type: 'undo', redoStep });\n }, [state.past, snapshot, applyValues]);\n\n const redo = useCallback(() => {\n const step = state.future[0];\n if (!step) return;\n const undoStep = { values: snapshot(), label: step.label, coalesceKey: null };\n applyValues(step.values);\n dispatch({ type: 'redo', undoStep });\n }, [state.future, snapshot, applyValues]);\n\n /**\n * Drop the history and make wherever the form is going to be the starting\n * point.\n *\n * The awkward moment is a form filled from an async fetch. The record\n * arriving is a state change like any other, so every slice records it, and\n * the user's first ⌘Z hands back the empty form they were looking at before\n * it loaded. Clearing after the fact does not fix that on its own, because\n * the values assigned alongside the call have not landed yet — they arrive in\n * the commit this schedules, and record on the way in.\n *\n * So it suspends recording rather than only clearing: the slices still take\n * the loaded values as their own starting point (`useUndoable` moves `last`\n * whether or not a step came of it), they just do not call it an edit. The\n * effect below lifts the suspension once that commit's slices have run —\n * child effects before parent — which is one commit, exactly, and no timer.\n *\n * The one thing it asks of a caller is to assign in the same effect:\n *\n * useEffect(() => {\n * if (!data) return;\n * setName(data.name); setQty(data.qty);\n * baseline();\n * }, [data]);\n *\n * React batches those into one commit, so the order within the effect does\n * not matter. Assigning in a *different* effect from the `baseline()` call\n * does, and would leave the load recorded.\n */\n const [baselineToken, setBaselineToken] = useState(0);\n\n const baseline = useCallback(() => {\n suspended.current = true;\n pending.current = null;\n setBaselineToken(t => t + 1);\n dispatch({ type: 'clear' });\n }, []);\n\n useEffect(() => {\n if (!suspended.current) return;\n suspended.current = false;\n pending.current = null;\n dispatch({ type: 'clear' });\n }, [baselineToken]);\n\n // Same operation, named for the other end of the edit. Kept distinct at the\n // call site because \"clear on save\" and \"baseline on load\" are different\n // facts about the form, and a reader of either line should not have to work\n // out which one was meant.\n const clear = baseline;\n\n const canUndo = enabled && state.past.length > 0;\n const canRedo = enabled && state.future.length > 0;\n\n // Bound here rather than on the buttons, so the keys work in a form that\n // shows no controls at all. The listener is on `window`, so every open\n // window's provider sees every press — `windowId` is what makes exactly one\n // of them answer.\n const isActive = useIsActiveWindow(windowId);\n const keyed = useRef({ undo, redo, canUndo, canRedo });\n keyed.current = { undo, redo, canUndo, canRedo };\n useEffect(() => {\n if (!isActive || !enabled) return;\n const handler = (e: KeyboardEvent) => {\n const action = matchUndoHotkey(e as unknown as UndoHotkeyEvent);\n if (!action) return;\n const k = keyed.current;\n // Nothing to step to — leave the key to whatever else wants it rather\n // than swallowing it into a no-op.\n if (action === 'undo' ? !k.canUndo : !k.canRedo) return;\n e.preventDefault();\n if (action === 'undo') k.undo(); else k.redo();\n };\n window.addEventListener('keydown', handler);\n return () => window.removeEventListener('keydown', handler);\n }, [isActive, enabled]);\n\n const value = useMemo<UndoContextValue>(() => ({\n register, unregister, record, undo, redo, clear, baseline, canUndo, canRedo, enabled,\n undoLabel: canUndo ? state.past[state.past.length - 1].label : null,\n redoLabel: canRedo ? state.future[0].label : null,\n }), [register, unregister, record, undo, redo, clear, baseline, canUndo, canRedo, enabled, state.past, state.future]);\n\n return <UndoContext.Provider value={value}>{children}</UndoContext.Provider>;\n}\n\nexport interface UndoControlsApi {\n undo: () => void;\n redo: () => void;\n canUndo: boolean;\n canRedo: boolean;\n /** What Undo/Redo would act on, for a button title. Null when unavailable. */\n undoLabel: string | null;\n redoLabel: string | null;\n /** End the history — call after a successful save. */\n clear: () => void;\n /**\n * Make the form as it stands the starting point, discarding the history.\n *\n * Call it once the record has arrived from the server. State filled from a\n * fetch is a change like any other as far as the slices are concerned, so\n * without this the load itself is the oldest step and the user's first ⌘Z\n * empties the form they were just given:\n *\n * const { data } = useQuery(...);\n * const { baseline } = useUndo();\n * useEffect(() => { if (data) baseline(); }, [data, baseline]);\n *\n * Worth calling on every arrival, not just the first: a window kept open\n * across a refetch, or one whose entity changes underneath it, wants the\n * same treatment, and the call is idempotent for a form nobody has touched.\n */\n baseline: () => void;\n /** False when the user may not edit this record, so custom UI can hide\n * itself the way `UndoControls` does. */\n enabled: boolean;\n}\n\n/**\n * The enclosing form's undo stack, for custom UI or to `clear()` on save.\n * Everything is inert outside an {@link UndoProvider}.\n */\nexport function useUndo(): UndoControlsApi {\n const ctx = useContext(UndoContext);\n const noop = useCallback(() => {}, []);\n return {\n undo: ctx?.undo ?? noop,\n redo: ctx?.redo ?? noop,\n clear: ctx?.clear ?? noop,\n baseline: ctx?.baseline ?? noop,\n canUndo: ctx?.canUndo ?? false,\n canRedo: ctx?.canRedo ?? false,\n undoLabel: ctx?.undoLabel ?? null,\n redoLabel: ctx?.redoLabel ?? null,\n enabled: ctx?.enabled ?? false,\n };\n}\n\nexport interface UndoableOptions {\n /** Names the step in a button title: `\"qty\"`, `\"line items\"`. */\n label: string;\n /**\n * Consecutive changes sharing a key fold into one step — pass the field name\n * so a run of typing is one Undo rather than one per keystroke. Omit for a\n * change that is already whole, like a bulk import or a deleted row.\n */\n coalesceKey?: string | null;\n}\n\n/**\n * Put one piece of the form's state under the window's undo stack.\n *\n * `value` is watched; when it changes, the form as it stood beforehand becomes\n * a step. `apply` puts a value back — the same setter the form already uses.\n *\n * const [items, setItems] = useState<Line[]>([]);\n * useUndoable(items, setItems, { label: 'line items' });\n *\n * Registering more than one slice is the point: a step snapshots all of them\n * together, so undoing restores a coherent form rather than one slice out of\n * step with the rest.\n *\n * `value` must be the state itself, not something derived from it on the way\n * in. A change is detected by identity, so `useUndoable(rows.filter(r => r.on),\n * ...)` hands over a new array on every render and reads as a change every\n * time — and since recording a step re-renders the provider, that closes a\n * loop at render speed. The provider trips a runaway guard and says so rather\n * than letting the tab hang, but the fix is at the call site: register the\n * state, and derive from it afterwards.\n */\nexport function useUndoable<T>(value: T, apply: (next: T) => void, opts: UndoableOptions) {\n const ctx = useContext(UndoContext);\n const id = useId();\n const last = useRef(value);\n const applyRef = useRef(apply);\n applyRef.current = apply;\n\n useEffect(() => {\n if (!ctx) return;\n ctx.register(id, {\n getLast: () => last.current,\n setLast: v => { last.current = v as T; },\n apply: v => applyRef.current(v as T),\n });\n return () => ctx.unregister(id);\n }, [ctx, id]);\n\n const { label, coalesceKey = null } = opts;\n // `value` alone, deliberately. The context object is a new identity after\n // every recorded step — it carries `canUndo` — so listing it here would run\n // this effect on each one; it is read through a ref instead. `label` and\n // `coalesceKey` are what a change would be *called*, not a change in\n // themselves, and neither should provoke a step.\n const ctxRef = useRef(ctx);\n ctxRef.current = ctx;\n const optsRef = useRef({ label, coalesceKey });\n optsRef.current = { label, coalesceKey };\n useEffect(() => {\n const c = ctxRef.current;\n if (!c) return;\n if (Object.is(value, last.current)) return;\n // Record before moving `last`: the snapshot the provider takes reads this\n // slice through `getLast`, and must see the value from before the change.\n c.record(optsRef.current.label, optsRef.current.coalesceKey);\n last.current = value;\n }, [value]);\n}\n\n/**\n * `useState`, with the value in the window's undo stack.\n *\n * Written to be a rename rather than an extra line, because the forms this is\n * for hold their state in dozens of separate `useState` calls — one of them has\n * forty-three. Adopting a form is then a per-line edit:\n *\n * const [supplier, setSupplier] = useState('');\n * const [supplier, setSupplier] = useUndoableState('', { label: 'supplier' });\n *\n * Which also makes the choice legible: state left as plain `useState` is state\n * deliberately kept out of the history. Keep it that way for anything that is\n * not the user's input — a search box, fetched data, validation output, an\n * initialisation guard. Undoing those puts stale results back on screen, and a\n * reverted guard can re-fire the effect it exists to suppress.\n *\n * Pass `coalesceKey` for anything typed into, so a run of keystrokes is one\n * Undo; the field's own name is the obvious key.\n */\nexport function useUndoableState<T>(\n initial: T | (() => T),\n opts: UndoableOptions,\n): [T, React.Dispatch<React.SetStateAction<T>>] {\n const [value, setValue] = useState(initial);\n // Restore through the updater form, so a T that is itself a function is set\n // rather than called.\n useUndoable(value, next => setValue(() => next), opts);\n return [value, setValue];\n}\n"]}
|