# PairingFlow

Canonical page: https://docs.ovok.com/native-sdk/guide/components/ui/pairing-flow

`PairingFlow` renders devices discovered by the active Bluetooth runtime, starts
pairing, presents a pairing-code field when the runtime requests one, and remembers
the ID of a device after it becomes bonded. Import it from `@ovok/native/ui` and
render it beneath `BTProvider`.

~~~tsx
import { BTProvider } from "@ovok/native/bt-management";
import { PairingFlow } from "@ovok/native/ui";

<BTProvider bleManager={bleManager} acceptedDevices={acceptedDevices}>
  <PairingFlow
    storage={pairedDeviceStorage}
    onPairingCode={(code, device) => confirmPairingCode(device, code)}
    onPaired={(device) => navigation.navigate("DeviceDetails", { id: device.id })}
    onError={(error, device) => reportPairingError(error, device?.id)}
  />
</BTProvider>
~~~

`BTProvider` owns discovery and the BLE runtime. This component does not create a
manager or start a scan. Supply a `PairedDeviceStorage` implementation; the flow
stores a JSON array of IDs, not device objects or credentials.

## Props [#props]

Every prop, with its type and description, is listed in the [`@ovok/native/ui` API reference](/native-sdk/reference/ui).

## Pairing lifecycle [#pairing-lifecycle]

The flow exposes these statuses through render state and custom device actions:

| Status | Meaning |
| --- | --- |
| `idle` | No pairing attempt is active. |
| `pairing` | `useNearbyDevices().pair` is in progress or awaiting the bond event. |
| `code-required` | A runtime pairing event requested a code; the flow shows its input. |
| `paired` | The selected device emitted a bonded event. |
| `error` | Pairing or code handling failed. |

`onPairingCode` receives the trimmed value and selected runtime device. The flow
does not confirm the code itself; provide a handler for the device's pairing
procedure. A resolved handler returns the status to `pairing`. The matching bonded
event updates the visible status to `paired`; after the underlying pair operation
resolves, the flow stores the ID and calls `onPaired` only if it observed that event.
If the pair operation rejects, the flow reports an error and does not store the ID.

The default row starts pairing and shows optional device image, name, manufacturer,
and pair action. It does not render a forget control. To offer forgetting, supply
`renderDevice` and call `actions.forget()` from your row. That method asks the active
Bluetooth manager to forget the device, then removes its ID from storage; it rejects
if the manager is not ready.

`PairingFlowRenderState` contains `devices`, `paired` IDs, optional `selected`
device, `status`, and optional `error`. `renderHeader` and `renderEmpty` receive this
state. `renderDevice` receives one device and an actions object:

~~~ts
{
  pair: () => Promise<void>;
  forget: () => Promise<void>;
  status: PairingFlowStatus;
}
~~~

The status is shared by the flow's current selection. If rows need independent
per-device state or richer accessibility behavior, own that presentation in the
custom row.

The `labels` keys and default copy are:

| Key | Default |
| --- | --- |
| `header` | Add a device |
| `description` | Wake your monitor and choose it when it appears nearby. |
| `empty` | No supported devices found yet. |
| `device` | Bluetooth device (used when the manufacturer name is empty) |
| `pair` | Pair |
| `pairingCodePrompt` | Type the code your monitor shows |
| `pairingCode` | Pairing code |
| `continue` | Continue |
| `pairing` | Pairing the selected device… |
| `paired` | The selected device is ready. |
| `retry` | Try again |
| `remembered` | A count-specific remembered-device message |

The default pairing, paired, and remembered messages include the selected device
name or count. A value supplied in `labels` replaces the message verbatim; the flow
does not interpolate placeholders in custom strings.

See [Reusable flows](/native-sdk/guide/how-to/reusable-flows) for integration guidance and
[Bluetooth](/native-sdk/guide/modules/bt-management) for provider and device discovery setup.
