# Service map
> Pan-and-zoom map of demo hosts and their services, linked by proxy routes and dependencies that carry live request traffic.
- Element: `<sv-map>`
- React: `import { SvMap } from "@/components/lumesec/sv-map"`
- Collection: Service Map (https://elements.lumesec.ai/components/service-map)
- Registry item: https://elements.lumesec.ai/r/sv-map.json
- Page: https://elements.lumesec.ai/components/service-map/map



Live preview: https://elements.lumesec.ai/view/sv-map

```html
<sv-shell>
  <svg slot="brand">…lockup…</svg>
  <sv-map slot="main" fill></sv-map>
</sv-shell>
```

## Playground

Change a prop and the component updates. Props marked live animate to the new value; the others rebuild the element.

## Installation

```bash
npx shadcn@latest add @lumesec/sv-map
```

First time with the @lumesec registry? Register it once, or install by URL:

```bash
npx shadcn@latest registry add @lumesec=https://elements.lumesec.ai/r/{name}.json
npx shadcn@latest add https://elements.lumesec.ai/r/sv-map.json
```

## Usage

React:

```tsx
import { SvShell } from "@/components/lumesec/sv-shell";
import { SvMap } from "@/components/lumesec/sv-map";

export function Example() {
  return (
    <SvShell>
      <span slot="brand">Your logo</span>
      <SvMap slot="main" fill />
    </SvShell>
  );
}
```

HTML:

```html
<script type="module" src="https://elements.lumesec.ai/cdn/sv-shell.js"></script>
<script type="module" src="https://elements.lumesec.ai/cdn/sv-map.js"></script>

<sv-shell>
  <span slot="brand">Your logo</span>
  <sv-map slot="main" fill></sv-map>
</sv-shell>
```

## Behaviour

Hosts as cards, each listing its services and the ports they listen on. Lines show the reverse proxy routes, the direct dependencies and, on request, the monitoring scrapes. Select a service to see its ports, its consumers and the domains that reach it; select a host to see every occupied port and to add a service, with port conflicts caught as you type.

## API reference

### Attributes

| Attribute | React prop | Type      | Default                     | Description                                                                                                                                              |
| --------- | ---------- | --------- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `label`   | `label`    | `string`  | `Innsbruck HQ · Production` | Title shown in the toolbar. Read once on first connect.                                                                                                  |
| `height`  | `height`   | `number`  | `600`                       | Stage height in pixels. Without it the stage is 600 px tall in wide containers and sizes itself to the content under 640 px. Read once on first connect. |
| `fill`    | `fill`     | `boolean` | `false`                     | Presence attribute. The map fills the height of its parent, with a stage of at least 360 px. Use it for `<sv-map slot="main" fill>` inside `sv-shell`.   |

### Events

Events bubble and cross the shadow boundary unless the description says otherwise.

| Event    | React prop | Detail                                                                                                                                                                                                          | Description                                                                                                                                                                                                                  |
| -------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `select` | `onSelect` | `{ svc: string } \| { host: string }`                                                                                                                                                                           | Fires when a service row or host card is selected by click, Enter or Space, or from the inspector. `svc` is a service id such as `api-1`, `host` a host id such as `db-01`. Clearing the selection does not fire it.         |
| `follow` | `onFollow` | `{ route: string, services: string[] }`                                                                                                                                                                         | Fires when a route is chosen in the Follow menu. `route` is host plus path (`api.lumesec.local/v1/infer`), `services` the ids of the upstreams and every service they depend on.                                             |
| `change` | `onChange` | `{ action: 'add-service', host: string, service: string, port: number } \| { action: 'remove-service', service: string, host: string } \| { action: 'add-dependency', from: string, to: string, port: number }` | Fires when the plan changes: a service added from the host inspector (`service` is its name), a service removed in Edit mode, or a dependency drawn in Edit mode (`from` and `to` are service ids). `sv-shell` queues these. |
| `move`   | `onMove`   | `{ host: string, x: number, y: number }`                                                                                                                                                                        | Fires after a host card is dragged with the pointer, with its new world position in pixels. Keyboard moves do not fire it.                                                                                                   |

### Methods

Call them on the element, for example through a React ref.

| Method                                                        | Description                                                                                                                                   |
| ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `applyPlanned()`                                              | Marks every planned service as running and redraws the affected hosts. `sv-shell` calls it after Apply.                                       |
| `select(target: { svc: string } \| { host: string } \| null)` | Selects a service or host and opens the inspector, as a click does, and fires `select`. `null` clears the selection.                          |
| `follow(routeId: string)`                                     | Highlights the path of a demo route (`r1` to `r6`) and fires `follow`. An empty string clears the highlight. Does not update the Follow menu. |
| `fit()`                                                       | Fits all hosts into view.                                                                                                                     |

## Keyboard

| Keys                                         | Action                                                                                        |
| -------------------------------------------- | --------------------------------------------------------------------------------------------- |
| Enter / Space                                | On a host header or service row: select it and open the inspector.                            |
| Escape                                       | Clear the selection and close the inspector. In an inspector field: leave the field instead.  |
| ArrowLeft / ArrowRight / ArrowUp / ArrowDown | On a host header: move the host card by 10 px.                                                |
| Shift + Arrow keys                           | On a host header: move the host card by 40 px.                                                |
| + / =                                        | Anywhere in the stage except a host header, service row or form field: zoom in.               |
| -                                            | Anywhere in the stage except a host header, service row or form field: zoom out.              |
| 0                                            | Anywhere in the stage except a host header, service row or form field: fit all hosts in view. |
| Delete / Backspace                           | On a service row in Edit mode: remove the service. Internet clients cannot be removed.        |

## Accessibility

* The stage is a focusable `role="application"` region whose `aria-label` describes the keyboard model.
* Host headers and service rows are focusable `role="button"` elements; service labels include the host, ports and status.
* The Routes, Dependencies, Monitoring and Edit toggles use `aria-pressed`. The Follow menu and the zoom buttons have `aria-label`s.
* A polite live region announces selections, followed routes and added services.
* In the add-service form an invalid port sets `aria-invalid="true"` and the message is in an assertive live region.
* The traffic canvas and the legend are `aria-hidden`.
* When an action inside the inspector rebuilds it (Show host, an entry under Consumes or Consumed by, or adding a service), focus moves to its Close button. When the inspector closes while focus is inside it (Close, Remove or Escape), focus moves to the stage.
* Reduced motion: request particles are not drawn and Fit jumps instead of easing; the inspector slide-in and new-row animation are switched off. Centring on a selected host still eases.

## Theming

The element reads your shadcn theme tokens through its shadow root, so light and dark follow your theme. The accent comes from `--lumesec`. See [Theming](/docs/theming).

This component reads `--background`, `--border`, `--card`, `--foreground`, `--lumesec`, `--lumesec-info`, `--muted` and `--muted-foreground`.

To restyle only LumeSec elements, set the matching `--ui-*` overrides: `--ui-accent`, `--ui-border`, `--ui-fg`, `--ui-fg2`, `--ui-info`, `--ui-mono`, `--ui-muted`, `--ui-page`, `--ui-raised` and `--ui-surface`.

## Notes

* Renders the shared demo infrastructure `INFRA` from `registry/lib/lumesec/service.ts`: the Internet plus 9 hosts, 19 services, their edges and 6 proxy routes. No attribute selects a subset.
* Edits stay inside the element. Added services are drawn as Planned, with dashed links, until `applyPlanned()` runs.
* Pointer: drag the background to pan, drag a host card to move it, Ctrl or Cmd + wheel to zoom between 35% and 200%. In Edit mode, drag from a service handle onto another service to add a dependency.
* Container query: under 640 px the legend and totals are hidden and the scale is fixed at 60%.
* Attributes are not observed; set them before the element connects.


