# tolky-chat

React component library for rendering chat conversation UIs. Supports text, media (image, audio, video, document), admin messages, ticket events, markdown, reply threading, and i18n.

## Installation

```bash
npm install tolky-chat
```

Peer dependencies: `react >= 18.2.0 < 20`, `react-dom` same range.

## CSS

Import once in your app entry point:

```js
import "tolky-chat/dist/chat.css";
```

## Basic usage

```tsx
import { Conversation } from "tolky-chat";
import "tolky-chat/dist/chat.css";

<Conversation
  conversation={messages}
  language="pt"
  location="manager"
  colors={{ user: { background: "#DCF8C6" } }}
  onMessageInfoClick={(msg) => console.log(msg)}
  onReplyMessageClick={(msg) => console.log(msg)}
/>
```

## `ConversationProps`

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `conversation` | `Message[]` | **required** | Ordered array of messages to render |
| `colors` | `Colors` | `undefined` | Per-role color overrides |
| `location` | `"webchat" \| "manager" \| "minichat"` | `"webchat"` | Surface context; controls which UI chrome is shown |
| `language` | `"pt" \| "en" \| "es"` | `"pt"` | UI string language and date locale |
| `onMessageInfoClick` | `(message) => void` | `undefined` | Fired when info icon clicked. Active at `location: "manager"` on user messages only. |
| `onReplyMessageClick` | `(message) => void` | `undefined` | Fired when reply button clicked. Enabled at `location: "manager"`. |

## Message types

### `MessageCore`

```ts
{
  id?:       string;
  role:      "user" | "system" | "assistant";
  content:   string | string[];
  createdAt?: string;              // ISO 8601
  userId?:   string | null;
  media?:    Media[];
  type?:     "ticket" | "document" | "audio" | "video" | string | null;
  status?:   "sent" | "delivered" | "accepted" | "read" | "failed" | null;
  reason?:   string | null;       // Tooltip text when status="failed"
}
```

### `MessageWithSource` — human agent message

Extends `MessageCore` with:

```ts
{
  source: {
    type:       string | null;
    userName:   string | null;  // Displayed below the bubble
    authUserId: string | null;  // Must be truthy to trigger admin rendering
    from:       string | null;
  }
}
```

### `MessageWithTicket` — ticket lifecycle event

Extends `MessageCore` with:

```ts
{
  type:   "ticket";
  ticket: Ticket;
}
```

### `Media`

```ts
{
  url?:          string;
  convertedUrl?: string | null;
  type:          "img" | "audio" | "video" | "document" | string | null;
  description?:  string | null;   // <img_description> or <document_description> tags
  transcription? string | null;   // <audio_transcription> or <img_transcription> tags
  fileName?:     string | null;
}
```

## Ticket types

### `TicketWithStatus`

```ts
{
  type:          "status";
  id:            string;
  level:         number;
  color:         string;   // "#3182CE" or "3182CE" — both accepted
  label:         string;
  timestamp:     Date | string;
  levelConfigId?: string;
  href?:         string;
  protocol?:     string;
}
```

### `TicketWithMessage`

```ts
{
  type:           "messageBox";
  id:             string;
  timestamp:      Date | string;
  levelConfigId?: string;
  protocol?:      string;
  sentBy: { authUserId: string; userName: string; };
  sendingMethods: Array<{
    type:    "email" | "wpp";
    format:  "html" | "markdown";
    content: string;
  }>;
}
```

### `TicketWithFeedback`

```ts
{
  type:          "feedback";
  id:            string;
  content:       string;
  score:         number;
  color:         string;
  label:         string;
  timestamp:     Date | string;
  levelConfigId?: string;
  protocol?:     string;
}
```

### `TicketWithInfo`

```ts
{
  type:          "info";
  id:            string;
  content:       string;
  timestamp:     Date | string;
  levelConfigId?: string;
  protocol?:     string;
}
```

> `TicketWithInfo` only renders when `location === "manager"`.

## `Colors`

```ts
type Colors = {
  user?:   ColorElements;
  system?: ColorElements;
  admin?:  ColorElements;
}

type ColorElements = {
  background?:        string | null;
  text?:              string | null;
  textLink?:          string | null;
  backgroundLink?:    string | null;
  bgTableHeader?:     string | null;
  borderTable?:       string | null;
  colorCreationTime?: string | null;
}
```

## Extended fields (runtime-only)

Not in the exported TypeScript types, but accepted at runtime:

```ts
type MyMessage = Message & {
  repliedMessageId?: string | { replyMetaId: string } | null;
};
```

Passing `repliedMessageId` shows a quoted preview above the bubble and enables scroll-to-original on click.

## Behavior notes

- `content: string[]` — joined with `\n` before Markdown rendering
- Markdown rendered via `react-markdown` + `remark-gfm` + `rehype-highlight` (tables, code blocks, GFM)
- Bare `www.` links auto-prefixed with `https://`
- `role: "system"` + `type: "text"` messages are silently suppressed (no output)
- `status: ""` treated same as `null` — no indicator shown
- Date separators inserted automatically between messages from different calendar days

---

## Development

```bash
npm install
npm run dev
# Edit mock data in src/main.tsx
# Edit source in lib/
```

## Publishing

```bash
# Bump version in package.json, then:
npm login
npm publish
```
