# Event Handing

The Floorplan SDK emits **global events** for interactions inside the embedded plan. Each event delivers a **unified payload** describing the targeted entity (space, room, wall perimeter, or area/background) and its position.

***

### Event names

```ts
export type FloorPlanEvents =
  | "click"
  | "right-click"
  | "double-click"
  | "hover"
  | "blur"
  | "plan-right-click"
  | "outside-click";
```

* **click / double-click / right-click** — Interaction on an entity.
* **hover / blur** — Pointer enters/leaves an entity.
* **plan-right-click** — Context menu on the plan canvas (not on a specific entity).
* **outside-click** — Click detected outside interactive entities (background).

***

### Payload shape

```ts
export type FloorPlanEntityType = "SPACE" | "WALL_PERIMETER" | "ROOM" | "AREA";

export type Center = {
  x: number;        // absolute pixels in canvas coords
  y: number;
  relativeX?: number; // 0..1 within canvas
  relativeY?: number; // 0..1 within canvas
};

export interface FloorPlanEntity<T extends Record<string, any> = {}> {
  id: string;
  type: FloorPlanEntityType;   // "SPACE" | "ROOM" | "WALL_PERIMETER" | "AREA"
  center?: Center;
  properties?: T & { locationId: string; layerId: string };
}

export type SpaceMetadata = any;
export type RoomMetadata = any;
export type WallPerimeterMetadata = any;
export type FloorPlanEntityMetadata =
  | SpaceMetadata
  | RoomMetadata
  | WallPerimeterMetadata;

interface FloorPlanEvent {
  event: FloorPlanEvents;
  id: string; // mirrors metadata.id
  metadata: FloorPlanEntity<FloorPlanEntityMetadata>;
}
```

* `metadata.type` identifies the target: **SPACE**, **ROOM**, **WALL\_PERIMETER**, or **AREA** (background).
* `properties.locationId` and `properties.layerId` help you route events per site/floor.
* `center` provides both pixel and relative coordinates for precise UI placement (e.g., tooltips, context menus).

***

### Subscribing & unsubscribing

```ts
// Subscribe
sdk.on(eventName: FloorPlanEvents, handler: (e: FloorPlanEvent) => void);

// Unsubscribe a specific handler
sdk.off(eventName: FloorPlanEvents, handler: (e: FloorPlanEvent) => void);

// Unsubscribe all handlers for an event
sdk.off(eventName: FloorPlanEvents);
```

***

### Vanilla JS example

```html
<div id="floorplan-root" style="width:100%;height:720px;"></div>
<script type="module">
  import Floorplan from "/node_modules/@gospace-ai/floorplan/dist/floorplan.es.js";

  const sdk = new Floorplan({
    key: "floorplan-root",
    access_token: "<short-lived-access-token>",
    location_id: "loc_123",
    layer_id: "layer_001",
  });

  const onClick = (e) => {
    const { event, id, metadata } = e;
    // Example: SPACE/ROOM selection
    if (metadata.type === "SPACE" || metadata.type === "ROOM") {
      console.log(`[${event}]`, id, metadata);
      // open details panel, booking flow, etc.
    }
  };

  const onPlanContext = (e) => {
    // Show a context menu at e.metadata.center
    console.log("[plan-right-click]", e.metadata.center);
  };

  sdk.on("click", onClick);
  sdk.on("double-click", onClick);
  sdk.on("right-click", onClick);
  sdk.on("plan-right-click", onPlanContext);

  // Optional: hover/blur for highlighting
  sdk.on("hover", (e) => {
    // highlight e.metadata.id
  });
  sdk.on("blur", (e) => {
    // remove highlight for e.metadata.id
  });

  // Outside clicks (background)
  sdk.on("outside-click", (e) => {
    // clear selections
  });

  sdk.init();

  // later:
  // sdk.off("click", onClick);
  // sdk.destroy?.();
</script>
```

***

### Filtering & patterns

**By entity type**

```ts
sdk.on("click", ({ metadata }) => {
  switch (metadata.type) {
    case "SPACE": /* handle desk/seat */ break;
    case "ROOM":  /* handle room      */ break;
    case "WALL_PERIMETER": /* ignore or inspect */ break;
    case "AREA":  /* background */ break;
  }
});
```

**Coordinate‑based UI**

```ts
sdk.on("right-click", ({ metadata }) => {
  const { x, y } = metadata.center || { x: 0, y: 0 };
  // position a context menu at (x, y)
});
```

**Debounce high‑frequency events**

```ts
let hoverT;
sdk.on("hover", (e) => {
  clearTimeout(hoverT);
  hoverT = setTimeout(() => {
    // lightweight hover preview
  }, 80);
});
```

***

### Security

Events are delivered from the embedded iframe via `postMessage`. The SDK validates the origin internally. If you attach your own `window.message` listeners, verify `event.origin === "https://floorplan.gospace.app"` before using payloads.
