react-dockable-desktop 1.0.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/README.md +327 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +427 -0
- package/dist/index.d.ts +427 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +1766 -0
- package/package.json +70 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/WindowManager.tsx","../src/components/WindowManagerContext.tsx","../src/components/PanelRegistry.ts","../src/components/predefinedMessages.ts","../src/components/FormContainerContext.ts","../src/components/PanelProviderContext.tsx","../src/components/ModalStackRenderer.tsx","../src/components/DirtyWarningOverlay.tsx","../src/components/SidePanelRenderer.tsx","../src/forms/ConfirmationForm.tsx","../src/components/Sidebar.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useWindowManagerState, useWindowManagerActions, useFormatMessage, formatLabel, usePredefinedMessages, useStyleClasses } from './WindowManagerContext';\nimport type { LayoutNode, LayoutLeafNode } from './WindowManagerContext';\nimport { PanelRegistry } from './PanelRegistry';\nimport { JsonContextMenu, type JsonContextMenuRef } from 'replace-react-contexify';\nimport 'replace-react-contexify/styles.css';\nimport { FormContainerProvider } from './FormContainerContext';\nimport type { FormContainerContract } from './FormContainerContext';\n\n// DOM Element Cache for preserving contexts (WebGL map, text area etc.)\nconst domCache = new Map<string, HTMLDivElement>();\nconst hiddenContainerId = 'preserved-dom-container';\n\nconst DefaultGridIcon = (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" style={{ display: 'block' }}>\n <rect x=\"3\" y=\"3\" width=\"7\" height=\"9\" rx=\"1\" />\n <rect x=\"14\" y=\"3\" width=\"7\" height=\"5\" rx=\"1\" />\n <rect x=\"14\" y=\"12\" width=\"7\" height=\"9\" rx=\"1\" />\n <rect x=\"3\" y=\"16\" width=\"7\" height=\"5\" rx=\"1\" />\n </svg>\n);\n\nconst getOrCreateDomCacheElement = (id: string): HTMLDivElement => {\n let el = domCache.get(id);\n if (!el) {\n el = document.createElement('div');\n el.style.width = '100%';\n el.style.height = '100%';\n domCache.set(id, el);\n }\n return el;\n};\n\n\n// ==========================================\n// 3. Persistent DOM Container Host & Slot\n// ==========================================\n\nconst renderPanelContent = (id: string, componentKey: string) => {\n const registryEntry = PanelRegistry.get(componentKey);\n if (!registryEntry) {\n return (\n <div className=\"w-100 h-100 d-flex flex-column align-items-center justify-content-center bg-transparent text-danger font-monospace p-3 text-center\" style={{ border: '2px dashed var(--bs-danger, #dc3545)' }}>\n <h6 className=\"fw-bold mb-1\">⚠️ Component Unregistered</h6>\n <span className=\"small text-muted\">Key: {componentKey}</span>\n </div>\n );\n }\n const Component = registryEntry.Component;\n return <Component panelId={id} />;\n};\n\nconst activePanelDimensions = new Map<string, { width: number; height: number }>();\n\nconst panelLifecycleRegistry = new Map<string, {\n onClose: Set<() => void>;\n onMinimize: Set<() => void>;\n onRestore: Set<() => void>;\n onResize: Set<(w: number, h: number) => void>;\n}>();\n\nconst getOrCreateLifecycleRegistry = (panelId: string) => {\n let entry = panelLifecycleRegistry.get(panelId);\n if (!entry) {\n entry = {\n onClose: new Set(),\n onMinimize: new Set(),\n onRestore: new Set(),\n onResize: new Set(),\n };\n panelLifecycleRegistry.set(panelId, entry);\n }\n return entry;\n};\n\nconst PreservedDOMWrapper: React.FC<{ panelId: string }> = ({ panelId }) => {\n const hostRef = useRef<HTMLDivElement | null>(null);\n\n useEffect(() => {\n const host = hostRef.current;\n if (!host) return;\n\n const cachedEl = getOrCreateDomCacheElement(panelId);\n host.appendChild(cachedEl);\n\n const resizeObserver = new ResizeObserver((entries) => {\n for (let entry of entries) {\n const { width, height } = entry.contentRect;\n if (width > 0 && height > 0) {\n activePanelDimensions.set(panelId, { width, height });\n const lifecycle = panelLifecycleRegistry.get(panelId);\n if (lifecycle) {\n lifecycle.onResize.forEach(h => h(width, height));\n }\n }\n }\n });\n resizeObserver.observe(host);\n\n return () => {\n resizeObserver.disconnect();\n let hiddenContainer = document.getElementById(hiddenContainerId);\n if (!hiddenContainer) {\n hiddenContainer = document.createElement('div');\n hiddenContainer.id = hiddenContainerId;\n hiddenContainer.style.display = 'none';\n document.body.appendChild(hiddenContainer);\n }\n hiddenContainer.appendChild(cachedEl);\n };\n }, [panelId]);\n\n return <div ref={hostRef} className=\"w-100 h-100\" />;\n};\n\nconst PreviewDOMWrapper: React.FC<{ panelId: string }> = ({ panelId }) => {\n const state = useWindowManagerState();\n const hostRef = useRef<HTMLDivElement | null>(null);\n \n const panel = state.panels[panelId];\n const regEntry = panel ? PanelRegistry.get(panel.component) : null;\n const disableLivePreview = regEntry?.defaultOptions?.disableLivePreview || false;\n\n const [dimensions, setDimensions] = useState({ width: 800, height: 500, scale: 0.25 });\n\n useEffect(() => {\n if (disableLivePreview) return;\n\n const host = hostRef.current;\n if (!host) return;\n\n const cachedEl = domCache.get(panelId);\n if (!cachedEl) return;\n\n // 1. Read the panel's active dimensions before minimization\n const lastSize = activePanelDimensions.get(panelId) || { width: 800, height: 500 };\n const origW = lastSize.width;\n const origH = lastSize.height;\n\n // 2. Calculate scale factor to fit within a 220px x 140px thumbnail container\n const maxW = 220;\n const maxH = 140;\n const scale = Math.min(maxW / origW, maxH / origH);\n\n setDimensions({ width: origW, height: origH, scale });\n\n host.appendChild(cachedEl);\n\n return () => {\n let hiddenContainer = document.getElementById(hiddenContainerId);\n if (!hiddenContainer) {\n hiddenContainer = document.createElement('div');\n hiddenContainer.id = hiddenContainerId;\n hiddenContainer.style.display = 'none';\n document.body.appendChild(hiddenContainer);\n }\n hiddenContainer.appendChild(cachedEl);\n };\n }, [panelId, disableLivePreview]);\n\n if (disableLivePreview) {\n const lastSize = activePanelDimensions.get(panelId) || { width: 800, height: 500 };\n const maxW = 220;\n const maxH = 140;\n const scale = Math.min(maxW / lastSize.width, maxH / lastSize.height);\n const displayW = lastSize.width * scale;\n const displayH = lastSize.height * scale;\n\n const icon = regEntry?.defaultOptions?.icon || <span>🔳</span>;\n\n return (\n <div \n className=\"taskbar-item-preview-frame d-flex flex-column align-items-center justify-content-center text-muted\"\n style={{\n width: `${displayW}px`,\n height: `${displayH}px`,\n background: 'linear-gradient(135deg, rgba(30, 41, 59, 0.9) 0%, rgba(15, 23, 42, 0.95) 100%)',\n border: '1px dashed var(--taskbar-item-border, rgba(255, 255, 255, 0.15))'\n }}\n >\n <div className=\"taskbar-preview-placeholder-icon mb-1.5\" style={{ transform: 'scale(1.2)', filter: 'drop-shadow(0 0 8px rgba(56, 189, 248, 0.4))' }}>\n {icon}\n </div>\n <div style={{ fontSize: '9px', fontWeight: 500, letterSpacing: '0.5px', opacity: 0.7, textTransform: 'uppercase' }}>\n Active Session\n </div>\n </div>\n );\n }\n\n return (\n <div \n className=\"taskbar-item-preview-frame\"\n style={{\n width: `${dimensions.width * dimensions.scale}px`,\n height: `${dimensions.height * dimensions.scale}px`,\n }}\n >\n <div \n ref={hostRef} \n className=\"taskbar-item-preview-host\"\n style={{\n width: `${dimensions.width}px`,\n height: `${dimensions.height}px`,\n transform: `scale(${dimensions.scale})`,\n transformOrigin: 'top left',\n position: 'absolute',\n top: 0,\n left: 0\n }}\n />\n </div>\n );\n};\n\nconst FormContainerProviderWrapper: React.FC<{ panelId: string; children: React.ReactNode }> = ({ panelId, children }) => {\n const state = useWindowManagerState();\n const { requestClosePanel, setPanelDirty, registerCloseGuard, unregisterCloseGuard, updatePanelTitle } = useWindowManagerActions();\n \n const isMin = state.minimized.some(m => m.id === panelId);\n const prevMinRef = useRef(isMin);\n\n useEffect(() => {\n const entry = panelLifecycleRegistry.get(panelId);\n if (!entry) return;\n\n if (isMin && !prevMinRef.current) {\n entry.onMinimize.forEach(h => h());\n } else if (!isMin && prevMinRef.current) {\n entry.onRestore.forEach(h => h());\n }\n prevMinRef.current = isMin;\n }, [isMin, panelId]);\n\n useEffect(() => {\n return () => {\n const entry = panelLifecycleRegistry.get(panelId);\n if (entry) {\n entry.onClose.forEach(h => h());\n panelLifecycleRegistry.delete(panelId);\n }\n };\n }, [panelId]);\n\n const contract = React.useMemo<FormContainerContract>(() => ({\n requestClose: (options) => requestClosePanel(panelId, options),\n setDirty: (dirty) => setPanelDirty(panelId, dirty),\n onCloseRequested: (handler) => {\n registerCloseGuard(panelId, handler);\n return () => unregisterCloseGuard(panelId);\n },\n setTitle: (title) => updatePanelTitle(panelId, title),\n instanceId: panelId,\n onClose: (handler) => {\n const reg = getOrCreateLifecycleRegistry(panelId);\n reg.onClose.add(handler);\n return () => reg.onClose.delete(handler);\n },\n onMinimize: (handler) => {\n const reg = getOrCreateLifecycleRegistry(panelId);\n reg.onMinimize.add(handler);\n return () => reg.onMinimize.delete(handler);\n },\n onRestore: (handler) => {\n const reg = getOrCreateLifecycleRegistry(panelId);\n reg.onRestore.add(handler);\n return () => reg.onRestore.delete(handler);\n },\n onResize: (handler) => {\n const reg = getOrCreateLifecycleRegistry(panelId);\n reg.onResize.add(handler);\n return () => reg.onResize.delete(handler);\n }\n }), [panelId, requestClosePanel, setPanelDirty, registerCloseGuard, unregisterCloseGuard, updatePanelTitle]);\n\n return (\n <FormContainerProvider value={contract}>\n {children}\n </FormContainerProvider>\n );\n};\n\n\n\n\n// ==========================================\n// 4. Panel Tab Headers & Split Layout Component\n// ==========================================\n\ninterface WorkspaceGridProps {\n node: LayoutNode;\n path: number[];\n onTabRightClick: (id: string, e: React.MouseEvent) => void;\n activeDropZone: { leafId: string; position: 'left' | 'right' | 'top' | 'bottom' | 'center' } | null;\n onHoverDropZone: (leafId: string, position: 'left' | 'right' | 'top' | 'bottom' | 'center' | null) => void;\n onTabDragStart: (id: string, e: React.MouseEvent) => void;\n hoveredTab: { leafId: string; panelId: string; index: number; side: 'left' | 'right' } | null;\n onTabHover: (leafId: string, panelId: string, index: number, side: 'left' | 'right' | null) => void;\n defaultPanelIcon?: React.ReactNode;\n}\n\nconst WorkspaceGrid: React.FC<WorkspaceGridProps> = ({ node, path, onTabRightClick, activeDropZone, onHoverDropZone, onTabDragStart, hoveredTab, onTabHover, defaultPanelIcon }) => {\n const { updateSplitSizes } = useWindowManagerActions();\n\n if (node.type === 'leaf') {\n return <LeafGroup leaf={node} onTabRightClick={onTabRightClick} activeDropZone={activeDropZone} onHoverDropZone={onHoverDropZone} onTabDragStart={onTabDragStart} hoveredTab={hoveredTab} onTabHover={onTabHover} defaultPanelIcon={defaultPanelIcon} />;\n }\n\n const isRow = node.orientation === 'horizontal';\n\n const handleResizerMouseDown = (idx: number, e: React.MouseEvent) => {\n e.preventDefault();\n const startOffset = isRow ? e.clientX : e.clientY;\n const startSizes = [...node.sizes];\n \n // Capture the parent element and its size synchronously on mousedown\n const parentEl = e.currentTarget.parentElement;\n const parentSize = parentEl \n ? (isRow ? parentEl.clientWidth : parentEl.clientHeight) \n : (isRow ? 1000 : 800);\n\n const handleMouseMove = (moveEvent: MouseEvent) => {\n const currentOffset = isRow ? moveEvent.clientX : moveEvent.clientY;\n const delta = currentOffset - startOffset;\n\n const deltaPercentage = delta / parentSize;\n \n const newSizes = [...startSizes];\n newSizes[idx] += deltaPercentage;\n newSizes[idx + 1] -= deltaPercentage;\n\n // Restrict range bounds\n if (newSizes[idx] > 0.1 && newSizes[idx + 1] > 0.1) {\n updateSplitSizes(path, newSizes);\n }\n };\n\n const handleMouseUp = () => {\n window.removeEventListener('mousemove', handleMouseMove);\n window.removeEventListener('mouseup', handleMouseUp);\n };\n\n window.addEventListener('mousemove', handleMouseMove);\n window.addEventListener('mouseup', handleMouseUp);\n };\n\n return (\n <div \n className={`d-flex w-100 h-100 ${isRow ? 'flex-row' : 'flex-column'}`}\n style={{ overflow: 'hidden', position: 'relative' }}\n >\n {node.children.map((child, idx) => {\n const size = node.sizes[idx] * 100;\n return (\n <React.Fragment key={idx}>\n <div style={{ flexGrow: node.sizes[idx], flexBasis: `${size}%`, overflow: 'hidden', position: 'relative' }}>\n <WorkspaceGrid node={child} path={[...path, idx]} onTabRightClick={onTabRightClick} activeDropZone={activeDropZone} onHoverDropZone={onHoverDropZone} onTabDragStart={onTabDragStart} hoveredTab={hoveredTab} onTabHover={onTabHover} defaultPanelIcon={defaultPanelIcon} />\n </div>\n {idx < node.children.length - 1 && (\n <div \n onMouseDown={(e) => handleResizerMouseDown(idx, e)}\n style={{\n cursor: isRow ? 'col-resize' : 'row-resize',\n width: isRow ? '6px' : '100%',\n height: isRow ? '100%' : '6px',\n backgroundColor: 'var(--resizer-bg)',\n zIndex: 20,\n transition: 'background-color 0.2s',\n }}\n className=\"resizer-bar hover-highlight\"\n />\n )}\n </React.Fragment>\n );\n })}\n </div>\n );\n};\n\ninterface LeafGroupProps {\n leaf: LayoutLeafNode;\n onTabRightClick: (id: string, e: React.MouseEvent) => void;\n activeDropZone: { leafId: string; position: 'left' | 'right' | 'top' | 'bottom' | 'center' } | null;\n onHoverDropZone: (leafId: string, position: 'left' | 'right' | 'top' | 'bottom' | 'center' | null) => void;\n onTabDragStart: (id: string, e: React.MouseEvent) => void;\n hoveredTab: { leafId: string; panelId: string; index: number; side: 'left' | 'right' } | null;\n onTabHover: (leafId: string, panelId: string, index: number, side: 'left' | 'right' | null) => void;\n defaultPanelIcon?: React.ReactNode;\n}\n\nconst LeafGroup: React.FC<LeafGroupProps> = ({ leaf, onTabRightClick, activeDropZone, onHoverDropZone, onTabDragStart, hoveredTab, onTabHover, defaultPanelIcon }) => {\n const state = useWindowManagerState();\n const { requestClosePanel, openPanel, closeLeafGroup } = useWindowManagerActions();\n const formatMessage = useFormatMessage();\n const messages = usePredefinedMessages();\n const { windowClass, windowBodyClass } = useStyleClasses();\n\n const selectTab = (id: string) => {\n openPanel(id, state.panels[id].component);\n };\n\n return (\n <div className={`workspace-panel w-100 h-100 d-flex flex-column ${windowClass ?? ''}`} style={{ overflow: 'hidden', position: 'relative' }}>\n {/* Tab Headers */}\n <div className=\"workspace-tab-bar d-flex flex-row justify-content-between align-items-center\" style={{ minHeight: '38px' }}>\n <div \n className=\"d-flex flex-row overflow-x-auto flex-grow-1 tab-headers-container\" \n style={{ scrollbarWidth: 'none' }}\n onMouseMove={(e) => {\n if (state.draggedPanelId && e.target === e.currentTarget) {\n onTabHover(leaf.id, 'EMPTY', leaf.panels.length, 'right');\n }\n }}\n onMouseLeave={(e) => {\n if (state.draggedPanelId && e.target === e.currentTarget) {\n onTabHover(leaf.id, '', -1, null);\n }\n }}\n >\n {leaf.panels.map((id, idx) => {\n const panel = state.panels[id];\n if (!panel) return null;\n const isActive = leaf.activePanelId === id;\n \n const registryEntry = PanelRegistry.get(panel.component);\n const options = registryEntry?.defaultOptions;\n\n const isHovered = hoveredTab && hoveredTab.leafId === leaf.id && hoveredTab.panelId === id;\n const isLast = idx === leaf.panels.length - 1;\n const isHoveredEmpty = hoveredTab && hoveredTab.leafId === leaf.id && hoveredTab.panelId === 'EMPTY' && isLast;\n const sideClass = isHovered \n ? (hoveredTab.side === 'left' ? 'drag-hover-left' : 'drag-hover-right') \n : (isHoveredEmpty ? 'drag-hover-right' : '');\n\n return (\n <div \n key={id}\n onClick={() => selectTab(id)}\n onMouseDown={(e) => {\n if (options?.canDrag !== false) {\n onTabDragStart(id, e);\n }\n }}\n onContextMenu={(e) => onTabRightClick(id, e)}\n onMouseMove={(e) => {\n if (state.draggedPanelId) {\n const rect = e.currentTarget.getBoundingClientRect();\n const relativeX = e.clientX - rect.left;\n const side = relativeX < rect.width / 2 ? 'left' : 'right';\n onTabHover(leaf.id, id, idx, side);\n }\n }}\n onMouseLeave={() => {\n if (state.draggedPanelId) {\n onTabHover(leaf.id, '', -1, null);\n }\n }}\n className={`workspace-tab ${isActive ? 'active workspace-tab-active' : 'workspace-tab-inactive'} ${sideClass}`}\n style={{ cursor: options?.canDrag === false ? 'default' : 'pointer' }}\n >\n <span className=\"text-truncate d-flex align-items-center\" style={{ maxWidth: '120px' }}>\n <span className=\"workspace-tab-icon\">{options?.icon || defaultPanelIcon || DefaultGridIcon}</span>\n <span>\n {formatLabel(panel.title, formatMessage)}\n {panel.dirty ? ' *' : ''}\n </span>\n </span>\n {options?.canClose !== false && (\n <span \n onClick={(e) => {\n e.stopPropagation();\n requestClosePanel(id);\n }}\n title={formatLabel(messages.closeTab, formatMessage)}\n className=\"close-tab-x ms-auto d-flex align-items-center justify-content-center\"\n style={{ width: '18px', height: '18px' }}\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\">\n <path d=\"M18 6L6 18M6 6l12 12\"/>\n </svg>\n </span>\n )}\n </div>\n );\n })}\n </div>\n \n {/* Empty group close button — only visible when keepOnEmpty keeps the group alive */}\n {leaf.panels.length === 0 && leaf.keepOnEmpty && leaf.canClose !== false && (\n <span\n onClick={() => closeLeafGroup(leaf.id)}\n className=\"close-tab-x d-flex align-items-center justify-content-center me-2 header-close-empty-group\"\n style={{ width: '18px', height: '18px', cursor: 'pointer' }}\n title={formatLabel(messages.closeEmptyGroup, formatMessage)}\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\">\n <path d=\"M18 6L6 18M6 6l12 12\"/>\n </svg>\n </span>\n )}\n </div>\n\n {/* Tab Content Display Area */}\n <div className={`flex-grow-1 w-100 h-100 bg-transparent ${windowBodyClass ?? ''}`} style={{ position: 'relative', overflow: 'hidden' }}>\n {leaf.activePanelId && state.panels[leaf.activePanelId] ? (\n <PreservedDOMWrapper key={leaf.activePanelId} panelId={leaf.activePanelId} />\n ) : (\n <div className=\"w-100 h-100 d-flex align-items-center justify-content-center font-monospace text-muted small empty-leaf-placeholder\">\n <span>Empty Workspace Section</span>\n </div>\n )}\n\n {/* Drag overlay targets cross */}\n {state.draggedPanelId !== null && (\n <div className=\"dock-drop-zone-overlay\">\n <div className=\"dock-target-cross\">\n {/* Top target */}\n <div \n onMouseEnter={() => onHoverDropZone(leaf.id, 'top')}\n onMouseLeave={() => onHoverDropZone(leaf.id, null)}\n className=\"dock-target-box dock-target-top\"\n >\n ▲\n </div>\n {/* Bottom target */}\n <div \n onMouseEnter={() => onHoverDropZone(leaf.id, 'bottom')}\n onMouseLeave={() => onHoverDropZone(leaf.id, null)}\n className=\"dock-target-box dock-target-bottom\"\n >\n ▼\n </div>\n {/* Left target */}\n <div \n onMouseEnter={() => onHoverDropZone(leaf.id, 'left')}\n onMouseLeave={() => onHoverDropZone(leaf.id, null)}\n className=\"dock-target-box dock-target-left\"\n >\n ◀\n </div>\n {/* Right target */}\n <div \n onMouseEnter={() => onHoverDropZone(leaf.id, 'right')}\n onMouseLeave={() => onHoverDropZone(leaf.id, null)}\n className=\"dock-target-box dock-target-right\"\n >\n ▶\n </div>\n {/* Center target */}\n <div \n onMouseEnter={() => onHoverDropZone(leaf.id, 'center')}\n onMouseLeave={() => onHoverDropZone(leaf.id, null)}\n className=\"dock-target-box dock-target-center\"\n >\n ▣\n </div>\n </div>\n </div>\n )}\n\n {/* Visual preview highlight overlay */}\n {state.draggedPanelId !== null && activeDropZone !== null && activeDropZone.leafId === leaf.id && (\n <div \n className=\"dock-preview-highlight\"\n style={{\n left: activeDropZone.position === 'right' ? '50%' : '0',\n top: activeDropZone.position === 'bottom' ? '50%' : '0',\n width: (activeDropZone.position === 'left' || activeDropZone.position === 'right') ? '50%' : '100%',\n height: (activeDropZone.position === 'top' || activeDropZone.position === 'bottom') ? '50%' : '100%',\n }}\n />\n )}\n </div>\n </div>\n );\n};\n\n\n// ==========================================\n// 5. WindowManager (Main Render Component)\n// ==========================================\n\nexport interface WindowManagerProps {\n skin?: string;\n defaultPanelIcon?: React.ReactNode;\n}\n\nexport const WindowManager: React.FC<WindowManagerProps> = ({ skin = 'vscode', defaultPanelIcon }) => {\n const state = useWindowManagerState();\n const { restorePanel, minimizePanel, requestClosePanel, resolvePendingClose, maximizePanel, updateFloatingPosition, bringToFront, floatPanel, setDraggedPanelId, dockPanelToGroup, movePanelOrder, dockPanelToWorkspaceEdge } = useWindowManagerActions();\n const formatMessage = useFormatMessage();\n const messages = usePredefinedMessages();\n const { windowClass, windowBodyClass } = useStyleClasses();\n const [instantiatedPanels, setInstantiatedPanels] = useState<string[]>([]);\n const taskbarRef = useRef<HTMLDivElement | null>(null);\n const contextMenuRef = useRef<JsonContextMenuRef>(null);\n\n const [hoveredMinimized, setHoveredMinimized] = useState<{ id: string; rect: DOMRect; title: string | any; component: string } | null>(null);\n const minimizedTooltipTimeoutRef = useRef<any>(null);\n const [isContextMenuOpen, setIsContextMenuOpen] = useState(false);\n\n useEffect(() => {\n return () => {\n if (minimizedTooltipTimeoutRef.current) {\n clearTimeout(minimizedTooltipTimeoutRef.current);\n }\n };\n }, []);\n\n const [activeDropZone, setActiveDropZone] = useState<{ leafId: string; position: 'left' | 'right' | 'top' | 'bottom' | 'center' } | null>(null);\n const activeDropZoneRef = useRef<{ leafId: string; position: 'left' | 'right' | 'top' | 'bottom' | 'center' } | null>(null);\n const [dragPos, setDragPos] = useState<{ x: number; y: number }>({ x: 0, y: 0 });\n\n const [activeEdgeDrop, setActiveEdgeDropState] = useState<'left' | 'right' | 'top' | 'bottom' | null>(null);\n const activeEdgeDropRef = useRef<'left' | 'right' | 'top' | 'bottom' | null>(null);\n const setActiveEdgeDrop = (val: 'left' | 'right' | 'top' | 'bottom' | null) => {\n setActiveEdgeDropState(val);\n activeEdgeDropRef.current = val;\n };\n\n const [hoveredTab, setHoveredTab] = useState<{ leafId: string; panelId: string; index: number; side: 'left' | 'right' } | null>(null);\n const hoveredTabRef = useRef<{ leafId: string; panelId: string; index: number; side: 'left' | 'right' } | null>(null);\n\n const handleTabHover = (leafId: string, panelId: string, index: number, side: 'left' | 'right' | null) => {\n const val = side ? { leafId, panelId, index, side } : null;\n setHoveredTab(val);\n hoveredTabRef.current = val;\n };\n\n const handleHoverDropZone = (leafId: string, position: 'left' | 'right' | 'top' | 'bottom' | 'center' | null) => {\n const val = position ? { leafId, position } : null;\n setActiveDropZone(val);\n activeDropZoneRef.current = val;\n };\n\n const handleTabDragStart = (id: string, e: React.MouseEvent) => {\n // Only handle left click drags\n if (e.button !== 0) return;\n \n const startX = e.clientX;\n const startY = e.clientY;\n let dragStarted = false;\n\n const handleMouseMove = (moveEvent: MouseEvent) => {\n const dx = moveEvent.clientX - startX;\n const dy = moveEvent.clientY - startY;\n\n // Threshold trigger (5px)\n if (!dragStarted && (Math.abs(dx) > 5 || Math.abs(dy) > 5)) {\n dragStarted = true;\n setDraggedPanelId(id);\n }\n\n if (dragStarted) {\n setDragPos({ x: moveEvent.clientX, y: moveEvent.clientY });\n }\n };\n\n const handleMouseUp = (moveEvent: MouseEvent) => {\n window.removeEventListener('mousemove', handleMouseMove);\n window.removeEventListener('mouseup', handleMouseUpWrapper);\n \n if (dragStarted) {\n const dropZone = activeDropZoneRef.current;\n const targetTab = hoveredTabRef.current;\n const edgeDrop = activeEdgeDropRef.current;\n\n if (edgeDrop) {\n dockPanelToWorkspaceEdge(id, edgeDrop);\n } else if (targetTab) {\n let targetIndex = targetTab.index;\n if (targetTab.side === 'right') {\n targetIndex += 1;\n }\n movePanelOrder(id, targetTab.leafId, targetIndex);\n } else if (dropZone) {\n dockPanelToGroup(id, dropZone.leafId, dropZone.position);\n } else {\n // Float at dropped coordinates\n floatPanel(id, {\n x: moveEvent.clientX - 150,\n y: moveEvent.clientY - 15,\n width: 450,\n height: 350\n });\n }\n setDraggedPanelId(null);\n setActiveDropZone(null);\n activeDropZoneRef.current = null;\n setHoveredTab(null);\n hoveredTabRef.current = null;\n setActiveEdgeDrop(null);\n }\n };\n\n const handleMouseUpWrapper = (moveEvent: MouseEvent) => {\n handleMouseUp(moveEvent);\n };\n\n window.addEventListener('mousemove', handleMouseMove);\n window.addEventListener('mouseup', handleMouseUpWrapper);\n };\n\n const handleTabRightClick = (id: string, e: React.MouseEvent) => {\n e.preventDefault();\n const panel = state.panels[id];\n if (!panel) return;\n const registryEntry = PanelRegistry.get(panel.component);\n const options = registryEntry?.defaultOptions;\n\n const items = [];\n if (options?.canDrag !== false) {\n items.push({\n label: formatLabel(messages.floatWindow, formatMessage),\n action: () => floatPanel(id)\n });\n }\n if (options?.canMinimize !== false) {\n items.push({\n label: formatLabel(messages.minimizePanel, formatMessage),\n action: () => minimizePanel(id)\n });\n }\n if (items.length > 0 && options?.canClose !== false) {\n items.push({ separator: true as const });\n }\n if (options?.canClose !== false) {\n items.push({\n label: formatLabel(messages.closeTab, formatMessage),\n action: () => requestClosePanel(id)\n });\n }\n\n if (items.length === 0) return;\n\n contextMenuRef.current?.show({\n event: e,\n contextMenu: { items }\n });\n };\n\n const handleMinimizedRightClick = (id: string, e: React.MouseEvent) => {\n e.preventDefault();\n setHoveredMinimized(null);\n contextMenuRef.current?.show({\n event: e,\n contextMenu: {\n items: [\n {\n label: formatLabel(messages.restorePanel, formatMessage),\n action: () => restorePanel(id)\n },\n {\n label: formatLabel(messages.maximizePanel, formatMessage),\n action: () => maximizePanel(id)\n },\n { separator: true },\n {\n label: formatLabel(messages.closePanel, formatMessage),\n action: () => requestClosePanel(id)\n }\n ]\n }\n });\n };\n\n // Sync state.panels keys to dynamic DOM tree to mount components inside hidden Persistent Port\n useEffect(() => {\n const keys = Object.keys(state.panels);\n setInstantiatedPanels(keys);\n\n // Clean up domCache for panels that are no longer in state.panels\n for (const cachedId of Array.from(domCache.keys())) {\n if (!keys.includes(cachedId)) {\n domCache.delete(cachedId);\n }\n }\n }, [state.panels]);\n\n // Safe window blur handler to cancel sticky dragging states when iframe/webview loses focus\n useEffect(() => {\n const handleWindowBlur = () => {\n if (state.draggedPanelId !== null) {\n setDraggedPanelId(null);\n setActiveDropZone(null);\n setHoveredTab(null);\n }\n };\n window.addEventListener('blur', handleWindowBlur);\n return () => {\n window.removeEventListener('blur', handleWindowBlur);\n };\n }, [state.draggedPanelId]);\n\n const workspaceRef = useRef<HTMLDivElement | null>(null);\n const [workspaceSize, setWorkspaceSize] = useState({ width: 1024, height: 768 });\n\n // Dynamically observe the workspace container bounds (accounts for sidebar expanding/collapsing and taskbar showing/hiding)\n useEffect(() => {\n const el = workspaceRef.current;\n if (!el) return;\n\n const observer = new ResizeObserver((entries) => {\n if (!entries || entries.length === 0) return;\n const rect = entries[0].contentRect;\n setWorkspaceSize({\n width: Math.max(100, rect.width),\n height: Math.max(100, rect.height)\n });\n });\n\n observer.observe(el);\n return () => {\n observer.disconnect();\n };\n }, []);\n\n // Sync / Realignment Effect when actual workspace size changes\n useEffect(() => {\n const viewW = workspaceSize.width;\n const viewH = workspaceSize.height;\n\n state.floating.forEach(w => {\n const winW = typeof w.width === 'string' ? parseFloat(w.width) : w.width;\n const winH = typeof w.height === 'string' ? parseFloat(w.height) : w.height;\n const winX = typeof w.x === 'string' ? parseFloat(w.x) : w.x;\n const winY = typeof w.y === 'string' ? parseFloat(w.y) : w.y;\n\n let newWidth = winW;\n let newHeight = winH;\n let newX = winX;\n let newY = winY;\n let changed = false;\n\n // Clamp window size if it exceeds the new workspace size\n if (newWidth > viewW) {\n newWidth = Math.max(200, viewW - 20);\n changed = true;\n }\n if (newHeight > viewH) {\n newHeight = Math.max(150, viewH - 40);\n changed = true;\n }\n\n const GAP = 10;\n\n // Align sticky borders\n if (w.stickyRight) {\n newX = viewW - newWidth - GAP;\n changed = true;\n } else {\n // Bounding clamp for non-sticky windows to prevent falling off-screen\n const maxX = viewW - 100; // Keep at least 100px of titlebar visible\n if (newX > maxX) {\n newX = Math.max(0, maxX);\n changed = true;\n }\n }\n\n if (w.stickyBottom) {\n newY = viewH - newHeight - GAP;\n changed = true;\n } else {\n const maxY = viewH - 40; // Keep titlebar clickable\n if (newY > maxY) {\n newY = Math.max(0, maxY);\n changed = true;\n }\n }\n\n if (changed) {\n updateFloatingPosition(w.id, {\n x: newX,\n y: newY,\n width: newWidth,\n height: newHeight\n });\n }\n });\n }, [workspaceSize, state.floating, updateFloatingPosition]);\n\n // Global Window Focus Event Delegation (Left-click anywhere inside a window raises it)\n useEffect(() => {\n const handleMouseDownGlobal = (e: MouseEvent) => {\n // Only handle left clicks (button === 0)\n if (e.button !== 0) return;\n\n const target = e.target as HTMLElement | null;\n if (!target) return;\n\n const windowEl = target.closest('.floating-window') as HTMLElement | null;\n if (!windowEl) return;\n\n const winId = windowEl.getAttribute('data-window-id');\n if (winId) {\n bringToFront(winId);\n }\n };\n\n document.addEventListener('mousedown', handleMouseDownGlobal);\n return () => {\n document.removeEventListener('mousedown', handleMouseDownGlobal);\n };\n }, [bringToFront]);\n\n // Floating Window dragging handler\n const startDrag = (id: string, e: React.MouseEvent) => {\n const floatingWin = state.floating.find(w => w.id === id);\n if (!floatingWin || floatingWin.maximized) return;\n bringToFront(id);\n\n const startX = e.clientX;\n const startY = e.clientY;\n const titlebarEl = e.currentTarget as HTMLDivElement;\n const windowEl = titlebarEl.closest('.floating-window') as HTMLDivElement | null;\n const startPosX = windowEl ? windowEl.offsetLeft : 0;\n const startPosY = windowEl ? windowEl.offsetTop : 0;\n let dragStarted = false;\n\n const handleMouseMove = (moveEvent: MouseEvent) => {\n const dx = moveEvent.clientX - startX;\n const dy = moveEvent.clientY - startY;\n\n if (!dragStarted && (Math.abs(dx) > 5 || Math.abs(dy) > 5)) {\n dragStarted = true;\n setDraggedPanelId(id);\n }\n\n if (dragStarted) {\n const newX = startPosX + dx;\n const newY = startPosY + dy;\n\n // Dragging clears all sticky anchoring\n updateFloatingPosition(id, {\n x: newX,\n y: newY,\n stickyRight: false,\n stickyBottom: false\n });\n }\n };\n\n const handleMouseUp = () => {\n if (dragStarted) {\n const dropZone = activeDropZoneRef.current;\n const targetTab = hoveredTabRef.current;\n const edgeDrop = activeEdgeDropRef.current;\n\n if (edgeDrop) {\n dockPanelToWorkspaceEdge(id, edgeDrop);\n } else if (targetTab) {\n let targetIndex = targetTab.index;\n if (targetTab.side === 'right') {\n targetIndex += 1;\n }\n movePanelOrder(id, targetTab.leafId, targetIndex);\n } else if (dropZone) {\n dockPanelToGroup(id, dropZone.leafId, dropZone.position);\n }\n setDraggedPanelId(null);\n setActiveDropZone(null);\n activeDropZoneRef.current = null;\n setHoveredTab(null);\n hoveredTabRef.current = null;\n setActiveEdgeDrop(null);\n }\n window.removeEventListener('mousemove', handleMouseMove);\n window.removeEventListener('mouseup', handleMouseUp);\n };\n\n window.addEventListener('mousemove', handleMouseMove);\n window.addEventListener('mouseup', handleMouseUp);\n };\n\n // Floating Window resizing handler\n const startResize = (id: string, e: React.MouseEvent) => {\n e.stopPropagation();\n const floatingWin = state.floating.find(w => w.id === id);\n if (!floatingWin || floatingWin.maximized) return;\n bringToFront(id);\n\n const startX = e.clientX;\n const startY = e.clientY;\n const handleEl = e.currentTarget as HTMLDivElement;\n const windowEl = handleEl.closest('.floating-window') as HTMLDivElement | null;\n const startW = windowEl ? windowEl.offsetWidth : 400;\n const startH = windowEl ? windowEl.offsetHeight : 300;\n\n const handleMouseMove = (moveEvent: MouseEvent) => {\n const dw = moveEvent.clientX - startX;\n const dh = moveEvent.clientY - startY;\n\n let newWidth = Math.max(200, startW + dw);\n let newHeight = Math.max(150, startH + dh);\n\n let newX = floatingWin.x;\n let newY = floatingWin.y;\n\n const viewW = workspaceSize.width;\n const viewH = workspaceSize.height;\n\n const parsedX = typeof floatingWin.x === 'string' ? parseFloat(floatingWin.x) : floatingWin.x;\n const parsedY = typeof floatingWin.y === 'string' ? parseFloat(floatingWin.y) : floatingWin.y;\n const parsedW = typeof floatingWin.width === 'string' ? parseFloat(floatingWin.width) : floatingWin.width;\n const parsedH = typeof floatingWin.height === 'string' ? parseFloat(floatingWin.height) : floatingWin.height;\n\n const isRightSnapped = Math.abs(parsedX + parsedW - viewW) < 4;\n const isBottomSnapped = Math.abs(parsedY + parsedH - viewH) < 4;\n\n if (isRightSnapped) {\n newX = viewW - newWidth;\n if (newX < 0) {\n newX = 0;\n newWidth = viewW;\n }\n }\n\n if (isBottomSnapped) {\n newY = viewH - newHeight;\n if (newY < 0) {\n newY = 0;\n newHeight = viewH;\n }\n }\n\n updateFloatingPosition(id, {\n x: newX,\n y: newY,\n width: newWidth,\n height: newHeight,\n stickyRight: isRightSnapped,\n stickyBottom: isBottomSnapped\n });\n };\n\n const handleMouseUp = () => {\n window.removeEventListener('mousemove', handleMouseMove);\n window.removeEventListener('mouseup', handleMouseUp);\n };\n\n window.addEventListener('mousemove', handleMouseMove);\n window.addEventListener('mouseup', handleMouseUp);\n };\n\n // horizontal scroll for minimized taskbar\n const scrollTaskbar = (direction: 'left' | 'right') => {\n if (taskbarRef.current) {\n const amount = direction === 'left' ? -150 : 150;\n taskbarRef.current.scrollBy({ left: amount, behavior: 'smooth' });\n }\n };\n\n // Fetch the active bs-theme from documentElement to make sure nested variables resolve correctly\n const [currentBsTheme, setCurrentBsTheme] = useState<'dark' | 'light'>('dark');\n useEffect(() => {\n const updateThemeState = () => {\n const activeTheme = document.documentElement.getAttribute('data-bs-theme') === 'light' ? 'light' : 'dark';\n setCurrentBsTheme(activeTheme);\n };\n updateThemeState();\n const obs = new MutationObserver(updateThemeState);\n obs.observe(document.documentElement, { attributes: true, attributeFilter: ['data-bs-theme'] });\n return () => obs.disconnect();\n }, []);\n\n return (\n <div \n data-workspace-skin={skin}\n data-bs-theme={currentBsTheme}\n className=\"d-flex flex-column w-100 h-100 overflow-hidden\" \n style={{ userSelect: 'none' }}\n >\n \n {/* 1. Main Workspace Viewport (Grids & Floating Panels) */}\n <div \n ref={workspaceRef} \n className={`flex-grow-1 w-100 position-relative ${state.draggedPanelId ? 'dragging-active' : ''}`}\n style={{ overflow: 'hidden' }}\n >\n {/* Workspace outer edge drop zone targets */}\n {state.draggedPanelId !== null && (\n <>\n <div \n className=\"workspace-edge-trigger edge-trigger-left\"\n onMouseEnter={() => setActiveEdgeDrop('left')}\n onMouseLeave={() => setActiveEdgeDrop(null)}\n />\n <div \n className=\"workspace-edge-trigger edge-trigger-right\"\n onMouseEnter={() => setActiveEdgeDrop('right')}\n onMouseLeave={() => setActiveEdgeDrop(null)}\n />\n <div \n className=\"workspace-edge-trigger edge-trigger-top\"\n onMouseEnter={() => setActiveEdgeDrop('top')}\n onMouseLeave={() => setActiveEdgeDrop(null)}\n />\n <div \n className=\"workspace-edge-trigger edge-trigger-bottom\"\n onMouseEnter={() => setActiveEdgeDrop('bottom')}\n onMouseLeave={() => setActiveEdgeDrop(null)}\n />\n </>\n )}\n\n {/* Edge drop visual preview overlay */}\n {state.draggedPanelId !== null && activeEdgeDrop !== null && (\n <div className={`workspace-edge-preview edge-preview-${activeEdgeDrop}`} />\n )}\n \n {/* 1.1 Viewport Split Grid Layout */}\n <div className=\"w-100 h-100\" style={{ overflow: 'hidden', position: 'relative' }}>\n {state.gridRoot ? (\n <WorkspaceGrid \n node={state.gridRoot} \n path={[]} \n onTabRightClick={handleTabRightClick} \n activeDropZone={activeDropZone} \n onHoverDropZone={handleHoverDropZone} \n onTabDragStart={handleTabDragStart}\n hoveredTab={hoveredTab}\n onTabHover={handleTabHover}\n defaultPanelIcon={defaultPanelIcon}\n />\n ) : (\n <div className=\"w-100 h-100 d-flex align-items-center justify-content-center text-muted font-monospace small\">\n Grid Empty\n </div>\n )}\n </div>\n\n {/* 1.2 Floating Windows Absolute Container Overlay */}\n {(() => {\n const maxZ = state.floating.length > 0 ? Math.max(...state.floating.map(w => w.z)) : 0;\n return state.floating.map(w => {\n const panel = state.panels[w.id];\n if (!panel) return null;\n \n const isMaximized = w.maximized;\n const isDragged = state.draggedPanelId === w.id;\n const isFocused = w.z === maxZ && state.floating.length > 0;\n\n const registryEntry = PanelRegistry.get(panel.component);\n const options = registryEntry?.defaultOptions;\n\n return (\n <div\n key={w.id}\n data-window-id={w.id}\n className={`floating-window ${isMaximized ? 'maximized' : ''} ${isFocused ? 'v2-window-focused' : ''} ${windowClass ?? ''}`}\n style={{\n position: 'absolute',\n left: isMaximized ? 0 : (typeof w.x === 'number' ? `${w.x}px` : w.x),\n top: isMaximized ? 0 : (typeof w.y === 'number' ? `${w.y}px` : w.y),\n width: isMaximized ? '100%' : (typeof w.width === 'number' ? `${w.width}px` : w.width),\n height: isMaximized ? '100%' : (typeof w.height === 'number' ? `${w.height}px` : w.height),\n zIndex: w.z,\n pointerEvents: isDragged ? 'none' : 'auto',\n }}\n >\n {/* Title Bar */}\n <div \n onDoubleClick={() => maximizePanel(w.id)}\n onMouseDown={(e) => {\n if (options?.canDrag !== false) {\n startDrag(w.id, e);\n }\n }}\n className=\"floating-window-titlebar d-flex flex-row justify-content-between align-items-center cursor-move\"\n style={{ cursor: isMaximized || options?.canDrag === false ? 'default' : 'move' }}\n >\n <span className=\"floating-window-title text-truncate me-2 d-flex align-items-center\">\n <span className=\"window-title-icon\">{options?.icon || defaultPanelIcon || DefaultGridIcon}</span>\n <span>\n {formatLabel(panel.title, formatMessage)}\n {panel.dirty ? ' *' : ''}\n </span>\n </span>\n <div className=\"d-flex align-items-center gap-1.5\" onMouseDown={(e) => e.stopPropagation()}>\n {options?.canDrag !== false && (\n <button \n type=\"button\" \n title={formatLabel(messages.windowAnchoringOptions, formatMessage)}\n onClick={(e) => {\n const isRight = !!w.stickyRight;\n const isBottom = !!w.stickyBottom;\n contextMenuRef.current?.show({\n event: e,\n contextMenu: {\n items: [\n {\n label: formatLabel(messages.anchorToRightEdge, formatMessage),\n checkbox: {\n active: true,\n enabled: true,\n value: isRight\n },\n action: () => {\n const viewW = workspaceSize.width;\n const winW = typeof w.width === 'string' ? parseFloat(w.width) : w.width;\n const GAP = 10;\n if (!isRight) {\n updateFloatingPosition(w.id, { x: viewW - winW - GAP, stickyRight: true });\n } else {\n updateFloatingPosition(w.id, { stickyRight: false });\n }\n }\n },\n {\n label: formatLabel(messages.anchorToBottomEdge, formatMessage),\n checkbox: {\n active: true,\n enabled: true,\n value: isBottom\n },\n action: () => {\n const viewH = workspaceSize.height;\n const winH = typeof w.height === 'string' ? parseFloat(w.height) : w.height;\n const GAP = 10;\n if (!isBottom) {\n updateFloatingPosition(w.id, { y: viewH - winH - GAP, stickyBottom: true });\n } else {\n updateFloatingPosition(w.id, { stickyBottom: false });\n }\n }\n }\n ]\n }\n });\n }}\n className=\"custom-tab-btn btn-anchor-tab\"\n >\n <svg className={`anchor-icon ${(w.stickyRight && w.stickyBottom) ? 'anchor-sticky-both' : w.stickyRight ? 'anchor-sticky-right' : w.stickyBottom ? 'anchor-sticky-bottom' : ''}`} width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\">\n <circle cx=\"12\" cy=\"5\" r=\"2\" />\n <path d=\"M12 7v7m0 0a4 4 0 0 1-4-4M12 14a4 4 0 0 0 4-4M5 18h14\" />\n </svg>\n </button>\n )}\n {options?.canMinimize !== false && (\n <button \n type=\"button\" \n title={formatLabel(messages.minimize, formatMessage)}\n onClick={() => minimizePanel(w.id)}\n className=\"custom-tab-btn\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\">\n <path d=\"M5 12h14\"/>\n </svg>\n </button>\n )}\n <button \n type=\"button\" \n title={isMaximized\n ? formatLabel(messages.restoreSize, formatMessage)\n : formatLabel(messages.maximize, formatMessage)}\n onClick={() => maximizePanel(w.id)}\n className=\"custom-tab-btn\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\">\n <rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"1.5\"/>\n </svg>\n </button>\n {options?.canClose !== false && (\n <button \n type=\"button\" \n title={formatLabel(messages.close, formatMessage)}\n onClick={() => requestClosePanel(w.id)}\n className=\"custom-tab-btn btn-close-tab\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\">\n <path d=\"M18 6L6 18M6 6l12 12\"/>\n </svg>\n </button>\n )}\n </div>\n </div>\n\n {/* Window Content */}\n <div className={`flex-grow-1 w-100 overflow-hidden ${windowBodyClass ?? ''}`} style={{ position: 'relative' }}>\n <PreservedDOMWrapper key={w.id} panelId={w.id} />\n </div>\n\n {/* Resize Handle */}\n {!isMaximized && (\n <div\n onMouseDown={(e) => startResize(w.id, e)}\n style={{\n position: 'absolute',\n right: 0,\n bottom: 0,\n width: '14px',\n height: '14px',\n cursor: 'se-resize',\n zIndex: 30,\n background: 'linear-gradient(135deg, transparent 50%, rgba(255,255,255,0.2) 50%)'\n }}\n />\n )}\n </div>\n );\n });\n })()}\n </div>\n\n {/* 2. macOS / Windows 11-style Taskbar Sibling Footer (Flex-shrinked at bottom) */}\n {state.minimized.length > 0 && (\n <div className=\"flex-shrink-0 w-100 d-flex flex-row align-items-center taskbar-footer-container px-3 py-1.5 justify-content-center\" style={{ height: '48px', zIndex: 100 }}>\n <button \n type=\"button\" \n onClick={() => scrollTaskbar('left')}\n className=\"btn btn-sm btn-link taskbar-nav-btn text-decoration-none py-0 font-monospace\"\n style={{ display: state.minimized.length > 4 ? 'block' : 'none' }}\n >\n ◀\n </button>\n \n <div \n ref={taskbarRef}\n className=\"d-flex flex-row gap-2 overflow-x-auto align-items-center mx-2 px-1 py-0.5 scrollbar-hidden\"\n style={{\n maxWidth: '800px',\n scrollbarWidth: 'none',\n scrollSnapType: 'x mandatory'\n }}\n >\n {state.minimized.map(m => {\n const regEntry = PanelRegistry.get(m.component);\n const icon = regEntry?.defaultOptions?.icon || defaultPanelIcon || DefaultGridIcon;\n\n return (\n <div\n key={m.id}\n onClick={() => restorePanel(m.id)}\n onContextMenu={(e) => handleMinimizedRightClick(m.id, e)}\n onMouseEnter={(e) => {\n if (isContextMenuOpen) return;\n if (minimizedTooltipTimeoutRef.current) {\n clearTimeout(minimizedTooltipTimeoutRef.current);\n }\n const rect = e.currentTarget.getBoundingClientRect();\n setHoveredMinimized({ id: m.id, rect, title: m.title, component: m.component });\n }}\n onMouseLeave={() => {\n minimizedTooltipTimeoutRef.current = setTimeout(() => {\n setHoveredMinimized(null);\n }, 150);\n }}\n className=\"taskbar-glassmorphic-item rounded d-flex align-items-center justify-content-center cursor-pointer hover-elevate\"\n style={{\n backdropFilter: 'blur(6px)',\n transition: 'all 0.2s',\n cursor: 'pointer',\n scrollSnapAlign: 'start',\n width: '38px',\n height: '38px',\n position: 'relative',\n padding: 0\n }}\n >\n <span className=\"taskbar-item-icon d-flex align-items-center justify-content-center\">\n {icon}\n </span>\n </div>\n );\n })}\n </div>\n\n {hoveredMinimized && createPortal(\n <div \n className=\"taskbar-item-tooltip d-flex flex-column gap-1\"\n style={{\n position: 'fixed',\n left: `${hoveredMinimized.rect.left + hoveredMinimized.rect.width / 2}px`,\n top: `${hoveredMinimized.rect.top - 8}px`,\n transform: 'translateX(-50%) translateY(-100%)',\n opacity: 1,\n pointerEvents: 'auto',\n zIndex: 999999\n }}\n onMouseEnter={() => {\n if (minimizedTooltipTimeoutRef.current) {\n clearTimeout(minimizedTooltipTimeoutRef.current);\n }\n }}\n onMouseLeave={() => {\n setHoveredMinimized(null);\n }}\n >\n <div className=\"d-flex flex-row align-items-center justify-content-between w-100 gap-3 px-1 py-0.5\">\n <span className=\"tooltip-title-text text-truncate\" style={{ maxWidth: '140px' }}>\n {formatLabel(hoveredMinimized.title, formatMessage)}\n {state.panels[hoveredMinimized.id]?.dirty ? ' *' : ''}\n </span>\n <span \n onClick={(e) => {\n e.stopPropagation();\n requestClosePanel(hoveredMinimized.id);\n setHoveredMinimized(null);\n }}\n title={formatLabel(messages.closePanel, formatMessage)}\n className=\"tooltip-close-x d-flex align-items-center justify-content-center\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\">\n <path d=\"M18 6L6 18M6 6l12 12\"/>\n </svg>\n </span>\n </div>\n <PreviewDOMWrapper panelId={hoveredMinimized.id} />\n </div>,\n document.body\n )}\n\n <button \n type=\"button\" \n onClick={() => scrollTaskbar('right')}\n className=\"btn btn-sm btn-link taskbar-nav-btn text-decoration-none py-0 font-monospace\"\n style={{ display: state.minimized.length > 4 ? 'block' : 'none' }}\n >\n ▶\n </button>\n </div>\n )}\n\n {/* 3. Persistence Port: Portals rendering panels into off-screen elements */}\n {instantiatedPanels.map((id) => {\n const panel = state.panels[id];\n if (!panel) return null;\n const targetEl = getOrCreateDomCacheElement(id);\n return createPortal(\n <FormContainerProviderWrapper panelId={id}>\n <div style={{ width: '100%', height: '100%' }}>\n {renderPanelContent(id, panel.component)}\n </div>\n </FormContainerProviderWrapper>,\n targetEl,\n id\n );\n })}\n\n {/* 4. Context Menu (replace-react-contexify JSON mode) */}\n <JsonContextMenu \n ref={contextMenuRef} \n id=\"workspace-context-menu\" \n theme=\"dark\" \n onShow={() => setIsContextMenuOpen(true)}\n onHide={() => setIsContextMenuOpen(false)}\n />\n\n {/* 5. Dragging Tab Ghost Representation */}\n {state.draggedPanelId !== null && !state.floating.some(w => w.id === state.draggedPanelId) && (\n <div \n className=\"position-fixed bg-black bg-opacity-80 border border-info rounded text-info font-monospace px-3 py-1.5 shadow-lg d-flex align-items-center gap-2\"\n style={{\n left: dragPos.x + 12,\n top: dragPos.y + 12,\n zIndex: 100000,\n pointerEvents: 'none',\n fontSize: '0.75rem',\n boxShadow: '0 8px 24px rgba(0,0,0,0.5)',\n borderLeft: '3px solid var(--accent-color)',\n whiteSpace: 'nowrap'\n }}\n >\n 📄 {formatLabel(state.panels[state.draggedPanelId]?.title, formatMessage) || 'Tab'}\n </div>\n )}\n\n {/* 6. Dirty warning dialog overlay */}\n {state.pendingClose && (() => {\n const pendingPanel = state.panels[state.pendingClose.id];\n const panelTitle = pendingPanel ? formatLabel(pendingPanel.title, formatMessage) : 'Panel';\n return (\n <div className=\"close-warning-overlay\">\n <div className=\"close-warning-modal\">\n <div className=\"close-warning-header\">\n <div className=\"close-warning-icon\">⚠️</div>\n <h5 className=\"close-warning-title\">Unsaved Changes</h5>\n </div>\n <p className=\"close-warning-message\">\n \"{panelTitle}\" has unsaved changes. Do you want to discard your changes and close the panel?\n </p>\n <div className=\"close-warning-footer\">\n <button\n type=\"button\"\n className=\"btn-warning-action btn-warning-cancel\"\n onClick={() => resolvePendingClose(false)}\n >\n Cancel\n </button>\n <button\n type=\"button\"\n className=\"btn-warning-action btn-warning-discard\"\n onClick={() => resolvePendingClose(true)}\n >\n Discard Changes\n </button>\n </div>\n </div>\n </div>\n );\n })()}\n \n </div>\n );\n};\n\nexport default WindowManager;\n","import React, { createContext, useContext, useState, useRef, useMemo, useCallback } from 'react';\nimport { PanelRegistry } from './PanelRegistry';\nimport { defaultPredefinedMessages } from './predefinedMessages';\nimport type { PredefinedMessageKey } from './predefinedMessages';\nexport type { PredefinedMessageKey } from './predefinedMessages';\nexport { defaultPredefinedMessages } from './predefinedMessages';\n\nexport interface ContextMenuPredefinedMessage {\n id: string;\n defaultMessage?: string;\n values?: Record<string, string | number>;\n}\n\nexport type MessageFormatter = (msg: ContextMenuPredefinedMessage) => string;\n\nexport type SplitOrientation = 'horizontal' | 'vertical';\n\nexport interface LayoutGridNode {\n type: 'branch';\n orientation: SplitOrientation;\n children: LayoutNode[];\n sizes: number[];\n}\n\nexport interface LayoutLeafNode {\n type: 'leaf';\n id: string;\n panels: string[];\n activePanelId: string | null;\n canClose?: boolean;\n /** When true the leaf group persists in the layout even after its last panel\n * is closed/floated/minimised. Defaults to false (auto-remove). */\n keepOnEmpty?: boolean;\n}\n\nexport type LayoutNode = LayoutGridNode | LayoutLeafNode;\n\nexport interface FloatingWindow {\n id: string;\n x: number | string;\n y: number | string;\n width: number | string;\n height: number | string;\n z: number;\n maximized?: boolean;\n stickyRight?: boolean;\n stickyBottom?: boolean;\n}\n\nexport interface PanelInfo {\n id: string;\n title: string | ContextMenuPredefinedMessage;\n component: string;\n state: 'docked' | 'floating' | 'minimized';\n previousState?: 'docked' | 'floating';\n lastFloatingRect?: { x: number; y: number; width: number; height: number; stickyRight?: boolean; stickyBottom?: boolean };\n lastLeafId?: string;\n dirty?: boolean;\n}\n\nexport interface WindowState {\n gridRoot: LayoutNode;\n floating: FloatingWindow[];\n minimized: { id: string; title: string | ContextMenuPredefinedMessage; component: string }[];\n panels: Record<string, PanelInfo>;\n draggedPanelId: string | null;\n pendingClose: { id: string; resolve: (discard: boolean) => void } | null;\n}\n\nexport interface WindowActions {\n openPanel: (id: string, component: string, options?: { title?: string | ContextMenuPredefinedMessage; initialTarget?: 'floating' | 'docked' | 'tabbed'; stickyRight?: boolean; stickyBottom?: boolean }) => void;\n closePanel: (id: string) => void;\n minimizePanel: (id: string) => void;\n restorePanel: (id: string) => void;\n floatPanel: (id: string, rect?: { x: number; y: number; width: number; height: number }) => void;\n dockPanel: (id: string, targetLeafId?: string) => void;\n maximizePanel: (id: string) => void;\n updateSplitSizes: (path: number[], sizes: number[]) => void;\n updateFloatingPosition: (id: string, updates: Partial<Pick<FloatingWindow, 'x' | 'y' | 'width' | 'height' | 'stickyRight' | 'stickyBottom'>>) => void;\n bringToFront: (id: string) => void;\n saveLayout: () => string;\n loadLayout: (layoutJson: string) => void;\n publish: (event: string, data: any) => void;\n subscribe: (event: string, callback: (data: any) => void) => () => void;\n setDraggedPanelId: (id: string | null) => void;\n dockPanelToGroup: (id: string, targetLeafId: string, position: 'left' | 'right' | 'top' | 'bottom' | 'center') => void;\n movePanelOrder: (panelId: string, targetLeafId: string, targetIndex: number) => void;\n closeLeafGroup: (leafId: string) => void;\n registerCloseGuard: (id: string, guard: () => boolean | Promise<boolean>) => void;\n unregisterCloseGuard: (id: string) => void;\n setPanelDirty: (id: string, dirty: boolean) => void;\n updatePanelTitle: (id: string, title: string | ContextMenuPredefinedMessage) => void;\n requestClosePanel: (id: string, options?: { force?: boolean }) => Promise<void>;\n resolvePendingClose: (discard: boolean) => void;\n dockPanelToWorkspaceEdge: (id: string, position: 'left' | 'right' | 'top' | 'bottom') => void;\n}\n\nconst WindowStateContext = createContext<WindowState | null>(null);\nconst WindowActionsContext = createContext<WindowActions | null>(null);\nconst WindowI18nContext = createContext<MessageFormatter | null>(null);\n\nconst WindowPredefinedMessagesContext = createContext<Record<PredefinedMessageKey, ContextMenuPredefinedMessage>>(defaultPredefinedMessages);\n\nexport interface StyleClasses {\n modalClass?: string;\n modalBodyClass?: string;\n sidePanelClass?: string;\n sidePanelBodyClass?: string;\n windowClass?: string;\n windowBodyClass?: string;\n}\n\nconst StyleClassContext = createContext<StyleClasses>({});\nexport const useStyleClasses = () => useContext(StyleClassContext);\n\n// Event Bus class for pub-sub communication between panels\nclass PanelEventBus {\n private listeners: Record<string, ((data: any) => void)[]> = {};\n\n subscribe(event: string, callback: (data: any) => void) {\n if (!this.listeners[event]) {\n this.listeners[event] = [];\n }\n this.listeners[event].push(callback);\n return () => {\n this.listeners[event] = this.listeners[event].filter(cb => cb !== callback);\n };\n }\n\n publish(event: string, data: any) {\n if (this.listeners[event]) {\n this.listeners[event].forEach(cb => cb(data));\n }\n }\n}\n\nconst initialLayout: LayoutNode = {\n type: 'branch',\n orientation: 'vertical',\n sizes: [0.75, 0.25],\n children: [\n {\n type: 'leaf',\n id: 'group-left-top',\n panels: ['main-map', 'main-editor'],\n activePanelId: 'main-map',\n },\n {\n type: 'leaf',\n id: 'group-left-bottom',\n panels: ['system-console', 'help-docs'],\n activePanelId: 'system-console',\n }\n ]\n};\n\nconst initialPanels: Record<string, PanelInfo> = {\n 'main-map': { id: 'main-map', title: 'Main Map', component: 'mainMap', state: 'docked' },\n 'main-editor': { id: 'main-editor', title: 'Code Editor', component: 'editor', state: 'docked' },\n 'system-console': { id: 'system-console', title: 'Console Output', component: 'terminal', state: 'docked' },\n 'help-docs': { id: 'help-docs', title: 'Help Center', component: 'help', state: 'docked' },\n 'live-preview': { id: 'live-preview', title: 'Live Preview Output', component: 'preview', state: 'floating' }\n};\n\nconst initialFloating: FloatingWindow[] = [\n { id: 'live-preview', x: 450, y: 200, width: 320, height: 250, z: 1000 }\n];\n\nexport interface WindowManagerProviderProps {\n children: React.ReactNode;\n formatMessage?: MessageFormatter;\n predefinedMessages?: Record<string, ContextMenuPredefinedMessage>;\n modalClass?: string;\n modalBodyClass?: string;\n sidePanelClass?: string;\n sidePanelBodyClass?: string;\n windowClass?: string;\n windowBodyClass?: string;\n}\n\nexport const WindowManagerProvider: React.FC<WindowManagerProviderProps> = ({\n children,\n formatMessage,\n predefinedMessages,\n modalClass,\n modalBodyClass,\n sidePanelClass,\n sidePanelBodyClass,\n windowClass,\n windowBodyClass\n}) => {\n const [state, setState] = useState<WindowState>({\n gridRoot: initialLayout,\n floating: initialFloating,\n minimized: [],\n panels: initialPanels,\n draggedPanelId: null,\n pendingClose: null\n });\n\n const stateRef = useRef(state);\n stateRef.current = state;\n\n const closeGuardsRef = useRef<Record<string, () => boolean | Promise<boolean>>>({});\n\n const mergedMessages = useMemo(() => ({\n ...defaultPredefinedMessages,\n ...predefinedMessages\n }), [predefinedMessages]);\n\n const eventBusRef = useRef(new PanelEventBus());\n const maxZRef = useRef(1000);\n\n const subscribe = useCallback((event: string, callback: (data: any) => void) => {\n return eventBusRef.current.subscribe(event, callback);\n }, []);\n\n const publish = useCallback((event: string, data: any) => {\n eventBusRef.current.publish(event, data);\n }, []);\n\n // Helper: Find free cascading location for floating window\n const getCascadedPosition = useCallback((\n fav: { x: number | string; y: number | string; width: number | string; height: number | string },\n currentFloating: FloatingWindow[]\n ) => {\n let x = typeof fav.x === 'string' ? parseFloat(fav.x) : fav.x;\n let y = typeof fav.y === 'string' ? parseFloat(fav.y) : fav.y;\n let width = typeof fav.width === 'string' ? parseFloat(fav.width) : fav.width;\n let height = typeof fav.height === 'string' ? parseFloat(fav.height) : fav.height;\n\n // Fallbacks if parseFloat fails and returns NaN\n if (isNaN(x)) x = 300;\n if (isNaN(y)) y = 150;\n if (isNaN(width)) width = 450;\n if (isNaN(height)) height = 350;\n\n const isOverlapping = (pos: { x: number; y: number }) => {\n return currentFloating.some(w => {\n const wx = typeof w.x === 'string' ? parseFloat(w.x) : w.x;\n const wy = typeof w.y === 'string' ? parseFloat(w.y) : w.y;\n return !w.maximized && Math.abs(wx - pos.x) < 20 && Math.abs(wy - pos.y) < 20;\n });\n };\n\n let attempts = 0;\n while (isOverlapping({ x, y }) && attempts < 10) {\n x += 30;\n y += 30;\n attempts++;\n }\n\n // Capture safe viewport boundaries (min 1024x768 fallback if not measured or in headless environments)\n const viewW = Math.max(100, window.innerWidth || 1024);\n const viewH = Math.max(100, window.innerHeight || 768);\n\n if (x + width > viewW || y + height > viewH) {\n x = 100 + (attempts % 5) * 30;\n y = 100 + (attempts % 5) * 30;\n }\n\n // Final safety clamp to make sure window title bar is always visible and clickable\n x = Math.max(0, Math.min(x, viewW - 100));\n y = Math.max(0, Math.min(y, viewH - 40));\n\n return { x, y, width, height };\n }, []);\n\n const bringToFront = useCallback((id: string) => {\n maxZRef.current += 1;\n const z = maxZRef.current;\n setState(prev => {\n const panel = prev.panels[id];\n if (!panel) return prev;\n\n if (panel.state === 'floating') {\n return {\n ...prev,\n floating: prev.floating.map(w => w.id === id ? { ...w, z } : w)\n };\n } else if (panel.state === 'docked') {\n const selectActiveInTree = (node: LayoutNode): LayoutNode => {\n if (node.type === 'leaf') {\n if (node.panels.includes(id)) {\n return { ...node, activePanelId: id };\n }\n return node;\n } else {\n return { ...node, children: node.children.map(selectActiveInTree) };\n }\n };\n return {\n ...prev,\n gridRoot: selectActiveInTree(prev.gridRoot)\n };\n }\n return prev;\n });\n }, []);\n\n // Recursive helpers to manipulate layout tree\n const removePanelFromTree = (node: LayoutNode, id: string): LayoutNode | null => {\n if (node.type === 'leaf') {\n const idx = node.panels.indexOf(id);\n if (idx === -1) return node;\n const panels = node.panels.filter(p => p !== id);\n const activePanelId = node.activePanelId === id\n ? (panels[idx] || panels[idx - 1] || panels[0] || null)\n : node.activePanelId;\n const updatedLeaf = { ...node, panels, activePanelId };\n // Auto-remove this leaf when it becomes empty, unless keepOnEmpty is set\n if (panels.length === 0 && !node.keepOnEmpty) return null;\n return updatedLeaf;\n } else {\n const children = node.children\n .map(c => removePanelFromTree(c, id))\n .filter((c): c is LayoutNode => c !== null);\n\n if (children.length === 0) return null;\n if (children.length === 1) return children[0];\n\n // Re-normalize sizes\n const sizes = node.sizes.slice(0, children.length);\n const sum = sizes.reduce((a, b) => a + b, 0);\n return {\n ...node,\n children,\n sizes: sizes.map(s => s / sum)\n };\n }\n };\n\n const addPanelToLeaf = (node: LayoutNode, leafId: string, panelId: string): LayoutNode => {\n if (node.type === 'leaf') {\n if (node.id === leafId) {\n const panels = node.panels.includes(panelId) ? node.panels : [...node.panels, panelId];\n return { ...node, panels, activePanelId: panelId };\n }\n return node;\n } else {\n return {\n ...node,\n children: node.children.map(c => addPanelToLeaf(c, leafId, panelId))\n };\n }\n };\n\n const findFirstLeafId = (node: LayoutNode): string | null => {\n if (node.type === 'leaf') return node.id;\n for (const child of node.children) {\n const id = findFirstLeafId(child);\n if (id) return id;\n }\n return null;\n };\n\n const openPanel = useCallback((id: string, component: string, options?: { title?: string | ContextMenuPredefinedMessage; initialTarget?: 'floating' | 'docked' | 'tabbed'; stickyRight?: boolean; stickyBottom?: boolean }) => {\n setState(prev => {\n const exists = prev.panels[id];\n const entry = PanelRegistry.get(component);\n const title = options?.title || options?.title || entry?.defaultOptions?.title || id;\n const target = options?.initialTarget || entry?.defaultOptions?.initialTarget || 'docked';\n const favPos = entry?.defaultOptions?.favoritePosition || { x: 300, y: 150, width: 450, height: 350 };\n\n // Case 1: Already exists\n if (exists) {\n if (exists.state === 'minimized') {\n // Restore\n const nextMinimized = prev.minimized.filter(m => m.id !== id);\n if (target === 'floating' || !prev.gridRoot) {\n maxZRef.current += 1;\n const cascaded = getCascadedPosition(favPos, prev.floating);\n return {\n ...prev,\n minimized: nextMinimized,\n floating: [...prev.floating, { ...cascaded, id, z: maxZRef.current }],\n panels: { ...prev.panels, [id]: { ...exists, state: 'floating' } }\n };\n } else {\n const firstLeaf = findFirstLeafId(prev.gridRoot) || 'group-left-top';\n return {\n ...prev,\n minimized: nextMinimized,\n gridRoot: addPanelToLeaf(prev.gridRoot, firstLeaf, id),\n panels: { ...prev.panels, [id]: { ...exists, state: 'docked' } }\n };\n }\n } else if (exists.state === 'floating') {\n bringToFront(id);\n return prev;\n } else {\n // Focus in tab group\n const selectActiveInTree = (node: LayoutNode): LayoutNode => {\n if (node.type === 'leaf') {\n if (node.panels.includes(id)) {\n return { ...node, activePanelId: id };\n }\n return node;\n } else {\n return { ...node, children: node.children.map(selectActiveInTree) };\n }\n };\n return {\n ...prev,\n gridRoot: selectActiveInTree(prev.gridRoot)\n };\n }\n }\n\n // Case 2: New panel\n const targetState = target === 'tabbed' ? 'docked' : target;\n const newPanelInfo: PanelInfo = { id, title, component, state: targetState };\n const nextPanels = { ...prev.panels, [id]: newPanelInfo };\n\n if (target === 'floating') {\n maxZRef.current += 1;\n const cascaded = getCascadedPosition(favPos, prev.floating);\n\n const stickyRight = options?.stickyRight ?? entry?.defaultOptions?.defaultStickyRight ?? false;\n const stickyBottom = options?.stickyBottom ?? entry?.defaultOptions?.defaultStickyBottom ?? false;\n\n const viewW = Math.max(100, window.innerWidth || 1024);\n const viewH = Math.max(100, window.innerHeight || 768);\n const winW = typeof cascaded.width === 'string' ? parseFloat(cascaded.width) : cascaded.width;\n const winH = typeof cascaded.height === 'string' ? parseFloat(cascaded.height) : cascaded.height;\n\n let initialX = cascaded.x;\n let initialY = cascaded.y;\n\n const GAP = 10;\n if (stickyRight) {\n initialX = viewW - winW - GAP;\n }\n if (stickyBottom) {\n initialY = viewH - winH - GAP;\n }\n\n return {\n ...prev,\n floating: [...prev.floating, { ...cascaded, id, z: maxZRef.current, x: initialX, y: initialY, stickyRight, stickyBottom }],\n panels: nextPanels\n };\n } else {\n const firstLeaf = findFirstLeafId(prev.gridRoot) || 'group-left-top';\n return {\n ...prev,\n gridRoot: addPanelToLeaf(prev.gridRoot, firstLeaf, id),\n panels: nextPanels\n };\n }\n });\n }, [getCascadedPosition, bringToFront]);\n\n const closePanel = useCallback((id: string) => {\n setState(prev => {\n const panel = prev.panels[id];\n if (!panel) return prev;\n\n const registryEntry = PanelRegistry.get(panel.component);\n if (registryEntry?.defaultOptions?.canClose === false) {\n return prev;\n }\n\n delete closeGuardsRef.current[id];\n\n const nextPanels = { ...prev.panels };\n delete nextPanels[id];\n\n const cleanRoot = removePanelFromTree(prev.gridRoot, id);\n return {\n ...prev,\n gridRoot: cleanRoot || { type: 'leaf', id: 'group-default', panels: [], activePanelId: null },\n floating: prev.floating.filter(w => w.id !== id),\n minimized: prev.minimized.filter(m => m.id !== id),\n panels: nextPanels\n };\n });\n }, []);\n\n const registerCloseGuard = useCallback((id: string, guard: () => boolean | Promise<boolean>) => {\n closeGuardsRef.current[id] = guard;\n }, []);\n\n const unregisterCloseGuard = useCallback((id: string) => {\n delete closeGuardsRef.current[id];\n }, []);\n\n const setPanelDirty = useCallback((id: string, dirty: boolean) => {\n setState(prev => {\n const panel = prev.panels[id];\n if (!panel) return prev;\n return {\n ...prev,\n panels: {\n ...prev.panels,\n [id]: { ...panel, dirty }\n }\n };\n });\n }, []);\n\n const updatePanelTitle = useCallback((id: string, title: string | ContextMenuPredefinedMessage) => {\n setState(prev => {\n const panel = prev.panels[id];\n if (!panel) return prev;\n return {\n ...prev,\n panels: {\n ...prev.panels,\n [id]: { ...panel, title }\n }\n };\n });\n }, []);\n\n const resolvePendingClose = useCallback((discard: boolean) => {\n setState(prev => {\n if (!prev.pendingClose) return prev;\n prev.pendingClose.resolve(discard);\n return { ...prev, pendingClose: null };\n });\n }, []);\n\n const requestClosePanel = useCallback(async (id: string, options?: { force?: boolean }) => {\n if (options?.force) {\n closePanel(id);\n return;\n }\n\n // 1. Check custom close guard\n const guard = closeGuardsRef.current[id];\n if (guard) {\n const canClose = await guard();\n if (!canClose) return;\n }\n\n // 2. Check automatic dirty flag\n const panel = stateRef.current.panels[id];\n if (panel?.dirty) {\n const discard = await new Promise<boolean>(resolve => {\n setState(prev => ({\n ...prev,\n pendingClose: { id, resolve }\n }));\n });\n if (!discard) return;\n }\n\n closePanel(id);\n }, [closePanel]);\n\n const minimizePanel = useCallback((id: string) => {\n setState(prev => {\n const panel = prev.panels[id];\n if (!panel || panel.state === 'minimized') return prev;\n\n const registryEntry = PanelRegistry.get(panel.component);\n if (registryEntry?.defaultOptions?.canMinimize === false) {\n return prev;\n }\n\n let lastFloatingRect: any = undefined;\n let lastLeafId: any = undefined;\n\n if (panel.state === 'floating') {\n const win = prev.floating.find(w => w.id === id);\n if (win) {\n lastFloatingRect = { \n x: win.x, \n y: win.y, \n width: win.width, \n height: win.height,\n stickyRight: win.stickyRight,\n stickyBottom: win.stickyBottom\n };\n }\n } else if (panel.state === 'docked') {\n const findLeafForPanel = (node: LayoutNode): string | null => {\n if (node.type === 'leaf') {\n return node.panels.includes(id) ? node.id : null;\n } else {\n for (const child of node.children) {\n const res = findLeafForPanel(child);\n if (res) return res;\n }\n return null;\n }\n };\n lastLeafId = findLeafForPanel(prev.gridRoot);\n }\n\n const cleanRoot = removePanelFromTree(prev.gridRoot, id);\n return {\n ...prev,\n gridRoot: cleanRoot || { type: 'leaf', id: 'group-default', panels: [], activePanelId: null },\n floating: prev.floating.filter(w => w.id !== id),\n minimized: [...prev.minimized, { id, title: panel.title, component: panel.component }],\n panels: {\n ...prev.panels,\n [id]: {\n ...panel,\n state: 'minimized',\n previousState: panel.state,\n lastFloatingRect,\n lastLeafId\n }\n }\n };\n });\n }, []);\n\n const restorePanel = useCallback((id: string) => {\n setState(prev => {\n const panel = prev.panels[id];\n if (!panel || panel.state !== 'minimized') return prev;\n\n const nextMinimized = prev.minimized.filter(m => m.id !== id);\n const prevState = panel.previousState || 'docked';\n\n if (prevState === 'floating') {\n maxZRef.current += 1;\n const entry = PanelRegistry.get(panel.component);\n const favPos = panel.lastFloatingRect || entry?.defaultOptions?.favoritePosition || { x: 300, y: 150, width: 450, height: 350 };\n const cascaded = getCascadedPosition(favPos, prev.floating);\n return {\n ...prev,\n minimized: nextMinimized,\n floating: [\n ...prev.floating, \n { \n ...cascaded, \n id, \n z: maxZRef.current,\n stickyRight: !!panel.lastFloatingRect?.stickyRight,\n stickyBottom: !!panel.lastFloatingRect?.stickyBottom\n }\n ],\n panels: { ...prev.panels, [id]: { ...panel, state: 'floating' } }\n };\n } else {\n const leafExists = (node: LayoutNode, targetId: string): boolean => {\n if (node.type === 'leaf') return node.id === targetId;\n return node.children.some(c => leafExists(c, targetId));\n };\n\n const parentLeafExists = panel.lastLeafId && leafExists(prev.gridRoot, panel.lastLeafId);\n const entry = PanelRegistry.get(panel.component);\n const canDrag = entry?.defaultOptions?.canDrag !== false;\n\n if (parentLeafExists) {\n return {\n ...prev,\n minimized: nextMinimized,\n gridRoot: addPanelToLeaf(prev.gridRoot, panel.lastLeafId!, id),\n panels: { ...prev.panels, [id]: { ...panel, state: 'docked' } }\n };\n } else if (canDrag) {\n // Leaf group ceased to exist: float it instead if floatable!\n maxZRef.current += 1;\n const favPos = panel.lastFloatingRect || entry?.defaultOptions?.favoritePosition || { x: 300, y: 150, width: 450, height: 350 };\n const cascaded = getCascadedPosition(favPos, prev.floating);\n return {\n ...prev,\n minimized: nextMinimized,\n floating: [\n ...prev.floating, \n { \n ...cascaded, \n id, \n z: maxZRef.current,\n stickyRight: !!panel.lastFloatingRect?.stickyRight,\n stickyBottom: !!panel.lastFloatingRect?.stickyBottom\n }\n ],\n panels: { ...prev.panels, [id]: { ...panel, state: 'floating' } }\n };\n } else {\n // Leaf group ceased to exist but not floatable: dock into fallback leaf group\n const targetLeafId = findFirstLeafId(prev.gridRoot) || 'group-left-top';\n return {\n ...prev,\n minimized: nextMinimized,\n gridRoot: addPanelToLeaf(prev.gridRoot, targetLeafId, id),\n panels: { ...prev.panels, [id]: { ...panel, state: 'docked' } }\n };\n }\n }\n });\n }, [getCascadedPosition]);\n\n const floatPanel = useCallback((id: string, rect?: { x: number; y: number; width: number; height: number }) => {\n setState(prev => {\n const panel = prev.panels[id];\n if (!panel) return prev;\n\n const registryEntry = PanelRegistry.get(panel.component);\n if (registryEntry?.defaultOptions?.canDrag === false) {\n return prev;\n }\n\n const entry = PanelRegistry.get(panel.component);\n const favPos = rect || entry?.defaultOptions?.favoritePosition || { x: 300, y: 150, width: 450, height: 350 };\n\n const cleanRoot = removePanelFromTree(prev.gridRoot, id);\n maxZRef.current += 1;\n const cascaded = getCascadedPosition(favPos, prev.floating);\n\n return {\n ...prev,\n gridRoot: cleanRoot || { type: 'leaf', id: 'group-default', panels: [], activePanelId: null },\n floating: [...prev.floating, { ...cascaded, id, z: maxZRef.current }],\n panels: {\n ...prev.panels,\n [id]: { ...panel, state: 'floating' }\n }\n };\n });\n }, [getCascadedPosition]);\n\n const dockPanel = useCallback((id: string, targetLeafId?: string) => {\n setState(prev => {\n const panel = prev.panels[id];\n if (!panel) return prev;\n\n const nextFloating = prev.floating.filter(w => w.id !== id);\n const cleanRoot = removePanelFromTree(prev.gridRoot, id);\n const leafId = targetLeafId || findFirstLeafId(cleanRoot || prev.gridRoot) || 'group-left-top';\n\n return {\n ...prev,\n gridRoot: addPanelToLeaf(cleanRoot || prev.gridRoot, leafId, id),\n floating: nextFloating,\n panels: {\n ...prev.panels,\n [id]: { ...panel, state: 'docked' }\n }\n };\n });\n }, []);\n\n // Helper to split a layout leaf node into a branch (for drag split targets)\n const splitLeafInTree = (\n node: LayoutNode,\n leafId: string,\n panelId: string,\n position: 'left' | 'right' | 'top' | 'bottom'\n ): LayoutNode => {\n if (node.type === 'leaf') {\n if (node.id === leafId) {\n const newLeaf: LayoutLeafNode = {\n type: 'leaf',\n id: `group-split-${Date.now()}-${Math.floor(Math.random() * 1000)}`,\n panels: [panelId],\n activePanelId: panelId\n };\n const orientation: SplitOrientation = (position === 'left' || position === 'right') ? 'horizontal' : 'vertical';\n const children = (position === 'left' || position === 'top') ? [newLeaf, node] : [node, newLeaf];\n return {\n type: 'branch',\n orientation,\n sizes: [0.5, 0.5],\n children\n };\n }\n return node;\n } else {\n return {\n ...node,\n children: node.children.map(c => splitLeafInTree(c, leafId, panelId, position))\n };\n }\n };\n\n const setDraggedPanelId = useCallback((id: string | null) => {\n setState(prev => ({ ...prev, draggedPanelId: id }));\n }, []);\n\n const dockPanelToGroup = useCallback((id: string, targetLeafId: string, position: 'left' | 'right' | 'top' | 'bottom' | 'center') => {\n setState(prev => {\n const panel = prev.panels[id];\n if (!panel) return prev;\n\n const nextFloating = prev.floating.filter(w => w.id !== id);\n const cleanRoot = removePanelFromTree(prev.gridRoot, id);\n\n let newRoot: LayoutNode;\n if (position === 'center') {\n newRoot = addPanelToLeaf(cleanRoot || prev.gridRoot, targetLeafId, id);\n } else {\n newRoot = splitLeafInTree(cleanRoot || prev.gridRoot, targetLeafId, id, position);\n }\n\n return {\n ...prev,\n gridRoot: newRoot,\n floating: nextFloating,\n panels: {\n ...prev.panels,\n [id]: { ...panel, state: 'docked' }\n },\n draggedPanelId: null\n };\n });\n }, []);\n\n const dockPanelToWorkspaceEdge = useCallback((id: string, position: 'left' | 'right' | 'top' | 'bottom') => {\n setState(prev => {\n const panel = prev.panels[id];\n if (!panel) return prev;\n\n const nextFloating = prev.floating.filter(w => w.id !== id);\n const cleanRoot = removePanelFromTree(prev.gridRoot, id);\n\n const newLeaf: LayoutLeafNode = {\n type: 'leaf',\n id: `group-edge-${Date.now()}-${Math.floor(Math.random() * 1000)}`,\n panels: [id],\n activePanelId: id\n };\n\n const orientation: SplitOrientation = (position === 'left' || position === 'right') ? 'horizontal' : 'vertical';\n const children = (position === 'left' || position === 'top')\n ? [newLeaf, cleanRoot || prev.gridRoot]\n : [cleanRoot || prev.gridRoot, newLeaf];\n\n const newRoot: LayoutNode = {\n type: 'branch',\n orientation,\n sizes: (position === 'left' || position === 'top') ? [0.3, 0.7] : [0.7, 0.3],\n children\n };\n\n return {\n ...prev,\n gridRoot: newRoot,\n floating: nextFloating,\n panels: {\n ...prev.panels,\n [id]: { ...panel, state: 'docked' }\n },\n draggedPanelId: null\n };\n });\n }, []);\n\n const movePanelOrder = useCallback((panelId: string, targetLeafId: string, targetIndex: number) => {\n setState(prev => {\n const panel = prev.panels[panelId];\n if (!panel) return prev;\n\n // 1. Remove panel from its current group in the layout tree\n const cleanRoot = removePanelFromTree(prev.gridRoot, panelId);\n\n // 2. Insert panel at specific index in target leaf ID\n const insertInLeaf = (node: LayoutNode): LayoutNode => {\n if (node.type === 'leaf') {\n if (node.id === targetLeafId) {\n const remaining = node.panels.filter(p => p !== panelId);\n const index = Math.max(0, Math.min(targetIndex, remaining.length));\n const newPanels = [...remaining];\n newPanels.splice(index, 0, panelId);\n return {\n ...node,\n panels: newPanels,\n activePanelId: panelId\n };\n }\n return node;\n } else {\n return {\n ...node,\n children: node.children.map(insertInLeaf)\n };\n }\n };\n\n const newRoot = insertInLeaf(cleanRoot || prev.gridRoot);\n const nextFloating = prev.floating.filter(w => w.id !== panelId);\n\n return {\n ...prev,\n gridRoot: newRoot,\n floating: nextFloating,\n panels: {\n ...prev.panels,\n [panelId]: { ...panel, state: 'docked' }\n },\n draggedPanelId: null\n };\n });\n }, []);\n\n const closeLeafGroup = useCallback((leafId: string) => {\n setState(prev => {\n const removeLeafFromTree = (node: LayoutNode): LayoutNode | null => {\n if (node.type === 'leaf') {\n if (node.id === leafId && node.canClose !== false) {\n return null;\n }\n return node;\n } else {\n const children = node.children\n .map(c => removeLeafFromTree(c))\n .filter((c): c is LayoutNode => c !== null);\n\n if (children.length === 0) return null;\n if (children.length === 1) return children[0];\n\n // Re-normalize sizes\n const sizes = node.sizes.slice(0, children.length);\n const sum = sizes.reduce((a, b) => a + b, 0);\n return {\n ...node,\n children,\n sizes: sizes.map(s => s / sum)\n };\n }\n };\n\n const newRoot = removeLeafFromTree(prev.gridRoot);\n return {\n ...prev,\n gridRoot: newRoot || { type: 'leaf', id: 'group-default', panels: [], activePanelId: null }\n };\n });\n }, []);\n\n const maximizePanel = useCallback((id: string) => {\n setState(prev => ({\n ...prev,\n floating: prev.floating.map(w => w.id === id ? { ...w, maximized: !w.maximized } : w)\n }));\n }, []);\n\n const updateSplitSizes = useCallback((path: number[], sizes: number[]) => {\n const updateInTree = (node: LayoutNode, depth: number): LayoutNode => {\n if (node.type === 'leaf') return node;\n if (depth === path.length) {\n return { ...node, sizes };\n }\n const idx = path[depth];\n const children = node.children.map((c, i) => i === idx ? updateInTree(c, depth + 1) : c);\n return { ...node, children };\n };\n\n setState(prev => ({\n ...prev,\n gridRoot: updateInTree(prev.gridRoot, 0)\n }));\n }, []);\n\n const updateFloatingPosition = useCallback((id: string, updates: Partial<Pick<FloatingWindow, 'x' | 'y' | 'width' | 'height' | 'stickyRight' | 'stickyBottom'>>) => {\n setState(prev => ({\n ...prev,\n floating: prev.floating.map(w => w.id === id ? { ...w, ...updates } : w)\n }));\n }, []);\n\n const saveLayout = useCallback(() => {\n return JSON.stringify({\n gridRoot: state.gridRoot,\n floating: state.floating,\n minimized: state.minimized,\n panels: state.panels\n });\n }, [state]);\n\n const loadLayout = useCallback((layoutJson: string) => {\n try {\n const parsed = JSON.parse(layoutJson);\n if (parsed.gridRoot && parsed.floating && parsed.minimized && parsed.panels) {\n setState({\n gridRoot: parsed.gridRoot,\n floating: parsed.floating,\n minimized: parsed.minimized,\n panels: parsed.panels,\n draggedPanelId: null,\n pendingClose: null\n });\n }\n } catch (e) {\n console.error('Failed to parse layout configuration:', e);\n }\n }, []);\n\n const actions = useMemo<WindowActions>(() => ({\n openPanel,\n closePanel,\n minimizePanel,\n restorePanel,\n floatPanel,\n dockPanel,\n maximizePanel,\n updateSplitSizes,\n updateFloatingPosition,\n bringToFront,\n saveLayout,\n loadLayout,\n publish,\n subscribe,\n setDraggedPanelId,\n dockPanelToGroup,\n movePanelOrder,\n closeLeafGroup,\n registerCloseGuard,\n unregisterCloseGuard,\n setPanelDirty,\n updatePanelTitle,\n requestClosePanel,\n resolvePendingClose,\n dockPanelToWorkspaceEdge\n }), [\n openPanel,\n closePanel,\n minimizePanel,\n restorePanel,\n floatPanel,\n dockPanel,\n maximizePanel,\n updateSplitSizes,\n updateFloatingPosition,\n bringToFront,\n saveLayout,\n loadLayout,\n publish,\n subscribe,\n setDraggedPanelId,\n dockPanelToGroup,\n movePanelOrder,\n closeLeafGroup,\n registerCloseGuard,\n unregisterCloseGuard,\n setPanelDirty,\n updatePanelTitle,\n requestClosePanel,\n resolvePendingClose,\n dockPanelToWorkspaceEdge\n ]);\n\n const defaultFormatMessage: MessageFormatter = (msg) => {\n let text = msg.defaultMessage || msg.id;\n if (msg.values) {\n Object.entries(msg.values).forEach(([key, value]) => {\n text = text.replace(`{${key}}`, String(value));\n });\n }\n return text;\n };\n\n const styleClasses = useMemo(() => ({\n modalClass,\n modalBodyClass,\n sidePanelClass,\n sidePanelBodyClass,\n windowClass,\n windowBodyClass\n }), [modalClass, modalBodyClass, sidePanelClass, sidePanelBodyClass, windowClass, windowBodyClass]);\n\n return (\n <StyleClassContext.Provider value={styleClasses}>\n <WindowStateContext.Provider value={state}>\n <WindowActionsContext.Provider value={actions}>\n <WindowI18nContext.Provider value={formatMessage || defaultFormatMessage}>\n <WindowPredefinedMessagesContext.Provider value={mergedMessages}>\n {children}\n </WindowPredefinedMessagesContext.Provider>\n </WindowI18nContext.Provider>\n </WindowActionsContext.Provider>\n </WindowStateContext.Provider>\n </StyleClassContext.Provider>\n );\n};\n\nexport const useWindowManagerState = () => {\n const ctx = useContext(WindowStateContext);\n if (!ctx) throw new Error('useWindowManagerState must be used within WindowManagerProvider');\n return ctx;\n};\n\nexport const useWindowManagerActions = () => {\n const ctx = useContext(WindowActionsContext);\n if (!ctx) throw new Error('useWindowManagerActions must be used within WindowManagerProvider');\n return ctx;\n};\n\nexport const useFormatMessage = () => {\n const formatter = useContext(WindowI18nContext);\n return formatter || ((msg) => {\n let text = msg.defaultMessage || msg.id;\n if (msg.values) {\n Object.entries(msg.values).forEach(([key, value]) => {\n text = text.replace(`{${key}}`, String(value));\n });\n }\n return text;\n });\n};\n\nexport const formatLabel = (\n label: string | ContextMenuPredefinedMessage | undefined,\n formatter: MessageFormatter\n): string => {\n if (!label) return '';\n if (typeof label === 'string') return label;\n return formatter(label);\n};\n\n// Panel level communication hook\nexport const usePanelContext = () => {\n const { publish, subscribe } = useWindowManagerActions();\n return { publish, subscribe };\n};\n\nexport const usePredefinedMessages = () => {\n return useContext(WindowPredefinedMessagesContext);\n};\n","import type { ComponentType } from 'react';\n\nexport interface PanelRegistryEntry {\n Component: ComponentType<any>;\n defaultOptions?: {\n title?: string;\n icon?: React.ReactNode;\n initialTarget?: 'floating' | 'docked' | 'tabbed';\n favoritePosition?: { x: number | string; y: number | string; width: number | string; height: number | string };\n canDrag?: boolean;\n canMinimize?: boolean;\n canClose?: boolean;\n defaultStickyRight?: boolean;\n defaultStickyBottom?: boolean;\n disableLivePreview?: boolean;\n };\n}\n\nclass PanelRegistryClass {\n private registry = new Map<string, PanelRegistryEntry>();\n\n register<P extends object>(\n id: string,\n Component: ComponentType<P>,\n defaultOptions?: PanelRegistryEntry['defaultOptions']\n ): void {\n this.registry.set(id, {\n Component: Component as ComponentType<any>,\n defaultOptions\n });\n }\n\n get(id: string): PanelRegistryEntry | undefined {\n return this.registry.get(id);\n }\n\n getRegisteredIds(): string[] {\n return Array.from(this.registry.keys());\n }\n}\n\nexport const PanelRegistry = new PanelRegistryClass();\nexport default PanelRegistry;\n","/**\n * Default English messages for every action exposed by Dockable Desktop.\n *\n * Each value's `id` is the react-intl message ID that the consumer should\n * define in their IntlProvider messages table. The `defaultMessage` is used\n * as a fallback when no external formatter is provided.\n *\n * Pass a partial or full override to <WindowManagerProvider predefinedMessages={…} />\n * to customise labels without replacing the whole table.\n */\nexport const defaultPredefinedMessages = {\n floatWindow: { id: 'dockable-desktop-floatWindow', defaultMessage: 'Float Window' },\n minimizePanel: { id: 'dockable-desktop-minimizePanel', defaultMessage: 'Minimize Panel' },\n closeTab: { id: 'dockable-desktop-closeTab', defaultMessage: 'Close Tab' },\n restorePanel: { id: 'dockable-desktop-restorePanel', defaultMessage: 'Restore Panel' },\n maximizePanel: { id: 'dockable-desktop-maximizePanel', defaultMessage: 'Maximize Panel' },\n closePanel: { id: 'dockable-desktop-closePanel', defaultMessage: 'Close Panel' },\n dockWindow: { id: 'dockable-desktop-dockWindow', defaultMessage: 'Dock Window' },\n minimize: { id: 'dockable-desktop-minimize', defaultMessage: 'Minimize' },\n maximize: { id: 'dockable-desktop-maximize', defaultMessage: 'Maximize' },\n restoreSize: { id: 'dockable-desktop-restoreSize', defaultMessage: 'Restore Size' },\n close: { id: 'dockable-desktop-close', defaultMessage: 'Close' },\n closeEmptyGroup: { id: 'dockable-desktop-closeEmptyGroup', defaultMessage: 'Close empty split group' },\n anchorToRightEdge: { id: 'dockable-desktop-anchorToRightEdge', defaultMessage: 'Anchor to Right Edge' },\n anchorToBottomEdge: { id: 'dockable-desktop-anchorToBottomEdge', defaultMessage: 'Anchor to Bottom Edge' },\n windowAnchoringOptions: { id: 'dockable-desktop-windowAnchoringOptions', defaultMessage: 'Window Anchoring Options' },\n} as const;\n\n/**\n * Union of every key in `defaultPredefinedMessages`.\n *\n * Import this type in your i18n message tables to get a compile-time\n * guarantee that all keys are present and no typos exist:\n *\n * import type { PredefinedMessageKey } from 'react-dockable-desktop';\n *\n * const myMessages: Record<PredefinedMessageKey, string> = { ... };\n */\nexport type PredefinedMessageKey = keyof typeof defaultPredefinedMessages;\n","import { createContext, useContext } from 'react';\n\nexport interface CloseOptions {\n force?: boolean;\n}\n\nexport type ContainerType = 'left-panel' | 'right-panel' | 'modal' | 'dockable-panel' | 'standalone';\n\nexport interface FormContainerContract {\n requestClose: (options?: CloseOptions) => void;\n setDirty: (dirty: boolean) => void;\n onCloseRequested: (handler: () => boolean | Promise<boolean>) => (() => void);\n setTitle: (title: string | { id: string; defaultMessage: string; values?: Record<string, any> }) => void;\n setIcon?: (icon: React.ReactNode) => void;\n containerType?: ContainerType;\n instanceId: string;\n onClose?: (handler: () => void) => () => void;\n onMinimize?: (handler: () => void) => () => void;\n onRestore?: (handler: () => void) => () => void;\n onResize?: (handler: (width: number, height: number) => void) => () => void;\n}\n\nconst defaultContract: FormContainerContract = {\n requestClose: () => {\n console.warn('FormContainerContract: requestClose called but no container is present');\n },\n setDirty: () => {},\n onCloseRequested: () => () => {},\n setTitle: () => {},\n setIcon: () => {},\n containerType: 'standalone',\n instanceId: 'standalone',\n onClose: () => () => {},\n onMinimize: () => () => {},\n onRestore: () => () => {},\n onResize: () => () => {},\n};\n\nexport const FormContainerContext = createContext<FormContainerContract>(defaultContract);\nexport const FormContainerProvider = FormContainerContext.Provider;\n\nexport const useFormContainer = (): FormContainerContract => {\n return useContext(FormContainerContext);\n};\n\n","import React, { createContext, useContext, useState, useCallback, useMemo, useRef } from 'react';\nimport type { ComponentType, ReactNode } from 'react';\n\nexport type PanelInstanceId = string;\n\nexport interface PanelTitleDescriptor {\n id: string;\n defaultMessage?: string;\n values?: Record<string, string | number>;\n}\n\nexport type PanelTitle = string | PanelTitleDescriptor;\n\nexport interface SidePanelOptions {\n title?: PanelTitle;\n icon?: React.ReactNode;\n width?: number | string;\n}\n\nexport interface ModalOptions {\n title?: PanelTitle;\n icon?: React.ReactNode;\n size?: 'small' | 'medium' | 'large' | 'fullscreen' | 'auto';\n closable?: boolean;\n}\n\nexport interface PanelInstance {\n id: PanelInstanceId;\n Component: ComponentType<any>;\n props: Record<string, any>;\n containerType: 'left-panel' | 'right-panel' | 'modal';\n options: SidePanelOptions | ModalOptions;\n dirty?: boolean;\n}\n\nexport interface PanelState {\n leftPanel: PanelInstance | null;\n rightPanel: PanelInstance | null;\n modals: PanelInstance[];\n}\n\nexport interface PanelActions {\n openLeftPanel: <P extends object>(Component: ComponentType<P>, props: P, options?: SidePanelOptions) => Promise<PanelInstanceId | null>;\n openRightPanel: <P extends object>(Component: ComponentType<P>, props: P, options?: SidePanelOptions) => Promise<PanelInstanceId | null>;\n openModal: <P extends object>(Component: ComponentType<P>, props: P, options?: ModalOptions) => PanelInstanceId;\n close: (id: PanelInstanceId) => void;\n closeAll: () => void;\n closeAllModals: () => void;\n getInstance: (id: PanelInstanceId) => PanelInstance | undefined;\n updateInstance: (id: PanelInstanceId, updates: Partial<Pick<PanelInstance, 'props' | 'options' | 'dirty'>>) => void;\n setDirty: (id: PanelInstanceId, dirty: boolean) => void;\n registerCloseHandler: (id: PanelInstanceId, handler: () => Promise<boolean>) => void;\n unregisterCloseHandler: (id: PanelInstanceId) => void;\n}\n\nlet idCounter = 0;\nconst generateId = (): PanelInstanceId => `panel-${++idCounter}-${Date.now()}`;\n\nconst closeHandlers = new Map<PanelInstanceId, () => Promise<boolean>>();\n\nconst initialState: PanelState = {\n leftPanel: null,\n rightPanel: null,\n modals: [],\n};\n\nconst PanelStateContext = createContext<PanelState | null>(null);\nconst PanelActionsContext = createContext<PanelActions | null>(null);\n\nexport const PanelProvider: React.FC<{ children: ReactNode }> = ({ children }) => {\n const [state, setState] = useState<PanelState>(initialState);\n\n const stateRef = useRef(state);\n stateRef.current = state;\n\n const registerCloseHandler = useCallback((id: PanelInstanceId, handler: () => Promise<boolean>) => {\n closeHandlers.set(id, handler);\n }, []);\n\n const unregisterCloseHandler = useCallback((id: PanelInstanceId) => {\n closeHandlers.delete(id);\n }, []);\n\n const openLeftPanel = useCallback(\n async <P extends object>(\n Component: ComponentType<P>,\n props: P,\n options: SidePanelOptions = {}\n ): Promise<PanelInstanceId | null> => {\n const currentPanel = stateRef.current.leftPanel;\n if (currentPanel) {\n const handler = closeHandlers.get(currentPanel.id);\n if (handler) {\n const canClose = await handler();\n if (!canClose) return null;\n }\n }\n\n const id = generateId();\n const instance: PanelInstance = {\n id,\n Component: Component as ComponentType<any>,\n props: props as Record<string, any>,\n containerType: 'left-panel',\n options,\n };\n setState(s => ({ ...s, leftPanel: instance }));\n return id;\n },\n []\n );\n\n const openRightPanel = useCallback(\n async <P extends object>(\n Component: ComponentType<P>,\n props: P,\n options: SidePanelOptions = {}\n ): Promise<PanelInstanceId | null> => {\n const currentPanel = stateRef.current.rightPanel;\n if (currentPanel) {\n const handler = closeHandlers.get(currentPanel.id);\n if (handler) {\n const canClose = await handler();\n if (!canClose) return null;\n }\n }\n\n const id = generateId();\n const instance: PanelInstance = {\n id,\n Component: Component as ComponentType<any>,\n props: props as Record<string, any>,\n containerType: 'right-panel',\n options,\n };\n setState(s => ({ ...s, rightPanel: instance }));\n return id;\n },\n []\n );\n\n const openModal = useCallback(\n <P extends object>(\n Component: ComponentType<P>,\n props: P,\n options: ModalOptions = {}\n ): PanelInstanceId => {\n const id = generateId();\n const formTitle = (props as any).title;\n \n const modalOptions: ModalOptions = {\n ...options,\n title: options.title || formTitle || 'Confirmation',\n };\n\n const instance: PanelInstance = {\n id,\n Component: Component as ComponentType<any>,\n props: props as Record<string, any>,\n containerType: 'modal',\n options: modalOptions,\n };\n setState(s => ({ ...s, modals: [...s.modals, instance] }));\n return id;\n },\n []\n );\n\n const close = useCallback((id: PanelInstanceId) => {\n setState(s => ({\n leftPanel: s.leftPanel?.id === id ? null : s.leftPanel,\n rightPanel: s.rightPanel?.id === id ? null : s.rightPanel,\n modals: s.modals.filter(m => m.id !== id),\n }));\n }, []);\n\n const closeAll = useCallback(() => {\n setState(initialState);\n }, []);\n\n const closeAllModals = useCallback(() => {\n setState(s => ({ ...s, modals: [] }));\n }, []);\n\n const getInstance = useCallback(\n (id: PanelInstanceId): PanelInstance | undefined => {\n if (state.leftPanel?.id === id) return state.leftPanel;\n if (state.rightPanel?.id === id) return state.rightPanel;\n return state.modals.find(m => m.id === id);\n },\n [state]\n );\n\n const updateInstance = useCallback(\n (\n id: PanelInstanceId,\n updates: Partial<Pick<PanelInstance, 'props' | 'options' | 'dirty'>>\n ) => {\n setState(s => ({\n leftPanel: s.leftPanel?.id === id ? { ...s.leftPanel, ...updates } : s.leftPanel,\n rightPanel: s.rightPanel?.id === id ? { ...s.rightPanel, ...updates } : s.rightPanel,\n modals: s.modals.map(m => m.id === id ? { ...m, ...updates } : m),\n }));\n },\n []\n );\n\n const setDirty = useCallback((id: PanelInstanceId, dirty: boolean) => {\n updateInstance(id, { dirty });\n }, [updateInstance]);\n\n const actions = useMemo<PanelActions>(\n () => ({\n openLeftPanel,\n openRightPanel,\n openModal,\n close,\n closeAll,\n closeAllModals,\n getInstance,\n updateInstance,\n setDirty,\n registerCloseHandler,\n unregisterCloseHandler,\n }),\n [\n openLeftPanel,\n openRightPanel,\n openModal,\n close,\n closeAll,\n closeAllModals,\n getInstance,\n updateInstance,\n setDirty,\n registerCloseHandler,\n unregisterCloseHandler,\n ]\n );\n\n return (\n <PanelStateContext.Provider value={state}>\n <PanelActionsContext.Provider value={actions}>\n {children}\n </PanelActionsContext.Provider>\n </PanelStateContext.Provider>\n );\n};\n\nexport const usePanelState = (): PanelState => {\n const ctx = useContext(PanelStateContext);\n if (!ctx) throw new Error('usePanelState must be used within PanelProvider');\n return ctx;\n};\n\nexport const usePanelActions = (): PanelActions => {\n const ctx = useContext(PanelActionsContext);\n if (!ctx) throw new Error('usePanelActions must be used within PanelProvider');\n return ctx;\n};\n","import React, { useCallback, useRef, useEffect, useState, useMemo } from 'react';\nimport { usePanelState, usePanelActions } from './PanelProviderContext';\nimport { FormContainerProvider, type FormContainerContract, type CloseOptions } from './FormContainerContext';\nimport type { PanelInstance, ModalOptions, PanelTitle } from './PanelProviderContext';\nimport { useFormatMessage, formatLabel, useStyleClasses } from './WindowManagerContext';\nimport { DirtyWarningOverlay } from './DirtyWarningOverlay';\n\ninterface ModalRendererProps {\n modal: PanelInstance;\n index: number;\n isTopmost: boolean;\n}\n\nconst ModalRenderer: React.FC<ModalRendererProps> = ({ modal, index, isTopmost }) => {\n const { close, updateInstance, setDirty } = usePanelActions();\n const formatMessage = useFormatMessage();\n const { modalClass, modalBodyClass } = useStyleClasses();\n const closeHandlerRef = useRef<(() => boolean | Promise<boolean>) | null>(null);\n\n const [showDirtyWarning, setShowDirtyWarning] = useState(false);\n const dirtyResolverRef = useRef<((discard: boolean) => void) | null>(null);\n\n const { id, Component, props, options, dirty } = modal;\n const modalOptions = options as ModalOptions;\n\n const [icon, setIconState] = useState<React.ReactNode>(modalOptions.icon || null);\n\n const optionsRef = useRef(modalOptions);\n optionsRef.current = modalOptions;\n\n const promptDirtyWarning = useCallback((): Promise<boolean> => {\n return new Promise((resolve) => {\n dirtyResolverRef.current = resolve;\n setShowDirtyWarning(true);\n });\n }, []);\n\n const handleDirtyDiscard = useCallback(() => {\n dirtyResolverRef.current?.(true);\n dirtyResolverRef.current = null;\n setShowDirtyWarning(false);\n }, []);\n\n const handleDirtyCancel = useCallback(() => {\n dirtyResolverRef.current?.(false);\n dirtyResolverRef.current = null;\n setShowDirtyWarning(false);\n }, []);\n\n const handleClose = useCallback(async (options?: CloseOptions) => {\n if (options?.force) {\n close(id);\n return;\n }\n\n if (closeHandlerRef.current) {\n const canClose = await closeHandlerRef.current();\n if (!canClose) return;\n close(id);\n return;\n }\n\n if (dirty) {\n const shouldDiscard = await promptDirtyWarning();\n if (!shouldDiscard) return;\n }\n\n close(id);\n }, [close, id, dirty, promptDirtyWarning]);\n\n const handleSetDirty = useCallback((dirty: boolean) => setDirty(id, dirty), [setDirty, id]);\n const handleSetTitle = useCallback((title: PanelTitle) => updateInstance(id, { options: { ...optionsRef.current, title } }), [updateInstance, id]);\n const handleSetIcon = useCallback((newIcon: React.ReactNode) => setIconState(newIcon), []);\n const handleOnCloseRequested = useCallback((handler: () => boolean | Promise<boolean>) => {\n closeHandlerRef.current = handler;\n return () => { closeHandlerRef.current = null; };\n }, []);\n\n const contract: FormContainerContract = useMemo(() => ({\n requestClose: handleClose,\n setDirty: handleSetDirty,\n setTitle: handleSetTitle,\n setIcon: handleSetIcon,\n onCloseRequested: handleOnCloseRequested,\n containerType: 'modal',\n instanceId: id,\n }), [handleClose, handleSetDirty, handleSetTitle, handleSetIcon, handleOnCloseRequested, id]);\n\n const baseTitle = formatLabel(modalOptions.title, formatMessage);\n const displayTitle = dirty ? `${baseTitle} *` : baseTitle;\n\n const sizeClass = modalOptions.size ? `v2-modal-size-${modalOptions.size}` : 'v2-modal-size-auto';\n const showCloseButton = modalOptions.closable !== false;\n\n useEffect(() => {\n if (!isTopmost || !showCloseButton || showDirtyWarning) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.stopPropagation();\n handleClose();\n }\n };\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [handleClose, showCloseButton, isTopmost, showDirtyWarning]);\n\n const baseZIndex = 10000;\n const modalZIndex = baseZIndex + (index * 10);\n const dirtyWarningZIndex = modalZIndex + 5;\n\n return (\n <>\n <div className=\"v2-modal-overlay\" style={{ zIndex: modalZIndex }}>\n <div className=\"v2-modal-curtain\" onClick={showCloseButton ? () => handleClose() : undefined} />\n <div className={`v2-modal-window ${sizeClass} ${modalClass ?? ''}`}>\n <div className=\"v2-modal-header\">\n {icon && <div className=\"v2-modal-icon\">{icon}</div>}\n <h4 className=\"v2-modal-title\">{displayTitle}</h4>\n {showCloseButton && (\n <button\n className=\"v2-modal-close-button\"\n onClick={() => handleClose()}\n title=\"Close\"\n type=\"button\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\">\n <path d=\"M18 6L6 18M6 6l12 12\" />\n </svg>\n </button>\n )}\n </div>\n <div className={`v2-modal-body ${modalBodyClass ?? ''}`}>\n <FormContainerProvider value={contract}>\n <Component {...props} panelId={id} />\n </FormContainerProvider>\n </div>\n </div>\n </div>\n\n {showDirtyWarning && (\n <DirtyWarningOverlay\n zIndex={dirtyWarningZIndex}\n onDiscard={handleDirtyDiscard}\n onCancel={handleDirtyCancel}\n />\n )}\n </>\n );\n};\n\nexport const ModalStackRenderer: React.FC = () => {\n const { modals } = usePanelState();\n\n if (modals.length === 0) return null;\n\n return (\n <>\n {modals.map((modal, index) => (\n <ModalRenderer\n key={modal.id}\n modal={modal}\n index={index}\n isTopmost={index === modals.length - 1}\n />\n ))}\n </>\n );\n};\n\nexport default ModalStackRenderer;\n","import React, { useEffect, useRef } from 'react';\nimport { useFormatMessage } from './WindowManagerContext';\n\nexport interface DirtyWarningOverlayProps {\n zIndex: number;\n onDiscard: () => void;\n onCancel: () => void;\n message?: string;\n title?: string;\n}\n\nexport const DirtyWarningOverlay: React.FC<DirtyWarningOverlayProps> = ({\n zIndex,\n onDiscard,\n onCancel,\n message,\n title,\n}) => {\n const cancelButtonRef = useRef<HTMLButtonElement>(null);\n\n useEffect(() => {\n const timer = setTimeout(() => {\n cancelButtonRef.current?.focus();\n }, 50);\n return () => clearTimeout(timer);\n }, []);\n\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.stopPropagation();\n e.preventDefault();\n onCancel();\n }\n };\n document.addEventListener('keydown', handleKeyDown, true);\n return () => document.removeEventListener('keydown', handleKeyDown, true);\n }, [onCancel]);\n\n const resolvedTitle = title || 'Unsaved Changes';\n const resolvedMessage = message || 'You have unsaved changes that will be lost.';\n const question = 'Do you want to discard your changes and close?';\n\n return (\n <div className=\"close-warning-overlay\" style={{ zIndex }}>\n <div className=\"close-warning-modal\">\n <div className=\"close-warning-header\">\n <div className=\"close-warning-icon\">⚠️</div>\n <h5 className=\"close-warning-title\">{resolvedTitle}</h5>\n </div>\n <p className=\"close-warning-message\">{resolvedMessage}</p>\n <p className=\"close-warning-message\" style={{ fontWeight: 500, margin: 0 }}>{question}</p>\n <div className=\"close-warning-footer\">\n <button\n type=\"button\"\n className=\"btn-warning-action btn-warning-cancel\"\n onClick={onCancel}\n ref={cancelButtonRef}\n >\n Cancel\n </button>\n <button\n type=\"button\"\n className=\"btn-warning-action btn-warning-discard\"\n onClick={onDiscard}\n >\n Discard Changes\n </button>\n </div>\n </div>\n </div>\n );\n};\n\nexport default DirtyWarningOverlay;\n","import React, { useCallback, useRef, useEffect, useState, useMemo } from 'react';\nimport { usePanelState, usePanelActions } from './PanelProviderContext';\nimport { FormContainerProvider, type FormContainerContract, type CloseOptions } from './FormContainerContext';\nimport type { PanelInstance, SidePanelOptions, PanelTitle } from './PanelProviderContext';\nimport { useFormatMessage, formatLabel, useStyleClasses } from './WindowManagerContext';\nimport { DirtyWarningOverlay } from './DirtyWarningOverlay';\n\ninterface SidePanelRendererItemProps {\n panel: PanelInstance;\n position: 'left' | 'right';\n defaultWidth?: number | string;\n}\n\nconst SidePanelRendererItem: React.FC<SidePanelRendererItemProps> = ({ panel, position, defaultWidth }) => {\n const { close, updateInstance, setDirty, registerCloseHandler, unregisterCloseHandler } = usePanelActions();\n const { modals } = usePanelState();\n const formatMessage = useFormatMessage();\n const { sidePanelClass, sidePanelBodyClass } = useStyleClasses();\n const closeHandlerRef = useRef<(() => boolean | Promise<boolean>) | null>(null);\n\n const [showDirtyWarning, setShowDirtyWarning] = useState(false);\n const dirtyResolverRef = useRef<((discard: boolean) => void) | null>(null);\n\n const { id, Component, props, options, dirty } = panel;\n const panelOptions = options as SidePanelOptions;\n const [icon, setIconState] = useState<React.ReactNode>(panelOptions.icon || null);\n\n const optionsRef = useRef(panelOptions);\n optionsRef.current = panelOptions;\n\n const promptDirtyWarning = useCallback((): Promise<boolean> => {\n return new Promise((resolve) => {\n dirtyResolverRef.current = resolve;\n setShowDirtyWarning(true);\n });\n }, []);\n\n const handleDirtyDiscard = useCallback(() => {\n dirtyResolverRef.current?.(true);\n dirtyResolverRef.current = null;\n setShowDirtyWarning(false);\n }, []);\n\n const handleDirtyCancel = useCallback(() => {\n dirtyResolverRef.current?.(false);\n dirtyResolverRef.current = null;\n setShowDirtyWarning(false);\n }, []);\n\n const handleClose = useCallback(async (options?: CloseOptions) => {\n if (options?.force) {\n close(id);\n return;\n }\n\n if (closeHandlerRef.current) {\n const canClose = await closeHandlerRef.current();\n if (!canClose) return;\n close(id);\n return;\n }\n\n if (dirty) {\n const shouldDiscard = await promptDirtyWarning();\n if (!shouldDiscard) return;\n }\n\n close(id);\n }, [close, id, dirty, promptDirtyWarning]);\n\n const canClose = useCallback(async (): Promise<boolean> => {\n if (closeHandlerRef.current) {\n return await closeHandlerRef.current();\n }\n return !dirty;\n }, [dirty]);\n\n useEffect(() => {\n registerCloseHandler(id, canClose);\n return () => unregisterCloseHandler(id);\n }, [id, canClose, registerCloseHandler, unregisterCloseHandler]);\n\n const handleSetDirty = useCallback((dirty: boolean) => setDirty(id, dirty), [setDirty, id]);\n const handleSetTitle = useCallback((title: PanelTitle) => updateInstance(id, { options: { ...optionsRef.current, title } }), [updateInstance, id]);\n const handleSetIcon = useCallback((newIcon: React.ReactNode) => setIconState(newIcon), []);\n const handleOnCloseRequested = useCallback((handler: () => boolean | Promise<boolean>) => {\n closeHandlerRef.current = handler;\n return () => { closeHandlerRef.current = null; };\n }, []);\n\n const contract: FormContainerContract = useMemo(() => ({\n requestClose: handleClose,\n setDirty: handleSetDirty,\n setTitle: handleSetTitle,\n setIcon: handleSetIcon,\n onCloseRequested: handleOnCloseRequested,\n containerType: position === 'left' ? 'left-panel' : 'right-panel',\n instanceId: id,\n }), [handleClose, handleSetDirty, handleSetTitle, handleSetIcon, handleOnCloseRequested, position, id]);\n\n const baseTitle = formatLabel(panelOptions.title, formatMessage);\n const displayTitle = dirty ? `${baseTitle} *` : baseTitle;\n\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && modals.length === 0 && !showDirtyWarning) {\n handleClose();\n }\n };\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [handleClose, modals.length, showDirtyWarning]);\n\n const width = panelOptions.width || defaultWidth || 400;\n const widthStyle = typeof width === 'number' ? `${width}px` : width;\n\n return (\n <>\n <div \n className={`v2-side-panel v2-side-panel-${position} v2-side-panel-visible ${sidePanelClass ?? ''}`}\n style={{ width: widthStyle }}\n >\n <div className=\"v2-side-panel-window\">\n <div className=\"v2-side-panel-header\">\n {icon && <div className=\"v2-side-panel-icon\">{icon}</div>}\n <h4 className=\"v2-side-panel-title\">{displayTitle}</h4>\n <button className=\"v2-side-panel-close-button\" onClick={() => handleClose()} title=\"Close\" type=\"button\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\">\n <path d=\"M18 6L6 18M6 6l12 12\" />\n </svg>\n </button>\n </div>\n <div className={`v2-side-panel-body ${sidePanelBodyClass ?? ''}`}>\n <FormContainerProvider value={contract}>\n <Component {...props} panelId={id} />\n </FormContainerProvider>\n </div>\n </div>\n </div>\n\n {showDirtyWarning && (\n <DirtyWarningOverlay\n zIndex={20000}\n onDiscard={handleDirtyDiscard}\n onCancel={handleDirtyCancel}\n />\n )}\n </>\n );\n};\n\nexport interface SidePanelRendererProps {\n /**\n * Default panel width applied when openLeftPanel/openRightPanel do not specify one.\n * Accepts a number (treated as px) or any CSS width string (e.g. '40vw').\n * Falls back to 400px if omitted.\n */\n defaultWidth?: number | string;\n}\n\nexport const SidePanelRenderer: React.FC<SidePanelRendererProps> = ({ defaultWidth }) => {\n const { leftPanel, rightPanel } = usePanelState();\n return (\n <>\n {leftPanel && <SidePanelRendererItem key={leftPanel.id} panel={leftPanel} position=\"left\" defaultWidth={defaultWidth} />}\n {rightPanel && <SidePanelRendererItem key={rightPanel.id} panel={rightPanel} position=\"right\" defaultWidth={defaultWidth} />}\n </>\n );\n};\n\nexport const LeftPanelRenderer: React.FC<SidePanelRendererProps> = ({ defaultWidth }) => {\n const { leftPanel } = usePanelState();\n if (!leftPanel) return null;\n return <SidePanelRendererItem key={leftPanel.id} panel={leftPanel} position=\"left\" defaultWidth={defaultWidth} />;\n};\n\nexport const RightPanelRenderer: React.FC<SidePanelRendererProps> = ({ defaultWidth }) => {\n const { rightPanel } = usePanelState();\n if (!rightPanel) return null;\n return <SidePanelRendererItem key={rightPanel.id} panel={rightPanel} position=\"right\" defaultWidth={defaultWidth} />;\n};\n\nexport default SidePanelRenderer;\n","import React, { useEffect, useRef } from 'react';\nimport { useFormContainer } from '../components/FormContainerContext';\n\nexport interface ConfirmationFormProps {\n title?: string | { id: string; defaultMessage?: string; values?: any };\n message: string | { id: string; defaultMessage?: string; values?: any };\n alert?: string;\n alertType?: 'info' | 'warning' | 'success' | 'danger';\n useYesNoTitles?: boolean;\n onOK?: () => void;\n onCancel?: () => void;\n}\n\nexport const ConfirmationForm: React.FC<ConfirmationFormProps> = ({\n title,\n message,\n alert,\n alertType = 'info',\n useYesNoTitles = false,\n onOK,\n onCancel,\n}) => {\n const { requestClose, setIcon, setTitle } = useFormContainer();\n const confirmButtonRef = useRef<HTMLButtonElement>(null);\n\n useEffect(() => {\n if (title) {\n const resolvedTitle = typeof title === 'string' ? title : title.defaultMessage || title.id;\n setTitle(resolvedTitle);\n }\n \n if (setIcon) {\n setIcon(<span>❓</span>);\n }\n }, [title, setTitle, setIcon]);\n\n useEffect(() => {\n confirmButtonRef.current?.focus();\n }, []);\n\n const resolvedMessage = typeof message === 'string' ? message : message.defaultMessage || message.id;\n\n const cancelLabel = useYesNoTitles ? 'No' : 'Cancel';\n const confirmLabel = useYesNoTitles ? 'Yes' : 'OK';\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n onOK?.();\n requestClose();\n };\n\n const handleCancel = () => {\n onCancel?.();\n requestClose();\n };\n\n return (\n <form onSubmit={handleSubmit} className=\"p-3 d-flex flex-column gap-3\">\n {alert && (\n <div className={`alert alert-${alertType === 'danger' ? 'danger' : alertType} d-flex align-items-center gap-2 m-0 p-2.5 small`}>\n <span>ℹ️</span>\n <span>{alert}</span>\n </div>\n )}\n\n <div style={{ fontSize: '0.9rem', color: 'inherit', lineHeight: 1.5 }}>\n {resolvedMessage}\n </div>\n\n <hr className=\"my-2 opacity-10\" />\n\n <div className=\"d-flex justify-content-end gap-2\">\n <button\n type=\"button\"\n className=\"btn btn-sm btn-outline-secondary font-monospace\"\n onClick={handleCancel}\n >\n {cancelLabel}\n </button>\n <button\n type=\"submit\"\n className=\"btn btn-sm btn-primary font-monospace\"\n ref={confirmButtonRef}\n >\n {confirmLabel}\n </button>\n </div>\n </form>\n );\n};\n\nexport default ConfirmationForm;\n","import React, {\n useState,\n useEffect,\n useRef,\n useCallback,\n useImperativeHandle,\n forwardRef,\n} from 'react';\n\n// ==========================================\n// Types\n// ==========================================\n\n/**\n * Per-tab configuration supplied by the consuming application.\n */\nexport interface SidebarTab {\n id: string;\n label: string;\n icon: React.ReactNode;\n /**\n * Mount immediately when the Sidebar first renders, not on first user click.\n * Implies `preserveState: true`.\n * Use when other parts of the app need to interact with the panel before\n * the user has opened it (e.g. push data into a context, warm up a WebGL map).\n * Default: false\n */\n eagerMount?: boolean;\n /**\n * Once mounted for the first time, keep the component alive in the DOM\n * behind `display: none` when closed instead of unmounting it.\n * Use for panels with expensive local state (long forms, WebGL scenes, etc.).\n * Ignored when `eagerMount` is true (eagerly mounted panels are always preserved).\n * Default: false\n */\n preserveState?: boolean;\n /**\n * Called to obtain the drawer content for this tab.\n * @param tabId - the id of this tab\n * @param onClose - call to collapse the sidebar drawer\n * @param onOpen - call to expand the drawer and select this tab programmatically\n * (useful when the panel itself detects it has new data to show)\n */\n renderContent: (tabId: string, onClose: () => void, onOpen: () => void) => React.ReactNode;\n}\n\nexport interface SidebarProps {\n /** Which side the tab strip and drawer appear on. Default: 'right' */\n position?: 'left' | 'right';\n tabs: SidebarTab[];\n /** Width of the open drawer. Default: '220px' */\n drawerWidth?: string;\n /** Controlled active tab id. Leave undefined to use internal state. */\n activeTabId?: string | null;\n /** Called when the active tab changes in uncontrolled mode. */\n onActiveTabChange?: (tabId: string | null) => void;\n /** Main workspace content, rendered between the strip and drawer (or around them). */\n children?: React.ReactNode;\n}\n\n/**\n * Imperative handle exposed by <Sidebar ref={...}> via forwardRef.\n * Allows external components (outside the sidebar tree) to control\n * which tab is open without prop drilling.\n */\nexport interface SidebarHandle {\n /** Expand the drawer and activate the tab with the given id. */\n openTab: (tabId: string) => void;\n /** Collapse the drawer (equivalent to clicking the active tab icon). */\n closeDrawer: () => void;\n /** Returns the currently active tab id, or null if the drawer is collapsed. */\n getActiveTab: () => string | null;\n}\n\n// ==========================================\n// Component\n// ==========================================\n\nexport const Sidebar = forwardRef<SidebarHandle, SidebarProps>(function Sidebar(\n {\n position = 'right',\n tabs,\n drawerWidth = '220px',\n activeTabId: controlledActiveTabId,\n onActiveTabChange,\n children,\n },\n ref\n) {\n const isControlled = controlledActiveTabId !== undefined;\n\n // Internal active tab state (used when uncontrolled)\n const [internalActiveTabId, setInternalActiveTabId] = useState<string | null>(null);\n\n // The effective active tab id — either from props (controlled) or internal state\n const activeTabId = isControlled ? controlledActiveTabId : internalActiveTabId;\n\n // Track which tabs have been mounted at least once\n // Pre-populate with all eagerMount tabs\n const [mountedTabIds, setMountedTabIds] = useState<Set<string>>(() => {\n const initial = new Set<string>();\n for (const tab of tabs) {\n if (tab.eagerMount) initial.add(tab.id);\n }\n return initial;\n });\n\n // When tabs change (e.g. new eagerMount tabs added), mount them immediately\n useEffect(() => {\n const newEager = tabs.filter(t => t.eagerMount && !mountedTabIds.has(t.id));\n if (newEager.length > 0) {\n setMountedTabIds(prev => {\n const next = new Set(prev);\n for (const tab of newEager) next.add(tab.id);\n return next;\n });\n }\n }, [tabs]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Stable ref to active tab for imperative handle\n const activeTabIdRef = useRef<string | null>(activeTabId ?? null);\n useEffect(() => {\n activeTabIdRef.current = activeTabId ?? null;\n }, [activeTabId]);\n\n const setActiveTabId = useCallback(\n (id: string | null) => {\n if (isControlled) {\n onActiveTabChange?.(id);\n } else {\n setInternalActiveTabId(id);\n onActiveTabChange?.(id);\n }\n },\n [isControlled, onActiveTabChange]\n );\n\n // Expose imperative handle\n useImperativeHandle(\n ref,\n () => ({\n openTab: (tabId: string) => setActiveTabId(tabId),\n closeDrawer: () => setActiveTabId(null),\n getActiveTab: () => activeTabIdRef.current,\n }),\n [setActiveTabId]\n );\n\n const handleTabClick = (tabId: string) => {\n setActiveTabId(activeTabId === tabId ? null : tabId);\n };\n\n const handleClose = useCallback(() => setActiveTabId(null), [setActiveTabId]);\n\n // On first open of a non-eager tab, add it to mounted set\n useEffect(() => {\n if (activeTabId && !mountedTabIds.has(activeTabId)) {\n setMountedTabIds(prev => {\n const next = new Set(prev);\n next.add(activeTabId);\n return next;\n });\n }\n }, [activeTabId, mountedTabIds]);\n\n // On close of a standard tab (neither eagerMount nor preserveState), unmount it\n useEffect(() => {\n if (activeTabId !== null) return; // drawer just opened or is still open\n setMountedTabIds(prev => {\n let changed = false;\n const next = new Set(prev);\n for (const id of prev) {\n const tab = tabs.find(t => t.id === id);\n if (tab && !tab.eagerMount && !tab.preserveState) {\n next.delete(id);\n changed = true;\n }\n }\n return changed ? next : prev;\n });\n }, [activeTabId, tabs]);\n\n // ---- Render helpers ----\n\n const tabStrip = (\n <div className={`sidebar-tabs-strip ${position}`} style={{ width: '56px', height: '100%' }}>\n {tabs.map(tab => {\n const isActive = activeTabId === tab.id;\n return (\n <button\n key={tab.id}\n type=\"button\"\n onClick={() => handleTabClick(tab.id)}\n className={`sidebar-tab-btn ${isActive ? 'active' : ''}`}\n title={tab.label}\n aria-pressed={isActive}\n >\n {tab.icon}\n </button>\n );\n })}\n </div>\n );\n\n const drawer = (\n <div\n className={`sidebar-content-drawer h-100 ${position}`}\n style={{\n width: activeTabId ? drawerWidth : '0px',\n minWidth: activeTabId ? drawerWidth : '0px',\n overflow: 'hidden',\n flexShrink: 0,\n }}\n >\n {/* Render all mounted tabs; only the active one is visible */}\n {tabs.map(tab => {\n const isMounted = mountedTabIds.has(tab.id);\n if (!isMounted) return null;\n\n const isCurrent = activeTabId === tab.id;\n\n // Stable onOpen per tab id\n const onOpen = () => setActiveTabId(tab.id);\n\n return (\n <div\n key={tab.id}\n style={{\n display: isCurrent ? 'flex' : 'none',\n flexDirection: 'column',\n height: '100%',\n width: '100%',\n }}\n >\n {/* Drawer header */}\n <div\n className=\"d-flex align-items-center justify-content-between border-bottom border-secondary-subtle px-3 py-2 flex-shrink-0\"\n style={{ background: 'rgba(0,0,0,0.08)', minHeight: '38px' }}\n >\n <span className=\"sidebar-header-title\">{tab.label}</span>\n <button\n type=\"button\"\n onClick={handleClose}\n className=\"btn btn-link p-0 text-secondary d-flex align-items-center\"\n style={{ textDecoration: 'none' }}\n title=\"Close panel\"\n aria-label=\"Close panel\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </div>\n\n {/* Drawer body — consumer-supplied content */}\n <div className=\"flex-grow-1 overflow-auto\">\n {tab.renderContent(tab.id, handleClose, onOpen)}\n </div>\n </div>\n );\n })}\n </div>\n );\n\n return (\n <>\n {position === 'left' && tabStrip}\n {position === 'left' && drawer}\n {children}\n {position === 'right' && drawer}\n {position === 'right' && tabStrip}\n </>\n );\n});\n\nexport default Sidebar;\n"],"mappings":"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","names":["React","useState","useRef","useEffect","createPortal","createContext","useContext","useState","useRef","useMemo","useCallback","PanelRegistryClass","id","Component","defaultOptions","PanelRegistry","defaultPredefinedMessages","jsx","WindowStateContext","createContext","WindowActionsContext","WindowI18nContext","WindowPredefinedMessagesContext","defaultPredefinedMessages","StyleClassContext","useStyleClasses","useContext","PanelEventBus","event","callback","cb","data","initialLayout","initialPanels","initialFloating","WindowManagerProvider","children","formatMessage","predefinedMessages","modalClass","modalBodyClass","sidePanelClass","sidePanelBodyClass","windowClass","windowBodyClass","state","setState","useState","stateRef","useRef","closeGuardsRef","mergedMessages","useMemo","eventBusRef","maxZRef","subscribe","useCallback","publish","getCascadedPosition","fav","currentFloating","x","y","width","height","isOverlapping","pos","w","wx","wy","attempts","viewW","viewH","bringToFront","id","z","prev","panel","selectActiveInTree","node","removePanelFromTree","idx","panels","p","activePanelId","updatedLeaf","c","sizes","sum","a","b","s","addPanelToLeaf","leafId","panelId","findFirstLeafId","child","openPanel","component","options","exists","entry","PanelRegistry","title","target","favPos","nextMinimized","m","cascaded","firstLeaf","newPanelInfo","nextPanels","stickyRight","stickyBottom","winW","winH","initialX","initialY","GAP","closePanel","cleanRoot","registerCloseGuard","guard","unregisterCloseGuard","setPanelDirty","dirty","updatePanelTitle","resolvePendingClose","discard","requestClosePanel","resolve","minimizePanel","lastFloatingRect","lastLeafId","win","findLeafForPanel","res","restorePanel","leafExists","targetId","parentLeafExists","canDrag","targetLeafId","floatPanel","rect","dockPanel","nextFloating","splitLeafInTree","position","newLeaf","setDraggedPanelId","dockPanelToGroup","newRoot","dockPanelToWorkspaceEdge","orientation","movePanelOrder","targetIndex","insertInLeaf","remaining","index","newPanels","closeLeafGroup","removeLeafFromTree","maximizePanel","updateSplitSizes","path","updateInTree","depth","i","updateFloatingPosition","updates","saveLayout","loadLayout","layoutJson","parsed","e","actions","defaultFormatMessage","msg","text","key","value","styleClasses","useWindowManagerState","ctx","useWindowManagerActions","useFormatMessage","formatLabel","label","formatter","usePanelContext","usePredefinedMessages","JsonContextMenu","createContext","useContext","defaultContract","FormContainerContext","FormContainerProvider","useFormContainer","Fragment","jsx","jsxs","domCache","hiddenContainerId","DefaultGridIcon","getOrCreateDomCacheElement","id","el","renderPanelContent","componentKey","registryEntry","PanelRegistry","Component","activePanelDimensions","panelLifecycleRegistry","getOrCreateLifecycleRegistry","panelId","entry","PreservedDOMWrapper","hostRef","useRef","useEffect","host","cachedEl","resizeObserver","entries","width","height","lifecycle","h","hiddenContainer","PreviewDOMWrapper","state","useWindowManagerState","panel","regEntry","disableLivePreview","dimensions","setDimensions","useState","lastSize","origW","origH","scale","displayW","displayH","icon","FormContainerProviderWrapper","children","requestClosePanel","setPanelDirty","registerCloseGuard","unregisterCloseGuard","updatePanelTitle","useWindowManagerActions","isMin","m","prevMinRef","contract","React","options","dirty","handler","title","reg","FormContainerProvider","WorkspaceGrid","node","path","onTabRightClick","activeDropZone","onHoverDropZone","onTabDragStart","hoveredTab","onTabHover","defaultPanelIcon","updateSplitSizes","LeafGroup","isRow","handleResizerMouseDown","idx","e","startOffset","startSizes","parentEl","parentSize","handleMouseMove","moveEvent","deltaPercentage","newSizes","handleMouseUp","child","size","leaf","openPanel","closeLeafGroup","formatMessage","useFormatMessage","messages","usePredefinedMessages","windowClass","windowBodyClass","useStyleClasses","selectTab","isActive","isHovered","isLast","isHoveredEmpty","sideClass","rect","side","formatLabel","WindowManager","skin","restorePanel","minimizePanel","resolvePendingClose","maximizePanel","updateFloatingPosition","bringToFront","floatPanel","setDraggedPanelId","dockPanelToGroup","movePanelOrder","dockPanelToWorkspaceEdge","instantiatedPanels","setInstantiatedPanels","taskbarRef","contextMenuRef","hoveredMinimized","setHoveredMinimized","minimizedTooltipTimeoutRef","isContextMenuOpen","setIsContextMenuOpen","setActiveDropZone","activeDropZoneRef","dragPos","setDragPos","activeEdgeDrop","setActiveEdgeDropState","activeEdgeDropRef","setActiveEdgeDrop","val","setHoveredTab","hoveredTabRef","handleTabHover","leafId","index","handleHoverDropZone","position","handleTabDragStart","startX","startY","dragStarted","dx","dy","handleMouseUpWrapper","dropZone","targetTab","edgeDrop","targetIndex","handleTabRightClick","items","handleMinimizedRightClick","keys","cachedId","handleWindowBlur","workspaceRef","workspaceSize","setWorkspaceSize","observer","viewW","viewH","w","winW","winH","winX","winY","newWidth","newHeight","newX","newY","changed","GAP","maxX","maxY","handleMouseDownGlobal","target","windowEl","winId","startDrag","floatingWin","startPosX","startPosY","startResize","startW","startH","dw","dh","parsedX","parsedY","parsedW","parsedH","isRightSnapped","isBottomSnapped","scrollTaskbar","direction","amount","currentBsTheme","setCurrentBsTheme","updateThemeState","activeTheme","obs","maxZ","isMaximized","isDragged","isFocused","isRight","isBottom","createPortal","targetEl","JsonContextMenu","pendingPanel","panelTitle","WindowManager_default","createContext","useContext","useState","useCallback","useMemo","useRef","jsx","idCounter","generateId","closeHandlers","initialState","PanelStateContext","PanelActionsContext","PanelProvider","children","state","setState","stateRef","registerCloseHandler","id","handler","unregisterCloseHandler","openLeftPanel","Component","props","options","currentPanel","instance","s","openRightPanel","openModal","formTitle","modalOptions","close","m","closeAll","closeAllModals","getInstance","updateInstance","updates","setDirty","dirty","actions","usePanelState","ctx","usePanelActions","useCallback","useRef","useEffect","useState","useMemo","useEffect","useRef","jsx","jsxs","DirtyWarningOverlay","zIndex","onDiscard","onCancel","message","title","cancelButtonRef","useRef","useEffect","timer","handleKeyDown","e","Fragment","jsx","jsxs","ModalRenderer","modal","index","isTopmost","close","updateInstance","setDirty","usePanelActions","formatMessage","useFormatMessage","modalClass","modalBodyClass","useStyleClasses","closeHandlerRef","useRef","showDirtyWarning","setShowDirtyWarning","useState","dirtyResolverRef","id","Component","props","options","dirty","modalOptions","icon","setIconState","optionsRef","promptDirtyWarning","useCallback","resolve","handleDirtyDiscard","handleDirtyCancel","handleClose","handleSetDirty","handleSetTitle","title","handleSetIcon","newIcon","handleOnCloseRequested","handler","contract","useMemo","baseTitle","formatLabel","displayTitle","sizeClass","showCloseButton","useEffect","handleKeyDown","e","modalZIndex","dirtyWarningZIndex","FormContainerProvider","DirtyWarningOverlay","ModalStackRenderer","modals","usePanelState","ModalStackRenderer_default","useCallback","useRef","useEffect","useState","useMemo","Fragment","jsx","jsxs","SidePanelRendererItem","panel","position","defaultWidth","close","updateInstance","setDirty","registerCloseHandler","unregisterCloseHandler","usePanelActions","modals","usePanelState","formatMessage","useFormatMessage","sidePanelClass","sidePanelBodyClass","useStyleClasses","closeHandlerRef","useRef","showDirtyWarning","setShowDirtyWarning","useState","dirtyResolverRef","id","Component","props","options","dirty","panelOptions","icon","setIconState","optionsRef","promptDirtyWarning","useCallback","resolve","handleDirtyDiscard","handleDirtyCancel","handleClose","canClose","useEffect","handleSetDirty","handleSetTitle","title","handleSetIcon","newIcon","handleOnCloseRequested","handler","contract","useMemo","baseTitle","formatLabel","displayTitle","handleKeyDown","e","width","widthStyle","FormContainerProvider","DirtyWarningOverlay","SidePanelRenderer","leftPanel","rightPanel","LeftPanelRenderer","RightPanelRenderer","SidePanelRenderer_default","useEffect","useRef","jsx","jsxs","ConfirmationForm","title","message","alert","alertType","useYesNoTitles","onOK","onCancel","requestClose","setIcon","setTitle","useFormContainer","confirmButtonRef","useRef","useEffect","resolvedTitle","resolvedMessage","cancelLabel","confirmLabel","handleSubmit","e","handleCancel","ConfirmationForm_default","useState","useEffect","useRef","useCallback","useImperativeHandle","forwardRef","Fragment","jsx","jsxs","Sidebar","position","tabs","drawerWidth","controlledActiveTabId","onActiveTabChange","children","ref","isControlled","internalActiveTabId","setInternalActiveTabId","activeTabId","mountedTabIds","setMountedTabIds","initial","tab","newEager","t","prev","next","activeTabIdRef","setActiveTabId","id","tabId","handleTabClick","handleClose","changed","tabStrip","isActive","drawer","isCurrent","onOpen"]}
|