# ChatBot SDK

Vanilla TypeScript + CSS chatbot UI SDK for popup and full-page embeds.

It ships with:

- `ChatBotSDK.init(config)` for direct setup
- `ChatBotSDK.initFromElement(...)` and `autoInitChatBotSDK()` for `data-*` driven pages
- built-in mock response fallback for local UI work before your backend exists
- text replies, generic card carousel rendering, and quick replies
- typed request/response contracts for custom API integration

## Install

```bash
npm install @soul_hope/chatbot-sdk
```

## Browser script build

Running `npm run build` now generates these browser-ready files:

- `dist/browser/chatbot-sdk.js`
- `dist/browser/chatbot-sdk.min.js`

They are meant for plain `<script src="...">` usage and expose `window.ChatBotSDK`.

```html
<link rel="stylesheet" href="/path/to/chatbot-sdk.css" />
<script src="/path/to/chatbot-sdk.min.js"></script>
<script>
  ChatBotSDK.init({
    container: "#chatbot",
    productType: "popup",
    apiUrl: "/chatbot-api",
    apiMethod: "GET"
  });
</script>
```

From the browser bundle, you can use:

- `ChatBotSDK.init(...)`
- `ChatBotSDK.autoInitChatBotSDK()`
- `ChatBotSDK.createChatBotApiRequest(...)`
- `ChatBotSDK.exampleResponse`

## Import

```ts
import {
  ChatBotSDK,
  autoInitChatBotSDK,
  createChatBotApiRequest,
  exampleResponse
} from "@soul_hope/chatbot-sdk";
import "@soul_hope/chatbot-sdk/styles.css";
```

## Quick start

If you do not pass `api.request` or `mockResponse`, the SDK automatically falls back to its built-in `exampleResponse`.
If `container: "#chatbot"` does not already exist, the SDK now creates `<div id="chatbot"></div>` for you automatically.

```ts
const chatbot = ChatBotSDK.init({
  container: "#chatbot",
  productType: "popup",
  recipientId: "123456"
});
```

`ChatBotSDK.init(...)` returns a `ChatBotSDK` instance, so you can control the widget later if needed.

## Use a custom mock response

This is useful when you want the real UI and payload flow before your backend API is ready.

```ts
ChatBotSDK.init({
  container: "#chatbot",
  productType: "popup",
  recipientId: "123456",
  mockResponse: async (payload) => ({
    ...exampleResponse,
    message: {
      ...exampleResponse.message,
      text: `Mock response for "${payload.text}"`
    }
  })
});
```

## Connect your own API

### Easiest way: pass `apiUrl`

```ts
ChatBotSDK.init({
  container: "#chatbot",
  productType: "full",
  recipientId: "123456",
  apiUrl: "https://your-api-url.com/chat",
  apiMethod: "POST",
  primaryColor: "#d26a3c"
});
```

### Manual way: build a request handler

If you want custom headers or want to reuse the SDK's default fetch logic directly:

```ts
const request = createChatBotApiRequest({
  apiUrl: "https://your-api-url.com/chat",
  apiMethod: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_KEY"
  }
});

ChatBotSDK.init({
  container: "#chatbot",
  productType: "full",
  recipientId: "123456",
  api: { request }
});
```

### Fully custom way: provide your own `api.request`

```ts
ChatBotSDK.init({
  container: "#chatbot",
  productType: "full",
  recipientId: "123456",
  api: {
    request: async (payload) => {
      const response = await fetch("https://your-api-url.com/chat", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: "Bearer YOUR_API_KEY"
        },
        body: JSON.stringify(payload)
      });

      return response.json();
    }
  }
});
```

Your `api.request` function receives a typed `ChatRequestPayload` and must return a `Promise<ChatResponse>`.

## Initialize from HTML attributes

You can keep your JavaScript mostly static and configure each page from HTML or Blade.

`resources/js/app.js`

```ts
import "./bootstrap";
import { autoInitChatBotSDK } from "@soul_hope/chatbot-sdk";
import "@soul_hope/chatbot-sdk/styles.css";

document.addEventListener("DOMContentLoaded", () => {
  autoInitChatBotSDK();
});
```

`resources/views/welcome.blade.php`

```blade
<div
  data-chatbot-sdk
  data-api-url="/chatbot-api"
  data-product-type="popup"
  data-primary-color="#d26a3c"
  data-title="Travel Concierge"
  data-recipient-id="123456"
  data-language="en"
  data-placeholder="Type your message..."
></div>
```

Supported attributes:

- `data-api-url`
- `data-api-method="GET"` or `data-api-method="POST"`
- `data-primary-color="#d26a3c"`
- `data-product-type="popup"` or `data-product-type="full"`
- `data-title`
- `data-language`
- `data-placeholder`
- `data-recipient-id`

If `data-api-url` is present, the SDK creates a default `fetch`-based request handler for you.
`GET` sends the chatbot payload as query parameters, and `POST` sends it as JSON.

You can also initialize a single element manually:

```ts
ChatBotSDK.initFromElement("#chatbot-root", {
  productType: "full"
});
```

`autoInitChatBotSDK()` returns `ChatBotSDK[]`, one instance per matching element.

## Instance methods

```ts
const chatbot = ChatBotSDK.init({
  container: "#chatbot",
  productType: "popup"
});

chatbot.open();
chatbot.close();
chatbot.destroy();
```

Notes:

- `open()` and `close()` only affect the `popup` variant
- `destroy()` clears the mounted SDK markup from the container

## Config

```ts
type ChatBotSDKConfig = {
  container: string | HTMLElement;
  productType?: "popup" | "full";
  language?: "en";
  title?: string;
  placeholder?: string;
  primaryColor?: string;
  recipientId?: string;
  apiUrl?: string;
  apiMethod?: "GET" | "POST";
  api?: {
    request?: (payload: ChatRequestPayload) => Promise<ChatResponse>;
  };
  mockResponse?:
    | ChatResponse
    | ((payload: ChatRequestPayload) => Promise<ChatResponse> | ChatResponse);
};
```

## Request and response shape

```ts
type ChatRequestPayload = {
  recipientId?: string;
  text: string;
  type: "text" | "quick_reply" | "postback";
  payload?: string;
};

type ChatResponse = {
  recipient: {
    id: string;
  };
  message: {
    text?: string;
    attachment?: {
      type: "template";
      payload: {
        template_type: "generic";
        elements: GenericElement[];
      };
    };
    quick_replies?: QuickReply[];
  };
};
```

For a working reference payload, use either:

- `exampleResponse` from the package
- `@soul_hope/chatbot-sdk/mock-response.json`
- `examples/mock-response.json` in this repository

## Local development

```bash
npm install
npm run build
```

Then serve the repository root with any local static server and open `examples/index.html`.
