import { CSSProperties, ReactNode, Ref } from 'react'; import { DerivedRoom, FloorPlan, PlanRoom, PlanView } from '../floorPlan/index.js'; import { IconContent } from '../types/icon.types.js'; import { HtmlProps, SlotClassNames, SlotStyles } from '../types/slots.types.js'; export type RoomViewerSlots = 'root' | 'floorBar' | 'floorTab' | 'canvasWrapper' | 'canvas' | 'grid' | 'rooms' | 'roomFill' | 'roomLabel' | 'walls' | 'wallBody' | 'openings' | 'opening' | 'viewControls' | 'viewButton' | 'empty'; export interface RoomViewerLabels { /** Accessible name for the floor strip. */ floors?: string; zoomIn?: string; zoomOut?: string; fit?: string; empty?: string; /** Stands in for the name of a room that has none. */ unnamedRoom?: string; /** Announced when a room is selected, given its name and its formatted area. */ selectedRoom?: (name: string, area: string) => string; /** Announced when the selection is cleared. */ noRoomSelected?: string; } export interface RoomViewerIcons { zoomIn?: IconContent; zoomOut?: IconContent; fit?: IconContent; } export interface RoomViewerHandle { /** Fits the active floor into the viewport. */ fitToContent: (options?: { padding?: number; }) => void; getView: () => PlanView; setView: (view: PlanView) => void; zoomBy: (factor: number) => void; /** Selects a room, or clears the selection with `null`. */ select: (roomId: string | null) => void; getFloorId: () => string | null; setFloorId: (floorId: string) => void; /** The live ``, for measuring or screenshotting. */ getSvgElement: () => SVGSVGElement | null; } export interface RoomViewerProps extends Omit, 'onSelect'> { /** * The plan to display, floors and all. This replaces the old `data` prop, which took * pre-rendered SVG: that could not be selected, measured or re-themed, and nothing * could be shared with the drawer. */ plan?: FloorPlan; /** Which storey is showing. Controlled; pair with `onFloorChange`. */ activeFloorId?: string; defaultActiveFloorId?: string; onFloorChange?: (floorId: string) => void; /** Controlled selection. `null` is a real value here: nothing selected. */ selectedRoomId?: string | null; defaultSelectedRoomId?: string | null; onSelect?: (roomId: string | null, room: DerivedRoom | null, floorId: string) => void; hoveredRoomId?: string | null; onHoverChange?: (roomId: string | null) => void; view?: PlanView; defaultView?: PlanView; onViewChange?: (view: PlanView) => void; /** Rooms respond to pointer and keyboard. Default `true`. */ interactive?: boolean; /** Drag to pan, wheel and pinch to zoom. Default `true`. */ pannable?: boolean; /** Fit the plan into view once it is measured. Default `true`. */ fitOnMount?: boolean; showFloorBar?: boolean; showViewControls?: boolean; showGrid?: boolean; showRoomLabels?: boolean; /** Door leaves, swing arcs and window symbols. Default `true`. */ showOpeningSymbols?: boolean; getRoomColor?: (room: PlanRoom, area: number) => string | undefined; renderRoomLabel?: (room: PlanRoom | null, context: { area: number; faceId: string; }) => ReactNode; getRoomLabel?: (room: PlanRoom | null, context: { area: number; }) => string; formatArea?: (areaMm2: number) => string; /** Canvas height. A number is pixels. Default 360. */ height?: number | string; /** Shown when there is no plan, or the plan has nothing in it. */ emptyState?: ReactNode; labels?: RoomViewerLabels; icons?: RoomViewerIcons; /** Imperative handle for driving the viewport. */ ref?: Ref; className?: string; style?: CSSProperties; classNames?: SlotClassNames; styles?: SlotStyles; }