'use client' import { type AnyNode, type AnyNodeId, type WindowNode, useScene } from '@pascal-app/core' import { useViewer } from '@pascal-app/viewer' import { X } from 'lucide-react' import Image from 'next/image' import { useCallback } from 'react' import { NumberInput } from '@/components/ui/primitives/number-input' import { Switch } from '@/components/ui/primitives/switch' export function WindowPanel() { const selectedIds = useViewer((s) => s.selection.selectedIds) const setSelection = useViewer((s) => s.setSelection) const nodes = useScene((s) => s.nodes) const updateNode = useScene((s) => s.updateNode) const selectedId = selectedIds[0] const node = selectedId ? (nodes[selectedId as AnyNode['id']] as WindowNode | undefined) : undefined const handleUpdate = useCallback( (updates: Partial) => { if (!selectedId) return updateNode(selectedId as AnyNode['id'], updates) // Mark dirty so window-system regenerates geometry useScene.getState().dirtyNodes.add(selectedId as AnyNodeId) }, [selectedId, updateNode], ) const handleClose = useCallback(() => { setSelection({ selectedIds: [] }) }, [setSelection]) if (!node || node.type !== 'window' || selectedIds.length !== 1) return null const columns = node.columnRatios.length const rows = node.rowRatios.length return (
{/* Header */}

{node.name || `Window (${node.width}×${node.height}m)`}

{/* Content */}
{/* Dimensions */}
handleUpdate({ width: v })} min={0.2} precision={2} className="flex-1" /> m
handleUpdate({ height: v })} min={0.2} precision={2} className="flex-1" /> m
{/* Frame */}
handleUpdate({ frameThickness: v })} min={0.01} precision={3} className="flex-1" /> m
handleUpdate({ frameDepth: v })} min={0.01} precision={3} className="flex-1" /> m
{/* Grid */}
{ const n = Math.max(1, Math.min(8, Math.round(v))) handleUpdate({ columnRatios: Array(n).fill(1) }) }} min={1} max={8} precision={0} className="flex-1" />
{ const n = Math.max(1, Math.min(8, Math.round(v))) handleUpdate({ rowRatios: Array(n).fill(1) }) }} min={1} max={8} precision={0} className="flex-1" />
{(columns > 1 || rows > 1) && (
handleUpdate({ dividerThickness: v })} min={0.005} precision={3} className="flex-1" /> m
)}
{/* Sill */}
handleUpdate({ sill: checked })} />
{node.sill && (
handleUpdate({ sillDepth: v })} min={0.01} precision={3} className="flex-1" /> m
handleUpdate({ sillThickness: v })} min={0.005} precision={3} className="flex-1" /> m
)}
) }