import { Group, Rect, Line } from 'react-konva'; import type { ProjectedOpening } from '../utils/projectionMapping'; import { projectionToPixel } from '../utils/projectionMapping'; import { useCanvasColors } from '../utils/canvasThemeColors'; interface ProjectionWindowProps { readonly projected: ProjectedOpening; readonly wallHeight: number; readonly scale: number; readonly padding: number; readonly isSelected: boolean; readonly isDragging?: boolean; readonly dragAlongWall?: number; readonly onClick: () => void; readonly onDragStart?: (openingId: string, evt: MouseEvent) => void; } /** Render a window in wall elevation view. */ export function ProjectionWindow({ projected, wallHeight, scale, padding, isSelected, isDragging = false, dragAlongWall, onClick, onDragStart, }: ProjectionWindowProps) { const colors = useCanvasColors(); const { rect, opening } = projected; const displayX = isDragging && dragAlongWall != null ? dragAlongWall - opening.width / 2 : rect.x; const topLeft = projectionToPixel(displayX, rect.y + rect.height, wallHeight, scale, padding); const pxWidth = rect.width * scale; const pxHeight = rect.height * scale; const frameInset = 3; return ( { if (onDragStart && e.evt.button === 0) { onDragStart(opening.id, e.evt); } }} > {/* Drag ghost outline */} {isDragging && ( )} {/* Window frame (outer) */} {/* Glass pane (inner rectangle) */} {/* Internal mullions — N×M grid. Rendered as lines spanning the glass area; `gridCols - 1` verticals + `gridRows - 1` horizontals. Defaults to 2×2 for legacy windows without an explicit grid set. */} {(() => { const cols = Math.max(1, Math.min(10, Math.round(opening.gridCols ?? 2))); const rows = Math.max(1, Math.min(10, Math.round(opening.gridRows ?? 2))); const innerLeft = topLeft.x + frameInset; const innerTop = topLeft.y + frameInset; const innerWidth = pxWidth - frameInset * 2; const innerHeight = pxHeight - frameInset * 2; const lines: React.ReactNode[] = []; for (let i = 1; i < cols; i++) { const x = innerLeft + (innerWidth * i) / cols; lines.push( , ); } for (let i = 1; i < rows; i++) { const y = innerTop + (innerHeight * i) / rows; lines.push( , ); } return lines; })()} ); }