import { CSSProperties, ReactNode, Ref } from 'react'; import { DerivedRoom, PlanFloor, PlanRoom, PlanSelection, PlanView } from '../floorPlan/index.js'; import { SlotClassNames, SlotStyles } from '../types/slots.types.js'; export type PlanCanvasSlots = 'canvas' | 'grid' | 'underlay' | 'rooms' | 'roomFill' | 'roomLabel' | 'walls' | 'wallBody' | 'openings' | 'opening' | 'overlay'; export interface PlanCanvasProps { floor: PlanFloor; /** * A floor traced faintly behind this one, normally the storey below, so walls can be * lined up between storeys. Drawn as wall centrelines only: it is a reference, not a * second plan, and it takes no pointer events. */ underlay?: PlanFloor | null; /** * Derived rooms, passed in rather than computed here so the parent controls * memoisation and both components share one derivation per render. */ rooms: DerivedRoom[]; view: PlanView; /** Everything currently selected. A single selection is a one-element array. */ selection?: readonly PlanSelection[]; hovered?: PlanSelection | null; /** Makes room fills focusable, clickable and screen-reader labelled. */ interactiveRooms?: boolean; interactiveOpenings?: boolean; showGrid?: boolean; /** Grid spacing in millimetres. */ gridSize?: number; showRoomLabels?: boolean; /** Door leaves, swing arcs and window panes. `false` leaves plain gaps. */ showOpeningSymbols?: boolean; getRoomColor?: (room: PlanRoom, area: number) => string | undefined; renderRoomLabel?: (room: PlanRoom | null, context: { area: number; faceId: string; }) => ReactNode; /** Accessible name for an interactive room. RoomViewer supplies the default, from its labels. */ getRoomLabel?: (room: PlanRoom | null, context: { area: number; }) => string; formatArea?: (areaMm2: number) => string; onRoomActivate?: (roomId: string) => void; onOpeningActivate?: (openingId: string) => void; onBackgroundActivate?: () => void; onHoverChange?: (target: PlanSelection | null) => void; /** * Extra SVG drawn above everything, in SCREEN space: handles, previews, badges. * The drawer supplies its editing chrome through this. */ overlay?: ReactNode; /** Extra SVG drawn in WORLD space, below the screen-space overlay. */ worldOverlay?: ReactNode; /** Width and height of the canvas in CSS pixels, measured by the parent. */ size: { width: number; height: number; }; 'aria-label'?: string; /** Ref to the rendered `` root. */ ref?: Ref; className?: string; style?: CSSProperties; classNames?: SlotClassNames; styles?: SlotStyles; }