npm package: @stradahq/react-native-sdk
Description: Strada React Native SDK
Author: Strada API, Inc.
Latest version: 0.1.2

# Strada React Native SDK

The official React Native SDK for embedding Strada Voice chat widget into your mobile app.

## Installation

### Via NPM

```bash
npm install @stradahq/react-native-sdk react-native-webview react-native-safe-area-context
```

### Via Yarn

```bash
yarn add @stradahq/react-native-sdk react-native-webview react-native-safe-area-context
```

## Platform Setup

### Peer dependencies

This SDK relies on autolinked native modules provided by your app:

- react-native-webview
- react-native-safe-area-context

Make sure both are installed in your app (commands above). The SDK declares them as peerDependencies so your app controls the versions.

### iOS

Run CocoaPods install after adding the peers:

```bash
cd ios && pod install
```

## Basic Usage

```typescript
import { useRef } from 'react';
import { View, Button } from 'react-native';
import { StradaWidget, type StradaWidgetRef } from '@stradahq/react-native-sdk';

export default function App() {
  const widgetRef = useRef<StradaWidgetRef>(null);

  return (
    <View style={{ flex: 1 }}>
      <Button title="Open Chat" onPress={() => widgetRef.current?.open()} />

      <StradaWidget
        ref={widgetRef}
        organizationId="your_org_id"
        agentId="your_agent_id"
      />
    </View>
  );
}
```

## Props

| Prop             | Type               | Required | Description                                     |
| ---------------- | ------------------ | -------- | ----------------------------------------------- |
| `organizationId` | `string`           | ✅       | Your Strada organization ID                     |
| `agentId`        | `string`           | ✅       | Your Strada agent ID                            |
| `widgetUrl`      | `string`           | ❌       | Widget URL (defaults to production)             |
| `agentVariables` | `object`           | ❌       | Custom variables to pass to the agent           |
| `metadata`       | `object`           | ❌       | Custom user data to pass to conversations       |
| `secureMetadata` | `object`           | ❌       | Secure metadata (not exposed to client)         |
| `defaultView`    | `'chat' \| 'list'` | ❌       | Default view (defaults to 'chat')               |
| `onReady`        | `function`         | ❌       | Called when widget is ready                     |
| `onChatStart`    | `function`         | ❌       | Called when a chat starts                       |
| `onChatEnd`      | `function`         | ❌       | Called when a chat ends                         |
| `onMinimize`     | `function`         | ❌       | Called when widget is minimized                 |
| `getUserToken`   | `function`         | ❌       | Function to get user authentication token (JWT) |
| `hideButton`     | `boolean`          | ❌       | Hide the default floating chat button           |

## Methods

### `open(options?)`

Open the chat widget.

```typescript
widgetRef.current?.open();

// Open with a different agent
widgetRef.current?.open({ agentId: 'different-agent-id' });
```

### `close()`

Close the chat widget.

```typescript
widgetRef.current?.close();
```

### `toggle()`

Toggle widget open/closed.

```typescript
widgetRef.current?.toggle();
```

### `setMetadata(data)`

Update metadata for the current conversation.

```typescript
widgetRef.current?.setMetadata({
  page: '/checkout',
  cart_total: 99.99
});
```

### `setAgentVariables(data)`

Update agent variables. Changes take effect on next `open()` call.

```typescript
widgetRef.current?.setAgentVariables({
  screenName: 'checkout',
  reason: 'purchase'
});
```

### `setSecureMetadata(data)`

Update secure metadata (not exposed to client-side code).

```typescript
widgetRef.current?.setSecureMetadata({
  internalUserId: 'user_123'
});
```

### `subscribeEvent(eventKey, callback)`

Subscribe to widget events.

```typescript
const subscriptionId = widgetRef.current?.subscribeEvent('strada:ready', (data) => {
  console.log('Widget ready:', data);
});
```

### `unsubscribeEvent(subscriptionId)`

Unsubscribe from events.

```typescript
widgetRef.current?.unsubscribeEvent(subscriptionId);
```

## Events

| Event Key               | Data                    | Description                |
| ----------------------- | ----------------------- | -------------------------- |
| `strada:ready`          | `{ isLoaded: boolean }` | Widget is loaded and ready |
| `strada:button:clicked` | `{}`                    | Floating button clicked    |
| `strada:chat:started`   | `{ chatId: string }`    | Chat session started       |
| `strada:chat:ended`     | `{ chatId: string }`    | Chat session ended         |
| `strada:chat:minimize`  | `{}`                    | Widget was minimized       |

## Advanced Usage

### With User Authentication

Provide a `getUserToken` function to enable authenticated chat sessions:

```typescript
<StradaWidget
  ref={widgetRef}
  organizationId="your_org_id"
  agentId="your_agent_id"
  getUserToken={async () => {
    const response = await fetch('https://your-api.com/strada-token');
    const { token } = await response.json();
    return token;
  }}
/>
```

### With Custom Metadata

Pass user information for analytics and attribution:

```typescript
<StradaWidget
  ref={widgetRef}
  organizationId="your_org_id"
  agentId="your_agent_id"
  metadata={{
    userId: user.id,
    userName: user.name,
    plan: user.subscription,
    language: user.preferredLanguage
  }}
/>
```

### With Agent Variables

Inject data into agent conversations:

```typescript
<StradaWidget
  ref={widgetRef}
  organizationId="your_org_id"
  agentId="your_agent_id"
  agentVariables={{
    first_name: 'John',
    last_name: 'Doe',
    email: 'john@example.com'
  }}
/>
```

### Hide Floating Button

Control widget visibility with your own UI:

```typescript
<StradaWidget
  ref={widgetRef}
  organizationId="your_org_id"
  agentId="your_agent_id"
  hideButton={true}
/>

<Button title="Get Help" onPress={() => widgetRef.current?.open()} />
```

### Per-Context Chat Persistence

Chats are persisted per context (combination of `agentId` + `agentVariables`). This allows different screens or flows to maintain separate conversations:

```typescript
// Mount widget once
<StradaWidget
  ref={widgetRef}
  organizationId="your_org_id"
  agentId="your_agent_id"
  hideButton={true}
/>

// Open with different contexts - each maintains its own chat history
<Button
  title="Sales Help"
  onPress={() => {
    widgetRef.current?.setAgentVariables({ screenName: 'sales', reason: 'inquiry' });
    widgetRef.current?.open();
  }}
/>

<Button
  title="Support Help"
  onPress={() => {
    widgetRef.current?.setAgentVariables({ screenName: 'support', reason: 'help' });
    widgetRef.current?.open();
  }}
/>
```

- Same `agentId` + same `agentVariables` = continues existing chat
- Same `agentId` + different `agentVariables` = separate chat
- Different `agentId` = separate chat

### Start in List View

Open the widget showing the list of recent chats (for authenticated users):

```typescript
<StradaWidget
  ref={widgetRef}
  organizationId="your_org_id"
  agentId="your_agent_id"
  defaultView="list"
  getUserToken={async () => {
    return await getAuthToken();
  }}
/>
```

### Event Handling

Subscribe to lifecycle events:

```typescript
import { useEffect, useRef } from 'react';

export default function App() {
  const widgetRef = useRef(null);

  useEffect(() => {
    const subscriptionId = widgetRef.current?.subscribeEvent(
      'strada:chat:started',
      (data) => {
        console.log('Chat started:', data.chatId);
      }
    );

    return () => {
      if (subscriptionId) {
        widgetRef.current?.unsubscribeEvent(subscriptionId);
      }
    };
  }, []);

  return (
    <StradaWidget
      ref={widgetRef}
      organizationId="your_org_id"
      agentId="your_agent_id"
    />
  );
}
```

### Using the Hook

For a more convenient API, use the `useStradaWidget` hook:

```typescript
import { View, Button } from 'react-native';
import { StradaWidget, useStradaWidget } from '@stradahq/react-native-sdk';

export default function App() {
  const { widgetRef, open, close, toggle, setMetadata } = useStradaWidget();

  return (
    <View style={{ flex: 1 }}>
      <Button title="Open" onPress={open} />
      <Button title="Close" onPress={close} />

      <StradaWidget
        ref={widgetRef}
        organizationId="your_org_id"
        agentId="your_agent_id"
      />
    </View>
  );
}
```

## TypeScript Support

The SDK is written in TypeScript and exports all types:

```typescript
import type {
  StradaWidgetProps,
  StradaWidgetRef,
  StradaEventKey,
  EventCallback,
  WebViewMessage
} from '@stradahq/react-native-sdk';
```

## Development

```bash
# Install dependencies
pnpm install

# Build the SDK
pnpm build

# Watch mode
pnpm dev

# Type check
pnpm typecheck

# Run linter
pnpm lint
```

## Example App

See the complete example app at `/apps/chat-native-example/` for a full working implementation with all features.

## Platform Compatibility

- iOS 12.0+
- Android 5.0+ (API level 21+)
- React Native 0.60+
- React 16.8+ (requires hooks support)

## Support

For issues and questions, contact your Strada team or visit our documentation at https://docs.getstrada.com