# `hb-player-live-camera-ptz` — integrator guide

**Category:** media · **Tags:** media, video, streaming, camera · **Package:** `@htmlbricks/hb-player-live-camera-ptz`

## Summary

`hb-player-live-camera-ptz` embeds a live stream using `hb-player-live` and layers a **PTZ (pan–tilt–zoom) control panel** on top of the video. The component handles the UI only: D-pad or analog joystick (via `hb-pad-joystick`), zoom buttons, go-home confirmation, **click-to-center** (draw a rectangle on the video), optional **grid overlay**, fullscreen, mute, and play/pause. Presets are listed and managed through `hb-dialog` and `hb-table` (add scene, go to preset, delete preset with confirmations).

Your application listens for **custom events** and calls your camera or robotics backend. Movement **speed** and **precision** are edited in the panel (sliders) and included on each movement-related event as `movementSettings`.

**Nested dependencies** (for bundling or CDN ordering) include `hb-player-live`, `hb-pad-joystick`, `hb-table`, and `hb-dialog` (see `extra/docs.ts` for the full tree).

## Custom element

```html
<hb-player-live-camera-ptz …></hb-player-live-camera-ptz>
```

Bootstrap Icons are loaded for toolbar glyphs (see `component.wc.svelte` / `styles/webcomponent.scss`).

## Attributes (snake_case; string values from HTML)

From HTML or `setAttribute`, values are **strings**. Objects and arrays must be **JSON strings**. Booleans should use **`yes`** / **`no`** where possible; the implementation also treats the strings `true` / `false` for some flags when coerced from attributes.

| Attribute | Required | Description |
|-----------|----------|-------------|
| `live_uri` | Yes | Stream URI passed to `hb-player-live` as `mediauri`. |
| `id` | No | Identifier echoed on dispatched events. |
| `style` | No | Host-level inline style (typed on `Component`; forwarding to inner players may vary). |
| `media_type` | No | `"hls"`, `"webrtc"`, `"auto"`, `"whep"`, or `""`. Default in code: `"auto"`. |
| `is_ptz_connected` | No | When falsy after coercion, the PTZ strip and opener are hidden. Use `yes` / `no`. |
| `is_ptz_panel_opened` | No | When falsy, the control panel is collapsed; the opener tab remains if connected. Use `yes` / `no`. |
| `is_home` | No | Drives the home button highlight (`yes` / `no`). |
| `presets` | No | JSON array of presets: `{ token, name, x, y, z }` (see **Preset shape** below). |
| `current_preset` | No | Token of the preset shown as active on the presets button. |
| `position` | No | Typed layout hint (`top`, `right-bottom`, `left-bottom`, `bottom`, `right-top`, `left-top`). **Not wired** in the current stylesheet; reserved for typing / future layout. |
| `configuration` | No | JSON object of feature flags (see **Configuration**). Defaults enable all documented features. |

### Preset shape (`presets` JSON)

Each preset is an object:

- `token` (string): stable id used in UI and events.
- `name` (string): label in the table and button.
- `x`, `y`, `z` (numbers): logical camera pose; the component does not interpret them beyond displaying names/tokens—it forwards them on preset events for your backend.

### Configuration (`configuration` JSON)

All keys are optional; defaults match the in-component `defaultConfiguration`.

| Key | Type | Role |
|-----|------|------|
| `joystick` | boolean | Allow switching between D-pad and analog joystick. |
| `presets` | boolean | Open the presets table dialog. |
| `addPreset` | boolean | “Add scene to preset” flow. |
| `switchPreset` | boolean | Confirm and dispatch go-to preset. |
| `deletePreset` | boolean | Delete preset from table flow. |
| `home` | boolean | Go-home button and confirmation. |
| `zoom.in`, `zoom.out` | boolean | Zoom buttons. |
| `pan`, `tilt` | boolean | Enable D-pad direction events; analog joystick path also checks these flags in code. |
| `clickToCenter` | boolean | Rectangle selection on the video and `goToSelectedArea`. |
| `settings` | boolean | Enables the settings button in the toolbar (handler is currently a **no-op**). |

## Styling (Bulma and CSS variables)

Bulma-oriented variables are documented in `extra/docs.ts` (`styleSetup.vars`). Set public **`--bulma-*`** (and the joystick variable) on the host or `:root` as needed; see [Bulma CSS variables](https://bulma.io/documentation/features/css-variables/).

| Variable | Role |
|----------|------|
| `--bulma-danger` | Click-to-center selection rectangle (`#area_selector`). |
| `--bulma-border` | Grid overlay lines on the video. |
| `--bulma-link` | Toolbar buttons, PTZ accents, active states. |
| `--bulma-text` | Labels in dialogs and toolbars. |
| `--bulma-scheme-main` | Panel / dialog surfaces (with transparency in the panel). |
| `--hb-pad-joystick-size` | Joystick size forwarded to nested `hb-pad-joystick` (see component SCSS). |

**CSS parts:** none on this element (`extra/docs.ts`). Child components may expose their own parts in their docs.

**Slots:** none.

## User-facing behavior

- **Stream:** `hb-player-live` with `no_controls="yes"`; outer toolbar handles mute and play/pause on the underlying `HTMLVideoElement`.
- **Panel visibility:** If `is_ptz_connected` is off, no PTZ UI. If connected but `is_ptz_panel_opened` is off, only the side **opener** control is shown; clicking it toggles the panel and dispatches `panelMove`.
- **Movement UI:** Default mode is **D-pad**; users can switch to **joystick** when `configuration.joystick` is enabled. **Speed** and **precision** sliders update `movementSettings` sent with events.
- **Click to center:** Toggle the square tool, then **two clicks** on the video define a rectangle; on completion the component dispatches `goToSelectedArea` with pixel geometry relative to the video box and the video’s width/height.
- **Presets:** “+” opens add confirmation → `setPreset`. Presets button opens `hb-table`; row actions trigger go/delete confirmations → `goToPreset` / `deletePreset`.
- **Fullscreen:** Requests fullscreen on the video element (browser UX).

## Events

Listen with `addEventListener` or framework equivalents. Payloads match `types/webcomponent.type.d.ts`.

| Event | `detail` summary |
|-------|------------------|
| `initVideo` | `{ id, time, htmlVideoElement }` — fired after the inner player exposes the video node. |
| `panelMove` | `{ id, opened }` — panel opened or closed via the opener control. |
| `goToHome` | `{ id, movementSettings, time }` — user confirmed home (types); wire to your PTZ home command. |
| `goToSelectedArea` | `{ id, movementSettings, time, top, left, width, height, htmlVideoElementWidth, htmlVideoElementHeight }` — rectangle in video coordinates plus intrinsic video layout size. |
| `setPreset` | `{ id, time }` — user confirmed adding the current scene as a preset; your backend should persist and then update `presets` / `current_preset` via attributes or properties. |
| `goToPreset` | Preset fields (`token`, `name`, `x`, `y`, `z`) plus `{ playerId, movementSettings, time }`. |
| `deletePreset` | Preset fields plus `{ playerId, time }`. |
| `zoomAction` | `{ id, movementSettings, direction: "in" \| "out", time }`. |
| `sendJoystickPosition` | `{ id, joyId, movementSettings, x, y, cardinalDirection, time }` — analog joystick samples (`CardinalDirection` in types). |
| `sendDirection` | `{ id, joyId, movementSettings, direction: "up" \| "right" \| "down" \| "left" }`. |

`movementSettings` is `{ speed: number; precision: number }` (defaults `50` / `50` in the component, user-adjustable in the panel).

## Integration checklist

1. Set `live_uri` and `media_type` appropriately for your stack (HLS, WebRTC, WHEP, etc.).
2. Set `is_ptz_connected="yes"` when your session can accept PTZ commands.
3. Subscribe to **movement and preset** events and translate them to your API.
4. Push updated **`presets`** (JSON string) and **`current_preset`** from your server or client state when presets change.
5. Optionally toggle **`configuration`** JSON to disable controls your backend does not support.

## Minimal HTML example

```html
<hb-player-live-camera-ptz
  id="cam-1"
  live_uri="https://example.com/live/stream.m3u8"
  media_type="auto"
  is_ptz_connected="yes"
  is_ptz_panel_opened="yes"
></hb-player-live-camera-ptz>

<script>
  const el = document.querySelector("hb-player-live-camera-ptz");
  el.addEventListener("sendDirection", (e) => {
    console.log(e.detail);
  });
</script>
```

### Example with presets (JSON attributes)

```html
<hb-player-live-camera-ptz
  live_uri="https://example.com/live/stream.m3u8"
  media_type="auto"
  is_ptz_connected="yes"
  current_preset="preset1"
  presets='[{"token":"preset1","name":"Door","x":0,"y":0,"z":0},{"token":"preset2","name":"Yard","x":0,"y":0,"z":0}]'
></hb-player-live-camera-ptz>
```

## TypeScript typings (authoring)

`types/webcomponent.type.d.ts` — **`Component`**, **`Events`**, **`TPreset`**, **`TMovementSettings`**. Metadata: `extra/docs.ts`. Implementation: `component.wc.svelte`. Generated consumer typings: package `types/html-elements.d.ts` and `types/svelte-elements.d.ts` after `npm run build:wc`.
