'use client' import { type AnyNode, type SlabNode, 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' export function SlabPanel() { 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) // Get the first selected node if it's a slab const selectedId = selectedIds[0] const node = selectedId ? (nodes[selectedId as AnyNode['id']] as SlabNode | undefined) : undefined const handleUpdate = useCallback( (updates: Partial) => { if (!selectedId) return updateNode(selectedId as AnyNode['id'], updates) }, [selectedId, updateNode], ) const handleClose = useCallback(() => { setSelection({ selectedIds: [] }) }, [setSelection]) // Only show if exactly one slab is selected if (!node || node.type !== 'slab' || selectedIds.length !== 1) return null // Calculate approximate area from polygon const calculateArea = (polygon: Array<[number, number]>): number => { if (polygon.length < 3) return 0 let area = 0 const n = polygon.length for (let i = 0; i < n; i++) { const j = (i + 1) % n area += polygon[i]![0] * polygon[j]![1] area -= polygon[j]![0] * polygon[i]![1] } return Math.abs(area) / 2 } const area = calculateArea(node.polygon) return (
{/* Header */}

{node.name || `Slab (${area.toFixed(1)}m²)`}

{/* Content */}
{/* Elevation */}
{ handleUpdate({ elevation: value }) }} precision={3} className="flex-1" /> m

Height offset from the level base (positive = raised, negative = sunken)

{/* Quick preset buttons */}
{/* Area info */}
{area.toFixed(2)} m²
) }