<!-- source-hash: 9e073aef3e517df1b4ab46b93212f4cb -->
Provides a React hook for managing NATS WebSocket dialog subscriptions with shared connection pooling, automatic reconnection with exponential backoff, and multi-topic support.

## Key Components

### `useNatsDialogSubscription(options)`
The primary exported hook that manages the full lifecycle of a NATS dialog subscription.

**Parameters (`UseNatsDialogSubscriptionOptions`):**

| Option | Description |
|--------|-------------|
| `enabled` | Toggles the connection/subscription on or off |
| `dialogId` | The dialog ID to subscribe to (e.g., `chat.<dialogId>.<topic>`) |
| `topics` | Array of `NatsMessageType` values to subscribe to (default: `['message']`) |
| `onEvent` | Callback fired when a NATS message is received |
| `onConnect` / `onDisconnect` | Lifecycle callbacks for connection state changes |
| `onSubscribed` | Fired when subscriptions are successfully established |
| `onBeforeReconnect` | Async hook called before each reconnection attempt (e.g., token refresh) |
| `getNatsWsUrl` | Factory function returning the WebSocket URL |
| `clientConfig` | Optional NATS client config overrides (`name`, `user`, `pass`) |
| `reconnectionBackoff` | Configures retry delays: `fastRetries`, `initialDelayMs`, `maxDelayMs`, `multiplier` |

**Returns (`UseNatsDialogSubscriptionReturn`):** `{ isConnected, isSubscribed, reconnectionCount }`

### `SharedConnection` (module-level singleton)
A module-scoped singleton that reference-counts active consumers sharing the same WebSocket URL, with a deferred close delay (`SHARED_CLOSE_DELAY_MS`) to avoid reconnect churn during component remounts.

## Usage Example

```typescript
import { useNatsDialogSubscription } from './use-nats-dialog-subscription'

function DialogListener({ dialogId }: { dialogId: string }) {
  const { isConnected, isSubscribed, reconnectionCount } = useNatsDialogSubscription({
    enabled: true,
    dialogId,
    topics: ['message', 'admin-message'],
    getNatsWsUrl: () => 'ws://nats.example.com:4223',
    onEvent: (event, messageType) => {
      console.log(`[${messageType}]`, event)
    },
    onConnect: () => console.log('NATS connected'),
    onDisconnect: () => console.log('NATS disconnected'),
    onBeforeReconnect: async () => {
      await refreshAuthToken() // e.g., refresh JWT before retry
    },
    reconnectionBackoff: {
      fastRetries: 3,
      fastRetryDelayMs: 500,
      initialDelayMs: 1000,
      maxDelayMs: 30000,
      multiplier: 2,
    },
  })

  return <div>Connected: {isConnected ? 'Yes' : 'No'} | Reconnects: {reconnectionCount}</div>
}
```

## Notes

- Reconnection uses **jittered exponential backoff** (`delay * (0.5 + random * 0.5)`) to avoid thundering herd scenarios.
- Callbacks (`onEvent`, `onConnect`, etc.) are stored in stable refs, so they never trigger reconnection when their identity changes.
- The shared connection is scoped per WebSocket URL — switching URLs tears down the old connection before establishing a new one.