tchao 0.1.3 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +132 -99
- package/dist/npm.d.mts +102 -5
- package/dist/npm.d.ts +102 -5
- package/dist/npm.js +1 -1
- package/dist/npm.js.map +1 -1
- package/dist/npm.mjs +1 -1
- package/dist/npm.mjs.map +1 -1
- package/dist/react.d.mts +68 -0
- package/dist/react.d.ts +68 -0
- package/dist/react.js +2 -0
- package/dist/react.js.map +1 -0
- package/dist/react.mjs +2 -0
- package/dist/react.mjs.map +1 -0
- package/package.json +18 -2
package/README.md
CHANGED
|
@@ -4,8 +4,6 @@ JavaScript SDK for integrating the Tchao chat widget into your application.
|
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
|
-
### Option 1: npm package
|
|
8
|
-
|
|
9
7
|
```bash
|
|
10
8
|
npm install tchao
|
|
11
9
|
# or
|
|
@@ -14,32 +12,61 @@ pnpm add tchao
|
|
|
14
12
|
yarn add tchao
|
|
15
13
|
```
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
## Quick Start
|
|
18
16
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
### React (Recommended)
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import { useTchao } from "tchao/react";
|
|
21
|
+
|
|
22
|
+
function App() {
|
|
23
|
+
const { isReady, open, identify } = useTchao({
|
|
24
|
+
websiteId: "your-website-id",
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Identify user when ready
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (isReady && user) {
|
|
30
|
+
identify({ email: user.email, name: user.name });
|
|
31
|
+
}
|
|
32
|
+
}, [isReady, user, identify]);
|
|
33
|
+
|
|
34
|
+
return <button onClick={() => open()}>Chat with us</button>;
|
|
35
|
+
}
|
|
24
36
|
```
|
|
25
37
|
|
|
26
|
-
|
|
38
|
+
### React Provider (Simpler)
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
import { TchaoProvider } from "tchao/react";
|
|
42
|
+
|
|
43
|
+
function Layout({ children }) {
|
|
44
|
+
return (
|
|
45
|
+
<>
|
|
46
|
+
<TchaoProvider
|
|
47
|
+
websiteId="your-website-id"
|
|
48
|
+
visitor={{ email: user?.email, name: user?.name }}
|
|
49
|
+
/>
|
|
50
|
+
{children}
|
|
51
|
+
</>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
```
|
|
27
55
|
|
|
28
|
-
###
|
|
56
|
+
### Vanilla JavaScript
|
|
29
57
|
|
|
30
58
|
```typescript
|
|
31
|
-
import {
|
|
59
|
+
import { tchao } from "tchao";
|
|
32
60
|
|
|
33
|
-
// Initialize
|
|
34
|
-
|
|
35
|
-
websiteId: "your-website-id",
|
|
36
|
-
});
|
|
61
|
+
// Initialize (call once)
|
|
62
|
+
await tchao.init({ websiteId: "your-website-id" });
|
|
37
63
|
|
|
38
|
-
//
|
|
39
|
-
|
|
64
|
+
// All methods are safe - no try/catch needed
|
|
65
|
+
tchao.identify({ email: "user@example.com" });
|
|
66
|
+
tchao.open();
|
|
40
67
|
```
|
|
41
68
|
|
|
42
|
-
### Script
|
|
69
|
+
### Script Tag
|
|
43
70
|
|
|
44
71
|
```html
|
|
45
72
|
<script
|
|
@@ -47,123 +74,129 @@ widget.open();
|
|
|
47
74
|
data-website-id="your-website-id"
|
|
48
75
|
></script>
|
|
49
76
|
<script>
|
|
50
|
-
// Widget auto-initializes
|
|
51
|
-
window.Tchao.
|
|
52
|
-
|
|
53
|
-
// Listen for events
|
|
54
|
-
window.Tchao.on("ready", () => {
|
|
55
|
-
console.log("Widget ready!");
|
|
56
|
-
});
|
|
77
|
+
// Widget auto-initializes
|
|
78
|
+
window.Tchao.identify({ email: "user@example.com" });
|
|
57
79
|
</script>
|
|
58
80
|
```
|
|
59
81
|
|
|
60
82
|
## API Reference
|
|
61
83
|
|
|
62
|
-
### `
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
84
|
+
### React Hook: `useTchao(config)`
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
import { useTchao } from "tchao/react";
|
|
88
|
+
|
|
89
|
+
const {
|
|
90
|
+
isReady, // boolean - widget is initialized
|
|
91
|
+
isLoading, // boolean - widget is loading
|
|
92
|
+
error, // Error | null - initialization error
|
|
93
|
+
show, // () => void
|
|
94
|
+
hide, // () => void
|
|
95
|
+
toggle, // () => void
|
|
96
|
+
open, // (message?: string) => void
|
|
97
|
+
identify, // (info: VisitorInfo) => void
|
|
98
|
+
config, // () => Partial<WidgetConfig>
|
|
99
|
+
on, // (event, callback) => void
|
|
100
|
+
off, // (event, callback) => void
|
|
101
|
+
} = useTchao({ websiteId: "..." });
|
|
71
102
|
```
|
|
72
103
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
### Instance Methods
|
|
76
|
-
|
|
77
|
-
#### `widget.show()`
|
|
78
|
-
|
|
79
|
-
Show the widget launcher button.
|
|
104
|
+
### Safe API: `tchao`
|
|
80
105
|
|
|
81
|
-
|
|
106
|
+
All methods are safe to call at any time - they will queue and execute when ready.
|
|
82
107
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
#### `widget.toggle()`
|
|
86
|
-
|
|
87
|
-
Toggle the chat window open/closed.
|
|
88
|
-
|
|
89
|
-
#### `widget.open()`
|
|
90
|
-
|
|
91
|
-
Open the chat window.
|
|
108
|
+
```typescript
|
|
109
|
+
import { tchao } from "tchao";
|
|
92
110
|
|
|
93
|
-
|
|
111
|
+
// Initialize
|
|
112
|
+
await tchao.init({ websiteId: "your-website-id" });
|
|
94
113
|
|
|
95
|
-
|
|
114
|
+
// Control methods (safe before/after init)
|
|
115
|
+
tchao.show();
|
|
116
|
+
tchao.hide();
|
|
117
|
+
tchao.toggle();
|
|
118
|
+
tchao.open();
|
|
119
|
+
tchao.open("I need help with...");
|
|
96
120
|
|
|
97
|
-
|
|
98
|
-
|
|
121
|
+
// Identify visitor
|
|
122
|
+
tchao.identify({
|
|
99
123
|
email: "user@example.com",
|
|
100
124
|
name: "John Doe",
|
|
101
125
|
avatar: "https://example.com/avatar.jpg",
|
|
102
|
-
metadata: {
|
|
103
|
-
plan: "pro",
|
|
104
|
-
userId: "12345",
|
|
105
|
-
},
|
|
126
|
+
metadata: { plan: "pro", userId: "123" },
|
|
106
127
|
});
|
|
107
|
-
```
|
|
108
128
|
|
|
109
|
-
|
|
129
|
+
// Events
|
|
130
|
+
tchao.on("message", (msg) => console.log(msg));
|
|
131
|
+
tchao.on("open", () => console.log("Opened"));
|
|
132
|
+
tchao.on("close", () => console.log("Closed"));
|
|
133
|
+
tchao.on("ready", () => console.log("Ready"));
|
|
110
134
|
|
|
111
|
-
|
|
135
|
+
// Cleanup
|
|
136
|
+
tchao.destroy();
|
|
112
137
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
position: "bottom-left", // 'bottom-right' | 'bottom-left'
|
|
116
|
-
primaryColor: "#6366f1",
|
|
117
|
-
themeMode: "dark", // 'light' | 'dark' | 'system'
|
|
118
|
-
});
|
|
138
|
+
// Status
|
|
139
|
+
tchao.isReady(); // boolean
|
|
119
140
|
```
|
|
120
141
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
Subscribe to widget events.
|
|
142
|
+
### Init Config
|
|
124
143
|
|
|
125
144
|
```typescript
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
widget.on("ready", () => {
|
|
139
|
-
console.log("Widget ready");
|
|
145
|
+
tchao.init({
|
|
146
|
+
websiteId: "required",
|
|
147
|
+
host: "https://tchao.app", // optional, for self-hosted
|
|
148
|
+
position: "bottom-right", // "bottom-right" | "bottom-left"
|
|
149
|
+
primaryColor: "#6366f1",
|
|
150
|
+
themeMode: "system", // "light" | "dark" | "system"
|
|
151
|
+
widgetStyle: "bubble", // "bubble" | "name_line" | "question_cta"
|
|
152
|
+
agentName: "Support",
|
|
153
|
+
agentRole: "Customer Support",
|
|
154
|
+
agentImage: "https://...",
|
|
155
|
+
agentWelcomeMessage: "Hi! How can I help?",
|
|
156
|
+
hidePoweredBy: false,
|
|
140
157
|
});
|
|
141
158
|
```
|
|
142
159
|
|
|
143
|
-
|
|
160
|
+
### Events
|
|
161
|
+
|
|
162
|
+
| Event | Callback | Description |
|
|
163
|
+
|-------|----------|-------------|
|
|
164
|
+
| `message` | `(message: Message) => void` | New message received |
|
|
165
|
+
| `open` | `() => void` | Chat window opened |
|
|
166
|
+
| `close` | `() => void` | Chat window closed |
|
|
167
|
+
| `ready` | `() => void` | Widget initialized |
|
|
144
168
|
|
|
145
|
-
|
|
169
|
+
### TypeScript
|
|
146
170
|
|
|
147
171
|
```typescript
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
172
|
+
import type {
|
|
173
|
+
TchaoConfig,
|
|
174
|
+
TchaoInstance,
|
|
175
|
+
VisitorInfo,
|
|
176
|
+
Message,
|
|
177
|
+
WidgetConfig,
|
|
178
|
+
TchaoEvent,
|
|
179
|
+
TchaoEventMap,
|
|
180
|
+
} from "tchao";
|
|
181
|
+
|
|
182
|
+
// React types
|
|
183
|
+
import type { UseTchaoOptions, UseTchaoReturn } from "tchao/react";
|
|
151
184
|
```
|
|
152
185
|
|
|
153
|
-
|
|
186
|
+
## Migration from v0.1.3
|
|
154
187
|
|
|
155
|
-
|
|
188
|
+
The API is backward compatible. New additions:
|
|
156
189
|
|
|
157
190
|
```typescript
|
|
158
|
-
|
|
159
|
-
|
|
191
|
+
// New: Safe API (no try/catch needed)
|
|
192
|
+
import { tchao } from "tchao";
|
|
193
|
+
tchao.identify({ email: "..." }); // Works before init!
|
|
160
194
|
|
|
161
|
-
|
|
195
|
+
// New: React hook
|
|
196
|
+
import { useTchao } from "tchao/react";
|
|
162
197
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
```typescript
|
|
166
|
-
import type { TchaoConfig, TchaoInstance, VisitorInfo, Message } from "tchao";
|
|
198
|
+
// New: React provider
|
|
199
|
+
import { TchaoProvider } from "tchao/react";
|
|
167
200
|
```
|
|
168
201
|
|
|
169
202
|
## License
|
package/dist/npm.d.mts
CHANGED
|
@@ -8,30 +8,127 @@ type WidgetConfig = {
|
|
|
8
8
|
websiteId: string;
|
|
9
9
|
position?: "bottom-right" | "bottom-left";
|
|
10
10
|
primaryColor?: string;
|
|
11
|
+
widgetStyle?: "bubble" | "name_line" | "question_cta";
|
|
12
|
+
themeMode?: "light" | "dark" | "system";
|
|
13
|
+
agentName?: string;
|
|
14
|
+
agentRole?: string;
|
|
15
|
+
agentImage?: string;
|
|
16
|
+
agentWelcomeMessage?: string;
|
|
17
|
+
hidePoweredBy?: boolean;
|
|
18
|
+
bubbleIcon?: string;
|
|
11
19
|
};
|
|
12
20
|
type TchaoConfig = {
|
|
13
21
|
websiteId: string;
|
|
14
22
|
host?: string;
|
|
23
|
+
convexUrl?: string;
|
|
24
|
+
position?: "bottom-right" | "bottom-left";
|
|
25
|
+
primaryColor?: string;
|
|
26
|
+
widgetStyle?: "bubble" | "name_line" | "question_cta";
|
|
27
|
+
themeMode?: "light" | "dark" | "system";
|
|
28
|
+
agentName?: string;
|
|
29
|
+
agentRole?: string;
|
|
30
|
+
agentImage?: string;
|
|
31
|
+
agentWelcomeMessage?: string;
|
|
32
|
+
hidePoweredBy?: boolean;
|
|
33
|
+
bubbleIcon?: string;
|
|
34
|
+
};
|
|
35
|
+
type Message = {
|
|
36
|
+
content: string;
|
|
37
|
+
sender: string;
|
|
38
|
+
timestamp: number;
|
|
39
|
+
};
|
|
40
|
+
type TchaoEventMap = {
|
|
41
|
+
message: (message: Message) => void;
|
|
42
|
+
open: () => void;
|
|
43
|
+
close: () => void;
|
|
44
|
+
ready: () => void;
|
|
15
45
|
};
|
|
46
|
+
type TchaoEvent = keyof TchaoEventMap;
|
|
16
47
|
type TchaoInstance = {
|
|
17
48
|
show: () => void;
|
|
18
49
|
hide: () => void;
|
|
19
50
|
toggle: () => void;
|
|
20
|
-
open: () => void;
|
|
51
|
+
open: (message?: string) => void;
|
|
52
|
+
identify: (info: VisitorInfo) => void;
|
|
53
|
+
config: () => Partial<WidgetConfig>;
|
|
54
|
+
on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;
|
|
55
|
+
off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;
|
|
56
|
+
destroy: () => void;
|
|
57
|
+
isReady: () => boolean;
|
|
58
|
+
};
|
|
59
|
+
type InternalTchaoInstance = {
|
|
60
|
+
show: () => void;
|
|
61
|
+
hide: () => void;
|
|
62
|
+
toggle: () => void;
|
|
63
|
+
open: (message?: string) => void;
|
|
21
64
|
identify: (info: VisitorInfo) => void;
|
|
22
|
-
config: (
|
|
65
|
+
config: () => Partial<WidgetConfig>;
|
|
23
66
|
on: (event: string, callback: (...args: unknown[]) => void) => void;
|
|
24
67
|
off: (event: string, callback: (...args: unknown[]) => void) => void;
|
|
25
|
-
destroy: () => void;
|
|
26
68
|
};
|
|
27
69
|
declare global {
|
|
28
70
|
interface Window {
|
|
29
|
-
Tchao?:
|
|
71
|
+
Tchao?: InternalTchaoInstance;
|
|
72
|
+
__TCHAO_CONFIG__?: TchaoConfig;
|
|
30
73
|
}
|
|
31
74
|
}
|
|
32
75
|
declare function init(config: TchaoConfig): Promise<TchaoInstance>;
|
|
76
|
+
/**
|
|
77
|
+
* Safe API that works before initialization.
|
|
78
|
+
* Calls are queued and executed once the widget is ready.
|
|
79
|
+
*/
|
|
80
|
+
declare const tchao: {
|
|
81
|
+
/**
|
|
82
|
+
* Initialize the widget. Returns a promise that resolves with the instance.
|
|
83
|
+
*/
|
|
84
|
+
init: typeof init;
|
|
85
|
+
/**
|
|
86
|
+
* Show the widget launcher. Safe to call before init.
|
|
87
|
+
*/
|
|
88
|
+
show: () => void;
|
|
89
|
+
/**
|
|
90
|
+
* Hide the widget launcher. Safe to call before init.
|
|
91
|
+
*/
|
|
92
|
+
hide: () => void;
|
|
93
|
+
/**
|
|
94
|
+
* Toggle the chat window. Safe to call before init.
|
|
95
|
+
*/
|
|
96
|
+
toggle: () => void;
|
|
97
|
+
/**
|
|
98
|
+
* Open the chat window. Safe to call before init.
|
|
99
|
+
*/
|
|
100
|
+
open: (message?: string) => void;
|
|
101
|
+
/**
|
|
102
|
+
* Identify the visitor. Safe to call before init.
|
|
103
|
+
*/
|
|
104
|
+
identify: (info: VisitorInfo) => void;
|
|
105
|
+
/**
|
|
106
|
+
* Get the current widget configuration.
|
|
107
|
+
*/
|
|
108
|
+
config: () => Partial<WidgetConfig>;
|
|
109
|
+
/**
|
|
110
|
+
* Subscribe to widget events. Safe to call before init.
|
|
111
|
+
*/
|
|
112
|
+
on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;
|
|
113
|
+
/**
|
|
114
|
+
* Unsubscribe from widget events.
|
|
115
|
+
*/
|
|
116
|
+
off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;
|
|
117
|
+
/**
|
|
118
|
+
* Destroy the widget and clean up resources.
|
|
119
|
+
*/
|
|
120
|
+
destroy: () => void;
|
|
121
|
+
/**
|
|
122
|
+
* Check if the widget is ready.
|
|
123
|
+
*/
|
|
124
|
+
isReady: () => boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Get the current instance (null if not initialized).
|
|
127
|
+
*/
|
|
128
|
+
getInstance: () => TchaoInstance | null;
|
|
129
|
+
};
|
|
33
130
|
declare const Tchao: {
|
|
34
131
|
init: typeof init;
|
|
35
132
|
};
|
|
36
133
|
|
|
37
|
-
export { Tchao, type TchaoConfig, type TchaoInstance, type VisitorInfo, type WidgetConfig, Tchao as default, init };
|
|
134
|
+
export { type Message, Tchao, type TchaoConfig, type TchaoEvent, type TchaoEventMap, type TchaoInstance, type VisitorInfo, type WidgetConfig, Tchao as default, init, tchao };
|
package/dist/npm.d.ts
CHANGED
|
@@ -8,30 +8,127 @@ type WidgetConfig = {
|
|
|
8
8
|
websiteId: string;
|
|
9
9
|
position?: "bottom-right" | "bottom-left";
|
|
10
10
|
primaryColor?: string;
|
|
11
|
+
widgetStyle?: "bubble" | "name_line" | "question_cta";
|
|
12
|
+
themeMode?: "light" | "dark" | "system";
|
|
13
|
+
agentName?: string;
|
|
14
|
+
agentRole?: string;
|
|
15
|
+
agentImage?: string;
|
|
16
|
+
agentWelcomeMessage?: string;
|
|
17
|
+
hidePoweredBy?: boolean;
|
|
18
|
+
bubbleIcon?: string;
|
|
11
19
|
};
|
|
12
20
|
type TchaoConfig = {
|
|
13
21
|
websiteId: string;
|
|
14
22
|
host?: string;
|
|
23
|
+
convexUrl?: string;
|
|
24
|
+
position?: "bottom-right" | "bottom-left";
|
|
25
|
+
primaryColor?: string;
|
|
26
|
+
widgetStyle?: "bubble" | "name_line" | "question_cta";
|
|
27
|
+
themeMode?: "light" | "dark" | "system";
|
|
28
|
+
agentName?: string;
|
|
29
|
+
agentRole?: string;
|
|
30
|
+
agentImage?: string;
|
|
31
|
+
agentWelcomeMessage?: string;
|
|
32
|
+
hidePoweredBy?: boolean;
|
|
33
|
+
bubbleIcon?: string;
|
|
34
|
+
};
|
|
35
|
+
type Message = {
|
|
36
|
+
content: string;
|
|
37
|
+
sender: string;
|
|
38
|
+
timestamp: number;
|
|
39
|
+
};
|
|
40
|
+
type TchaoEventMap = {
|
|
41
|
+
message: (message: Message) => void;
|
|
42
|
+
open: () => void;
|
|
43
|
+
close: () => void;
|
|
44
|
+
ready: () => void;
|
|
15
45
|
};
|
|
46
|
+
type TchaoEvent = keyof TchaoEventMap;
|
|
16
47
|
type TchaoInstance = {
|
|
17
48
|
show: () => void;
|
|
18
49
|
hide: () => void;
|
|
19
50
|
toggle: () => void;
|
|
20
|
-
open: () => void;
|
|
51
|
+
open: (message?: string) => void;
|
|
52
|
+
identify: (info: VisitorInfo) => void;
|
|
53
|
+
config: () => Partial<WidgetConfig>;
|
|
54
|
+
on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;
|
|
55
|
+
off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;
|
|
56
|
+
destroy: () => void;
|
|
57
|
+
isReady: () => boolean;
|
|
58
|
+
};
|
|
59
|
+
type InternalTchaoInstance = {
|
|
60
|
+
show: () => void;
|
|
61
|
+
hide: () => void;
|
|
62
|
+
toggle: () => void;
|
|
63
|
+
open: (message?: string) => void;
|
|
21
64
|
identify: (info: VisitorInfo) => void;
|
|
22
|
-
config: (
|
|
65
|
+
config: () => Partial<WidgetConfig>;
|
|
23
66
|
on: (event: string, callback: (...args: unknown[]) => void) => void;
|
|
24
67
|
off: (event: string, callback: (...args: unknown[]) => void) => void;
|
|
25
|
-
destroy: () => void;
|
|
26
68
|
};
|
|
27
69
|
declare global {
|
|
28
70
|
interface Window {
|
|
29
|
-
Tchao?:
|
|
71
|
+
Tchao?: InternalTchaoInstance;
|
|
72
|
+
__TCHAO_CONFIG__?: TchaoConfig;
|
|
30
73
|
}
|
|
31
74
|
}
|
|
32
75
|
declare function init(config: TchaoConfig): Promise<TchaoInstance>;
|
|
76
|
+
/**
|
|
77
|
+
* Safe API that works before initialization.
|
|
78
|
+
* Calls are queued and executed once the widget is ready.
|
|
79
|
+
*/
|
|
80
|
+
declare const tchao: {
|
|
81
|
+
/**
|
|
82
|
+
* Initialize the widget. Returns a promise that resolves with the instance.
|
|
83
|
+
*/
|
|
84
|
+
init: typeof init;
|
|
85
|
+
/**
|
|
86
|
+
* Show the widget launcher. Safe to call before init.
|
|
87
|
+
*/
|
|
88
|
+
show: () => void;
|
|
89
|
+
/**
|
|
90
|
+
* Hide the widget launcher. Safe to call before init.
|
|
91
|
+
*/
|
|
92
|
+
hide: () => void;
|
|
93
|
+
/**
|
|
94
|
+
* Toggle the chat window. Safe to call before init.
|
|
95
|
+
*/
|
|
96
|
+
toggle: () => void;
|
|
97
|
+
/**
|
|
98
|
+
* Open the chat window. Safe to call before init.
|
|
99
|
+
*/
|
|
100
|
+
open: (message?: string) => void;
|
|
101
|
+
/**
|
|
102
|
+
* Identify the visitor. Safe to call before init.
|
|
103
|
+
*/
|
|
104
|
+
identify: (info: VisitorInfo) => void;
|
|
105
|
+
/**
|
|
106
|
+
* Get the current widget configuration.
|
|
107
|
+
*/
|
|
108
|
+
config: () => Partial<WidgetConfig>;
|
|
109
|
+
/**
|
|
110
|
+
* Subscribe to widget events. Safe to call before init.
|
|
111
|
+
*/
|
|
112
|
+
on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;
|
|
113
|
+
/**
|
|
114
|
+
* Unsubscribe from widget events.
|
|
115
|
+
*/
|
|
116
|
+
off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;
|
|
117
|
+
/**
|
|
118
|
+
* Destroy the widget and clean up resources.
|
|
119
|
+
*/
|
|
120
|
+
destroy: () => void;
|
|
121
|
+
/**
|
|
122
|
+
* Check if the widget is ready.
|
|
123
|
+
*/
|
|
124
|
+
isReady: () => boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Get the current instance (null if not initialized).
|
|
127
|
+
*/
|
|
128
|
+
getInstance: () => TchaoInstance | null;
|
|
129
|
+
};
|
|
33
130
|
declare const Tchao: {
|
|
34
131
|
init: typeof init;
|
|
35
132
|
};
|
|
36
133
|
|
|
37
|
-
export { Tchao, type TchaoConfig, type TchaoInstance, type VisitorInfo, type WidgetConfig, Tchao as default, init };
|
|
134
|
+
export { type Message, Tchao, type TchaoConfig, type TchaoEvent, type TchaoEventMap, type TchaoInstance, type VisitorInfo, type WidgetConfig, Tchao as default, init, tchao };
|
package/dist/npm.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var w=Object.defineProperty;var f=Object.getOwnPropertyDescriptor;var u=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var T=(e,o)=>{for(var i in o)w(e,i,{get:o[i],enumerable:!0})},y=(e,o,i,s)=>{if(o&&typeof o=="object"||typeof o=="function")for(let t of u(o))!p.call(e,t)&&t!==i&&w(e,t,{get:()=>o[t],enumerable:!(s=f(o,t))||s.enumerable});return e};var v=e=>y(w({},"__esModule",{value:!0}),e);var x={};T(x,{Tchao:()=>g,default:()=>_,init:()=>l,tchao:()=>C});module.exports=v(x);var m="https://tchao.app/widget.js",h=!1,d=null,r=!1,c=null,n=[];function b(){for(;n.length>0;){let e=n.shift();if(!(!e||!window.Tchao))try{switch(e.type){case"show":window.Tchao.show();break;case"hide":window.Tchao.hide();break;case"toggle":window.Tchao.toggle();break;case"open":window.Tchao.open(e.message);break;case"identify":window.Tchao.identify(e.info);break;case"on":window.Tchao.on(e.event,e.callback);break;case"off":window.Tchao.off(e.event,e.callback);break}}catch{}}}async function E(e){return d||(d=new Promise((o,i)=>{if(h&&window.Tchao){o();return}if(document.querySelector("script[data-tchao-widget]")){h=!0,o();return}window.__TCHAO_CONFIG__=e;let t=document.createElement("script");t.src=e.host?`${e.host}/widget.js`:m,t.async=!0,t.dataset.websiteId=e.websiteId,t.dataset.tchaoWidget="true",t.onload=()=>{h=!0,o()},t.onerror=()=>{i(new Error("Failed to load Tchao widget script"))},document.head.appendChild(t)}),d)}async function I(){return new Promise((e,o)=>{let i=0,s=()=>{window.Tchao?e():i>=50?o(new Error("Tchao widget failed to initialize")):(i++,setTimeout(s,100))};s()})}async function l(e){if(!e.websiteId)throw new Error("websiteId is required");if(r&&window.Tchao&&c)return c;if(await E(e),await I(),!window.Tchao)throw new Error("Tchao widget failed to initialize");return r=!0,c=k(),b(),c}function k(){return{show:()=>{try{window.Tchao?.show()}catch{}},hide:()=>{try{window.Tchao?.hide()}catch{}},toggle:()=>{try{window.Tchao?.toggle()}catch{}},open:e=>{try{window.Tchao?.open(e)}catch{}},identify:e=>{try{window.Tchao?.identify(e)}catch{}},config:()=>{try{return window.Tchao?.config()??{}}catch{return{}}},on:(e,o)=>{try{window.Tchao?.on(e,o)}catch{}},off:(e,o)=>{try{window.Tchao?.off(e,o)}catch{}},isReady:()=>r&&!!window.Tchao,destroy:()=>{try{let e=document.querySelector("script[data-tchao-widget]");e&&e.remove();let o=document.getElementById("tchao-widget-root");o&&o.remove(),h=!1,d=null,r=!1,c=null,n.length=0,delete window.__TCHAO_CONFIG__,delete window.Tchao}catch{}}}}function a(e,o){try{return e()}catch{return o}}var C={init:l,show:()=>{window.Tchao?a(()=>window.Tchao?.show(),void 0):n.push({type:"show"})},hide:()=>{window.Tchao?a(()=>window.Tchao?.hide(),void 0):n.push({type:"hide"})},toggle:()=>{window.Tchao?a(()=>window.Tchao?.toggle(),void 0):n.push({type:"toggle"})},open:e=>{window.Tchao?a(()=>window.Tchao?.open(e),void 0):n.push({type:"open",message:e})},identify:e=>{window.Tchao?a(()=>window.Tchao?.identify(e),void 0):n.push({type:"identify",info:e})},config:()=>a(()=>window.Tchao?.config()??{},{}),on:(e,o)=>{window.Tchao?a(()=>window.Tchao?.on(e,o),void 0):n.push({type:"on",event:e,callback:o})},off:(e,o)=>{window.Tchao?a(()=>window.Tchao?.off(e,o),void 0):n.push({type:"off",event:e,callback:o})},destroy:()=>{c&&c.destroy()},isReady:()=>r&&!!window.Tchao,getInstance:()=>c},g={init:l};var _=g;0&&(module.exports={Tchao,init,tchao});
|
|
2
2
|
//# sourceMappingURL=npm.js.map
|
package/dist/npm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/widget/npm.ts"],"sourcesContent":["export type VisitorInfo = {\n name?: string;\n email?: string;\n avatar?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type WidgetConfig = {\n websiteId: string;\n position?: \"bottom-right\" | \"bottom-left\";\n primaryColor?: string;\n};\n\nexport type TchaoConfig = {\n websiteId: string;\n host?: string;\n};\n\nexport type TchaoInstance = {\n show: () => void;\n hide: () => void;\n toggle: () => void;\n open: () => void;\n identify: (info: VisitorInfo) => void;\n config: (opts: Partial<WidgetConfig>) => void;\n on: (event: string, callback: (...args: unknown[]) => void) => void;\n off: (event: string, callback: (...args: unknown[]) => void) => void;\n destroy: () => void;\n};\n\ndeclare global {\n interface Window {\n Tchao?: TchaoInstance;\n }\n}\n\nconst WIDGET_SCRIPT_URL = \"https://tchao.app/widget.js\";\n\nlet scriptLoaded = false;\nlet scriptPromise: Promise<void> | null = null;\n\nfunction loadScript(websiteId: string, host?: string): Promise<void> {\n if (scriptPromise) return scriptPromise;\n\n scriptPromise = new Promise((resolve, reject) => {\n if (scriptLoaded && window.Tchao) {\n resolve();\n return;\n }\n\n const existingScript = document.querySelector(\n 'script[data-tchao-widget]'\n ) as HTMLScriptElement | null;\n\n if (existingScript) {\n scriptLoaded = true;\n resolve();\n return;\n }\n\n const script = document.createElement(\"script\");\n script.src = host ? `${host}/widget.js` : WIDGET_SCRIPT_URL;\n script.async = true;\n script.dataset.websiteId = websiteId;\n script.dataset.tchaoWidget = \"true\";\n\n script.onload = () => {\n scriptLoaded = true;\n resolve();\n };\n\n script.onerror = () => {\n reject(new Error(\"Failed to load Tchao widget script\"));\n };\n\n document.head.appendChild(script);\n });\n\n return scriptPromise;\n}\n\nexport async function init(config: TchaoConfig): Promise<TchaoInstance> {\n if (!config.websiteId) {\n throw new Error(\"websiteId is required\");\n }\n\n await loadScript(config.websiteId, config.host);\n\n // Wait for Tchao to be available\n let attempts = 0;\n while (!window.Tchao && attempts < 50) {\n await new Promise((r) => setTimeout(r, 100));\n attempts++;\n }\n\n if (!window.Tchao) {\n throw new Error(\"Tchao widget failed to initialize\");\n }\n\n return {\n show: () => window.Tchao?.show(),\n hide: () => window.Tchao?.hide(),\n toggle: () => window.Tchao?.toggle(),\n open: () => window.Tchao?.open(),\n identify: (info) => window.Tchao?.identify(info),\n config: (opts) => window.Tchao?.config(opts),\n on: (event, cb) => window.Tchao?.on(event, cb),\n off: (event, cb) => window.Tchao?.off(event, cb),\n destroy: () => {\n const script = document.querySelector('script[data-tchao-widget]');\n if (script) script.remove();\n const widget = document.getElementById(\"tchao-widget\");\n if (widget) widget.remove();\n scriptLoaded = false;\n scriptPromise = null;\n },\n };\n}\n\nexport const Tchao = { init };\n\nexport default Tchao;\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,WAAAE,EAAA,YAAAC,EAAA,SAAAC,IAAA,eAAAC,EAAAL,GAoCA,IAAMM,EAAoB,8BAEtBC,EAAe,GACfC,EAAsC,KAE1C,SAASC,EAAWC,EAAmBC,EAA8B,CACnE,OAAIH,IAEJA,EAAgB,IAAI,QAAQ,CAACI,EAASC,IAAW,CAC/C,GAAIN,GAAgB,OAAO,MAAO,CAChCK,EAAQ,EACR,MACF,CAMA,GAJuB,SAAS,cAC9B,2BACF,EAEoB,CAClBL,EAAe,GACfK,EAAQ,EACR,MACF,CAEA,IAAME,EAAS,SAAS,cAAc,QAAQ,EAC9CA,EAAO,IAAMH,EAAO,GAAGA,CAAI,aAAeL,EAC1CQ,EAAO,MAAQ,GACfA,EAAO,QAAQ,UAAYJ,EAC3BI,EAAO,QAAQ,YAAc,OAE7BA,EAAO,OAAS,IAAM,CACpBP,EAAe,GACfK,EAAQ,CACV,EAEAE,EAAO,QAAU,IAAM,CACrBD,EAAO,IAAI,MAAM,oCAAoC,CAAC,CACxD,EAEA,SAAS,KAAK,YAAYC,CAAM,CAClC,CAAC,EAEMN,EACT,CAEA,eAAsBJ,EAAKW,EAA6C,CACtE,GAAI,CAACA,EAAO,UACV,MAAM,IAAI,MAAM,uBAAuB,EAGzC,MAAMN,EAAWM,EAAO,UAAWA,EAAO,IAAI,EAG9C,IAAIC,EAAW,EACf,KAAO,CAAC,OAAO,OAASA,EAAW,IACjC,MAAM,IAAI,QAASC,GAAM,WAAWA,EAAG,GAAG,CAAC,EAC3CD,IAGF,GAAI,CAAC,OAAO,MACV,MAAM,IAAI,MAAM,mCAAmC,EAGrD,MAAO,CACL,KAAM,IAAM,OAAO,OAAO,KAAK,EAC/B,KAAM,IAAM,OAAO,OAAO,KAAK,EAC/B,OAAQ,IAAM,OAAO,OAAO,OAAO,EACnC,KAAM,IAAM,OAAO,OAAO,KAAK,EAC/B,SAAWE,GAAS,OAAO,OAAO,SAASA,CAAI,EAC/C,OAASC,GAAS,OAAO,OAAO,OAAOA,CAAI,EAC3C,GAAI,CAACC,EAAOC,IAAO,OAAO,OAAO,GAAGD,EAAOC,CAAE,EAC7C,IAAK,CAACD,EAAOC,IAAO,OAAO,OAAO,IAAID,EAAOC,CAAE,EAC/C,QAAS,IAAM,CACb,IAAMP,EAAS,SAAS,cAAc,2BAA2B,EAC7DA,GAAQA,EAAO,OAAO,EAC1B,IAAMQ,EAAS,SAAS,eAAe,cAAc,EACjDA,GAAQA,EAAO,OAAO,EAC1Bf,EAAe,GACfC,EAAgB,IAClB,CACF,CACF,CAEO,IAAMN,EAAQ,CAAE,KAAAE,CAAK,EAErBD,EAAQD","names":["npm_exports","__export","Tchao","npm_default","init","__toCommonJS","WIDGET_SCRIPT_URL","scriptLoaded","scriptPromise","loadScript","websiteId","host","resolve","reject","script","config","attempts","r","info","opts","event","cb","widget"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/widget/npm.ts"],"sourcesContent":["export type VisitorInfo = {\n name?: string;\n email?: string;\n avatar?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type WidgetConfig = {\n websiteId: string;\n position?: \"bottom-right\" | \"bottom-left\";\n primaryColor?: string;\n widgetStyle?: \"bubble\" | \"name_line\" | \"question_cta\";\n themeMode?: \"light\" | \"dark\" | \"system\";\n agentName?: string;\n agentRole?: string;\n agentImage?: string;\n agentWelcomeMessage?: string;\n hidePoweredBy?: boolean;\n bubbleIcon?: string;\n};\n\nexport type TchaoConfig = {\n websiteId: string;\n host?: string;\n convexUrl?: string;\n position?: \"bottom-right\" | \"bottom-left\";\n primaryColor?: string;\n widgetStyle?: \"bubble\" | \"name_line\" | \"question_cta\";\n themeMode?: \"light\" | \"dark\" | \"system\";\n agentName?: string;\n agentRole?: string;\n agentImage?: string;\n agentWelcomeMessage?: string;\n hidePoweredBy?: boolean;\n bubbleIcon?: string;\n};\n\nexport type Message = {\n content: string;\n sender: string;\n timestamp: number;\n};\n\nexport type TchaoEventMap = {\n message: (message: Message) => void;\n open: () => void;\n close: () => void;\n ready: () => void;\n};\n\nexport type TchaoEvent = keyof TchaoEventMap;\n\nexport type TchaoInstance = {\n show: () => void;\n hide: () => void;\n toggle: () => void;\n open: (message?: string) => void;\n identify: (info: VisitorInfo) => void;\n config: () => Partial<WidgetConfig>;\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n destroy: () => void;\n isReady: () => boolean;\n};\n\ntype InternalTchaoInstance = {\n show: () => void;\n hide: () => void;\n toggle: () => void;\n open: (message?: string) => void;\n identify: (info: VisitorInfo) => void;\n config: () => Partial<WidgetConfig>;\n on: (event: string, callback: (...args: unknown[]) => void) => void;\n off: (event: string, callback: (...args: unknown[]) => void) => void;\n};\n\ndeclare global {\n interface Window {\n Tchao?: InternalTchaoInstance;\n __TCHAO_CONFIG__?: TchaoConfig;\n }\n}\n\nconst WIDGET_SCRIPT_URL = \"https://tchao.app/widget.js\";\n\nlet scriptLoaded = false;\nlet scriptPromise: Promise<void> | null = null;\nlet initialized = false;\nlet currentInstance: TchaoInstance | null = null;\n\ntype QueuedCall =\n | { type: \"show\" }\n | { type: \"hide\" }\n | { type: \"toggle\" }\n | { type: \"open\"; message?: string }\n | { type: \"identify\"; info: VisitorInfo }\n | { type: \"on\"; event: string; callback: (...args: unknown[]) => void }\n | { type: \"off\"; event: string; callback: (...args: unknown[]) => void };\n\nconst callQueue: QueuedCall[] = [];\n\nfunction flushQueue(): void {\n while (callQueue.length > 0) {\n const call = callQueue.shift();\n if (!call || !window.Tchao) continue;\n\n try {\n switch (call.type) {\n case \"show\":\n window.Tchao.show();\n break;\n case \"hide\":\n window.Tchao.hide();\n break;\n case \"toggle\":\n window.Tchao.toggle();\n break;\n case \"open\":\n window.Tchao.open(call.message);\n break;\n case \"identify\":\n window.Tchao.identify(call.info);\n break;\n case \"on\":\n window.Tchao.on(call.event, call.callback);\n break;\n case \"off\":\n window.Tchao.off(call.event, call.callback);\n break;\n }\n } catch {\n // Silent fail\n }\n }\n}\n\nasync function loadScript(config: TchaoConfig): Promise<void> {\n if (scriptPromise) return scriptPromise;\n\n scriptPromise = new Promise((resolve, reject) => {\n if (scriptLoaded && window.Tchao) {\n resolve();\n return;\n }\n\n const existingScript = document.querySelector(\n 'script[data-tchao-widget]'\n ) as HTMLScriptElement | null;\n\n if (existingScript) {\n scriptLoaded = true;\n resolve();\n return;\n }\n\n window.__TCHAO_CONFIG__ = config;\n\n const script = document.createElement(\"script\");\n script.src = config.host ? `${config.host}/widget.js` : WIDGET_SCRIPT_URL;\n script.async = true;\n script.dataset.websiteId = config.websiteId;\n script.dataset.tchaoWidget = \"true\";\n\n script.onload = () => {\n scriptLoaded = true;\n resolve();\n };\n\n script.onerror = () => {\n reject(new Error(\"Failed to load Tchao widget script\"));\n };\n\n document.head.appendChild(script);\n });\n\n return scriptPromise;\n}\n\nasync function waitForTchao(): Promise<void> {\n return new Promise((resolve, reject) => {\n let attempts = 0;\n const check = () => {\n if (window.Tchao) {\n resolve();\n } else if (attempts >= 50) {\n reject(new Error(\"Tchao widget failed to initialize\"));\n } else {\n attempts++;\n setTimeout(check, 100);\n }\n };\n check();\n });\n}\n\nasync function init(config: TchaoConfig): Promise<TchaoInstance> {\n if (!config.websiteId) {\n throw new Error(\"websiteId is required\");\n }\n\n if (initialized && window.Tchao && currentInstance) {\n return currentInstance;\n }\n\n await loadScript(config);\n await waitForTchao();\n\n if (!window.Tchao) {\n throw new Error(\"Tchao widget failed to initialize\");\n }\n\n initialized = true;\n currentInstance = createInstance();\n flushQueue();\n return currentInstance;\n}\n\nfunction createInstance(): TchaoInstance {\n return {\n show: () => {\n try {\n window.Tchao?.show();\n } catch {\n // Silent fail\n }\n },\n hide: () => {\n try {\n window.Tchao?.hide();\n } catch {\n // Silent fail\n }\n },\n toggle: () => {\n try {\n window.Tchao?.toggle();\n } catch {\n // Silent fail\n }\n },\n open: (message?: string) => {\n try {\n window.Tchao?.open(message);\n } catch {\n // Silent fail\n }\n },\n identify: (info: VisitorInfo) => {\n try {\n window.Tchao?.identify(info);\n } catch {\n // Silent fail\n }\n },\n config: () => {\n try {\n return window.Tchao?.config() ?? {};\n } catch {\n return {};\n }\n },\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => {\n try {\n window.Tchao?.on(event, callback as (...args: unknown[]) => void);\n } catch {\n // Silent fail\n }\n },\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => {\n try {\n window.Tchao?.off(event, callback as (...args: unknown[]) => void);\n } catch {\n // Silent fail\n }\n },\n isReady: () => initialized && !!window.Tchao,\n destroy: () => {\n try {\n const script = document.querySelector('script[data-tchao-widget]');\n if (script) script.remove();\n const widget = document.getElementById(\"tchao-widget-root\");\n if (widget) widget.remove();\n scriptLoaded = false;\n scriptPromise = null;\n initialized = false;\n currentInstance = null;\n callQueue.length = 0;\n delete window.__TCHAO_CONFIG__;\n delete window.Tchao;\n } catch {\n // Silent fail\n }\n },\n };\n}\n\nfunction safeCall<T>(fn: () => T, fallback: T): T {\n try {\n return fn();\n } catch {\n return fallback;\n }\n}\n\n/**\n * Safe API that works before initialization.\n * Calls are queued and executed once the widget is ready.\n */\nexport const tchao = {\n /**\n * Initialize the widget. Returns a promise that resolves with the instance.\n */\n init,\n\n /**\n * Show the widget launcher. Safe to call before init.\n */\n show: (): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.show(), undefined);\n } else {\n callQueue.push({ type: \"show\" });\n }\n },\n\n /**\n * Hide the widget launcher. Safe to call before init.\n */\n hide: (): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.hide(), undefined);\n } else {\n callQueue.push({ type: \"hide\" });\n }\n },\n\n /**\n * Toggle the chat window. Safe to call before init.\n */\n toggle: (): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.toggle(), undefined);\n } else {\n callQueue.push({ type: \"toggle\" });\n }\n },\n\n /**\n * Open the chat window. Safe to call before init.\n */\n open: (message?: string): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.open(message), undefined);\n } else {\n callQueue.push({ type: \"open\", message });\n }\n },\n\n /**\n * Identify the visitor. Safe to call before init.\n */\n identify: (info: VisitorInfo): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.identify(info), undefined);\n } else {\n callQueue.push({ type: \"identify\", info });\n }\n },\n\n /**\n * Get the current widget configuration.\n */\n config: (): Partial<WidgetConfig> => {\n return safeCall(() => window.Tchao?.config() ?? {}, {});\n },\n\n /**\n * Subscribe to widget events. Safe to call before init.\n */\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]): void => {\n if (window.Tchao) {\n safeCall(\n () => window.Tchao?.on(event, callback as (...args: unknown[]) => void),\n undefined\n );\n } else {\n callQueue.push({\n type: \"on\",\n event,\n callback: callback as (...args: unknown[]) => void,\n });\n }\n },\n\n /**\n * Unsubscribe from widget events.\n */\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]): void => {\n if (window.Tchao) {\n safeCall(\n () =>\n window.Tchao?.off(event, callback as (...args: unknown[]) => void),\n undefined\n );\n } else {\n callQueue.push({\n type: \"off\",\n event,\n callback: callback as (...args: unknown[]) => void,\n });\n }\n },\n\n /**\n * Destroy the widget and clean up resources.\n */\n destroy: (): void => {\n if (currentInstance) {\n currentInstance.destroy();\n }\n },\n\n /**\n * Check if the widget is ready.\n */\n isReady: (): boolean => initialized && !!window.Tchao,\n\n /**\n * Get the current instance (null if not initialized).\n */\n getInstance: (): TchaoInstance | null => currentInstance,\n};\n\nexport const Tchao = {\n init,\n};\n\nexport { init };\nexport default Tchao;\n"],"mappings":"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","names":["npm_exports","__export","Tchao","npm_default","init","tchao","__toCommonJS","WIDGET_SCRIPT_URL","scriptLoaded","scriptPromise","initialized","currentInstance","callQueue","flushQueue","call","loadScript","config","resolve","reject","script","waitForTchao","attempts","check","createInstance","message","info","event","callback","widget","safeCall","fn","fallback","npm_default","Tchao"]}
|
package/dist/npm.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var
|
|
1
|
+
var l="https://tchao.app/widget.js",r=!1,c=null,s=!1,i=null,t=[];function g(){for(;t.length>0;){let e=t.shift();if(!(!e||!window.Tchao))try{switch(e.type){case"show":window.Tchao.show();break;case"hide":window.Tchao.hide();break;case"toggle":window.Tchao.toggle();break;case"open":window.Tchao.open(e.message);break;case"identify":window.Tchao.identify(e.info);break;case"on":window.Tchao.on(e.event,e.callback);break;case"off":window.Tchao.off(e.event,e.callback);break}}catch{}}}async function f(e){return c||(c=new Promise((o,d)=>{if(r&&window.Tchao){o();return}if(document.querySelector("script[data-tchao-widget]")){r=!0,o();return}window.__TCHAO_CONFIG__=e;let a=document.createElement("script");a.src=e.host?`${e.host}/widget.js`:l,a.async=!0,a.dataset.websiteId=e.websiteId,a.dataset.tchaoWidget="true",a.onload=()=>{r=!0,o()},a.onerror=()=>{d(new Error("Failed to load Tchao widget script"))},document.head.appendChild(a)}),c)}async function u(){return new Promise((e,o)=>{let d=0,h=()=>{window.Tchao?e():d>=50?o(new Error("Tchao widget failed to initialize")):(d++,setTimeout(h,100))};h()})}async function w(e){if(!e.websiteId)throw new Error("websiteId is required");if(s&&window.Tchao&&i)return i;if(await f(e),await u(),!window.Tchao)throw new Error("Tchao widget failed to initialize");return s=!0,i=p(),g(),i}function p(){return{show:()=>{try{window.Tchao?.show()}catch{}},hide:()=>{try{window.Tchao?.hide()}catch{}},toggle:()=>{try{window.Tchao?.toggle()}catch{}},open:e=>{try{window.Tchao?.open(e)}catch{}},identify:e=>{try{window.Tchao?.identify(e)}catch{}},config:()=>{try{return window.Tchao?.config()??{}}catch{return{}}},on:(e,o)=>{try{window.Tchao?.on(e,o)}catch{}},off:(e,o)=>{try{window.Tchao?.off(e,o)}catch{}},isReady:()=>s&&!!window.Tchao,destroy:()=>{try{let e=document.querySelector("script[data-tchao-widget]");e&&e.remove();let o=document.getElementById("tchao-widget-root");o&&o.remove(),r=!1,c=null,s=!1,i=null,t.length=0,delete window.__TCHAO_CONFIG__,delete window.Tchao}catch{}}}}function n(e,o){try{return e()}catch{return o}}var y={init:w,show:()=>{window.Tchao?n(()=>window.Tchao?.show(),void 0):t.push({type:"show"})},hide:()=>{window.Tchao?n(()=>window.Tchao?.hide(),void 0):t.push({type:"hide"})},toggle:()=>{window.Tchao?n(()=>window.Tchao?.toggle(),void 0):t.push({type:"toggle"})},open:e=>{window.Tchao?n(()=>window.Tchao?.open(e),void 0):t.push({type:"open",message:e})},identify:e=>{window.Tchao?n(()=>window.Tchao?.identify(e),void 0):t.push({type:"identify",info:e})},config:()=>n(()=>window.Tchao?.config()??{},{}),on:(e,o)=>{window.Tchao?n(()=>window.Tchao?.on(e,o),void 0):t.push({type:"on",event:e,callback:o})},off:(e,o)=>{window.Tchao?n(()=>window.Tchao?.off(e,o),void 0):t.push({type:"off",event:e,callback:o})},destroy:()=>{i&&i.destroy()},isReady:()=>s&&!!window.Tchao,getInstance:()=>i},T={init:w};var v=T;export{T as Tchao,v as default,w as init,y as tchao};
|
|
2
2
|
//# sourceMappingURL=npm.mjs.map
|
package/dist/npm.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/widget/npm.ts"],"sourcesContent":["export type VisitorInfo = {\n name?: string;\n email?: string;\n avatar?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type WidgetConfig = {\n websiteId: string;\n position?: \"bottom-right\" | \"bottom-left\";\n primaryColor?: string;\n};\n\nexport type TchaoConfig = {\n websiteId: string;\n host?: string;\n};\n\nexport type TchaoInstance = {\n show: () => void;\n hide: () => void;\n toggle: () => void;\n open: () => void;\n identify: (info: VisitorInfo) => void;\n config: (opts: Partial<WidgetConfig>) => void;\n on: (event: string, callback: (...args: unknown[]) => void) => void;\n off: (event: string, callback: (...args: unknown[]) => void) => void;\n destroy: () => void;\n};\n\ndeclare global {\n interface Window {\n Tchao?: TchaoInstance;\n }\n}\n\nconst WIDGET_SCRIPT_URL = \"https://tchao.app/widget.js\";\n\nlet scriptLoaded = false;\nlet scriptPromise: Promise<void> | null = null;\n\nfunction loadScript(websiteId: string, host?: string): Promise<void> {\n if (scriptPromise) return scriptPromise;\n\n scriptPromise = new Promise((resolve, reject) => {\n if (scriptLoaded && window.Tchao) {\n resolve();\n return;\n }\n\n const existingScript = document.querySelector(\n 'script[data-tchao-widget]'\n ) as HTMLScriptElement | null;\n\n if (existingScript) {\n scriptLoaded = true;\n resolve();\n return;\n }\n\n const script = document.createElement(\"script\");\n script.src = host ? `${host}/widget.js` : WIDGET_SCRIPT_URL;\n script.async = true;\n script.dataset.websiteId = websiteId;\n script.dataset.tchaoWidget = \"true\";\n\n script.onload = () => {\n scriptLoaded = true;\n resolve();\n };\n\n script.onerror = () => {\n reject(new Error(\"Failed to load Tchao widget script\"));\n };\n\n document.head.appendChild(script);\n });\n\n return scriptPromise;\n}\n\nexport async function init(config: TchaoConfig): Promise<TchaoInstance> {\n if (!config.websiteId) {\n throw new Error(\"websiteId is required\");\n }\n\n await loadScript(config.websiteId, config.host);\n\n // Wait for Tchao to be available\n let attempts = 0;\n while (!window.Tchao && attempts < 50) {\n await new Promise((r) => setTimeout(r, 100));\n attempts++;\n }\n\n if (!window.Tchao) {\n throw new Error(\"Tchao widget failed to initialize\");\n }\n\n return {\n show: () => window.Tchao?.show(),\n hide: () => window.Tchao?.hide(),\n toggle: () => window.Tchao?.toggle(),\n open: () => window.Tchao?.open(),\n identify: (info) => window.Tchao?.identify(info),\n config: (opts) => window.Tchao?.config(opts),\n on: (event, cb) => window.Tchao?.on(event, cb),\n off: (event, cb) => window.Tchao?.off(event, cb),\n destroy: () => {\n const script = document.querySelector('script[data-tchao-widget]');\n if (script) script.remove();\n const widget = document.getElementById(\"tchao-widget\");\n if (widget) widget.remove();\n scriptLoaded = false;\n scriptPromise = null;\n },\n };\n}\n\nexport const Tchao = { init };\n\nexport default Tchao;\n"],"mappings":"AAoCA,IAAMA,EAAoB,8BAEtBC,EAAe,GACfC,EAAsC,KAE1C,SAASC,EAAWC,EAAmBC,EAA8B,CACnE,OAAIH,IAEJA,EAAgB,IAAI,QAAQ,CAACI,EAASC,IAAW,CAC/C,GAAIN,GAAgB,OAAO,MAAO,CAChCK,EAAQ,EACR,MACF,CAMA,GAJuB,SAAS,cAC9B,2BACF,EAEoB,CAClBL,EAAe,GACfK,EAAQ,EACR,MACF,CAEA,IAAME,EAAS,SAAS,cAAc,QAAQ,EAC9CA,EAAO,IAAMH,EAAO,GAAGA,CAAI,aAAeL,EAC1CQ,EAAO,MAAQ,GACfA,EAAO,QAAQ,UAAYJ,EAC3BI,EAAO,QAAQ,YAAc,OAE7BA,EAAO,OAAS,IAAM,CACpBP,EAAe,GACfK,EAAQ,CACV,EAEAE,EAAO,QAAU,IAAM,CACrBD,EAAO,IAAI,MAAM,oCAAoC,CAAC,CACxD,EAEA,SAAS,KAAK,YAAYC,CAAM,CAClC,CAAC,EAEMN,EACT,CAEA,eAAsBO,EAAKC,EAA6C,CACtE,GAAI,CAACA,EAAO,UACV,MAAM,IAAI,MAAM,uBAAuB,EAGzC,MAAMP,EAAWO,EAAO,UAAWA,EAAO,IAAI,EAG9C,IAAIC,EAAW,EACf,KAAO,CAAC,OAAO,OAASA,EAAW,IACjC,MAAM,IAAI,QAASC,GAAM,WAAWA,EAAG,GAAG,CAAC,EAC3CD,IAGF,GAAI,CAAC,OAAO,MACV,MAAM,IAAI,MAAM,mCAAmC,EAGrD,MAAO,CACL,KAAM,IAAM,OAAO,OAAO,KAAK,EAC/B,KAAM,IAAM,OAAO,OAAO,KAAK,EAC/B,OAAQ,IAAM,OAAO,OAAO,OAAO,EACnC,KAAM,IAAM,OAAO,OAAO,KAAK,EAC/B,SAAWE,GAAS,OAAO,OAAO,SAASA,CAAI,EAC/C,OAASC,GAAS,OAAO,OAAO,OAAOA,CAAI,EAC3C,GAAI,CAACC,EAAOC,IAAO,OAAO,OAAO,GAAGD,EAAOC,CAAE,EAC7C,IAAK,CAACD,EAAOC,IAAO,OAAO,OAAO,IAAID,EAAOC,CAAE,EAC/C,QAAS,IAAM,CACb,IAAMR,EAAS,SAAS,cAAc,2BAA2B,EAC7DA,GAAQA,EAAO,OAAO,EAC1B,IAAMS,EAAS,SAAS,eAAe,cAAc,EACjDA,GAAQA,EAAO,OAAO,EAC1BhB,EAAe,GACfC,EAAgB,IAClB,CACF,CACF,CAEO,IAAMgB,EAAQ,CAAE,KAAAT,CAAK,EAErBU,EAAQD","names":["WIDGET_SCRIPT_URL","scriptLoaded","scriptPromise","loadScript","websiteId","host","resolve","reject","script","init","config","attempts","r","info","opts","event","cb","widget","Tchao","npm_default"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/widget/npm.ts"],"sourcesContent":["export type VisitorInfo = {\n name?: string;\n email?: string;\n avatar?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type WidgetConfig = {\n websiteId: string;\n position?: \"bottom-right\" | \"bottom-left\";\n primaryColor?: string;\n widgetStyle?: \"bubble\" | \"name_line\" | \"question_cta\";\n themeMode?: \"light\" | \"dark\" | \"system\";\n agentName?: string;\n agentRole?: string;\n agentImage?: string;\n agentWelcomeMessage?: string;\n hidePoweredBy?: boolean;\n bubbleIcon?: string;\n};\n\nexport type TchaoConfig = {\n websiteId: string;\n host?: string;\n convexUrl?: string;\n position?: \"bottom-right\" | \"bottom-left\";\n primaryColor?: string;\n widgetStyle?: \"bubble\" | \"name_line\" | \"question_cta\";\n themeMode?: \"light\" | \"dark\" | \"system\";\n agentName?: string;\n agentRole?: string;\n agentImage?: string;\n agentWelcomeMessage?: string;\n hidePoweredBy?: boolean;\n bubbleIcon?: string;\n};\n\nexport type Message = {\n content: string;\n sender: string;\n timestamp: number;\n};\n\nexport type TchaoEventMap = {\n message: (message: Message) => void;\n open: () => void;\n close: () => void;\n ready: () => void;\n};\n\nexport type TchaoEvent = keyof TchaoEventMap;\n\nexport type TchaoInstance = {\n show: () => void;\n hide: () => void;\n toggle: () => void;\n open: (message?: string) => void;\n identify: (info: VisitorInfo) => void;\n config: () => Partial<WidgetConfig>;\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n destroy: () => void;\n isReady: () => boolean;\n};\n\ntype InternalTchaoInstance = {\n show: () => void;\n hide: () => void;\n toggle: () => void;\n open: (message?: string) => void;\n identify: (info: VisitorInfo) => void;\n config: () => Partial<WidgetConfig>;\n on: (event: string, callback: (...args: unknown[]) => void) => void;\n off: (event: string, callback: (...args: unknown[]) => void) => void;\n};\n\ndeclare global {\n interface Window {\n Tchao?: InternalTchaoInstance;\n __TCHAO_CONFIG__?: TchaoConfig;\n }\n}\n\nconst WIDGET_SCRIPT_URL = \"https://tchao.app/widget.js\";\n\nlet scriptLoaded = false;\nlet scriptPromise: Promise<void> | null = null;\nlet initialized = false;\nlet currentInstance: TchaoInstance | null = null;\n\ntype QueuedCall =\n | { type: \"show\" }\n | { type: \"hide\" }\n | { type: \"toggle\" }\n | { type: \"open\"; message?: string }\n | { type: \"identify\"; info: VisitorInfo }\n | { type: \"on\"; event: string; callback: (...args: unknown[]) => void }\n | { type: \"off\"; event: string; callback: (...args: unknown[]) => void };\n\nconst callQueue: QueuedCall[] = [];\n\nfunction flushQueue(): void {\n while (callQueue.length > 0) {\n const call = callQueue.shift();\n if (!call || !window.Tchao) continue;\n\n try {\n switch (call.type) {\n case \"show\":\n window.Tchao.show();\n break;\n case \"hide\":\n window.Tchao.hide();\n break;\n case \"toggle\":\n window.Tchao.toggle();\n break;\n case \"open\":\n window.Tchao.open(call.message);\n break;\n case \"identify\":\n window.Tchao.identify(call.info);\n break;\n case \"on\":\n window.Tchao.on(call.event, call.callback);\n break;\n case \"off\":\n window.Tchao.off(call.event, call.callback);\n break;\n }\n } catch {\n // Silent fail\n }\n }\n}\n\nasync function loadScript(config: TchaoConfig): Promise<void> {\n if (scriptPromise) return scriptPromise;\n\n scriptPromise = new Promise((resolve, reject) => {\n if (scriptLoaded && window.Tchao) {\n resolve();\n return;\n }\n\n const existingScript = document.querySelector(\n 'script[data-tchao-widget]'\n ) as HTMLScriptElement | null;\n\n if (existingScript) {\n scriptLoaded = true;\n resolve();\n return;\n }\n\n window.__TCHAO_CONFIG__ = config;\n\n const script = document.createElement(\"script\");\n script.src = config.host ? `${config.host}/widget.js` : WIDGET_SCRIPT_URL;\n script.async = true;\n script.dataset.websiteId = config.websiteId;\n script.dataset.tchaoWidget = \"true\";\n\n script.onload = () => {\n scriptLoaded = true;\n resolve();\n };\n\n script.onerror = () => {\n reject(new Error(\"Failed to load Tchao widget script\"));\n };\n\n document.head.appendChild(script);\n });\n\n return scriptPromise;\n}\n\nasync function waitForTchao(): Promise<void> {\n return new Promise((resolve, reject) => {\n let attempts = 0;\n const check = () => {\n if (window.Tchao) {\n resolve();\n } else if (attempts >= 50) {\n reject(new Error(\"Tchao widget failed to initialize\"));\n } else {\n attempts++;\n setTimeout(check, 100);\n }\n };\n check();\n });\n}\n\nasync function init(config: TchaoConfig): Promise<TchaoInstance> {\n if (!config.websiteId) {\n throw new Error(\"websiteId is required\");\n }\n\n if (initialized && window.Tchao && currentInstance) {\n return currentInstance;\n }\n\n await loadScript(config);\n await waitForTchao();\n\n if (!window.Tchao) {\n throw new Error(\"Tchao widget failed to initialize\");\n }\n\n initialized = true;\n currentInstance = createInstance();\n flushQueue();\n return currentInstance;\n}\n\nfunction createInstance(): TchaoInstance {\n return {\n show: () => {\n try {\n window.Tchao?.show();\n } catch {\n // Silent fail\n }\n },\n hide: () => {\n try {\n window.Tchao?.hide();\n } catch {\n // Silent fail\n }\n },\n toggle: () => {\n try {\n window.Tchao?.toggle();\n } catch {\n // Silent fail\n }\n },\n open: (message?: string) => {\n try {\n window.Tchao?.open(message);\n } catch {\n // Silent fail\n }\n },\n identify: (info: VisitorInfo) => {\n try {\n window.Tchao?.identify(info);\n } catch {\n // Silent fail\n }\n },\n config: () => {\n try {\n return window.Tchao?.config() ?? {};\n } catch {\n return {};\n }\n },\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => {\n try {\n window.Tchao?.on(event, callback as (...args: unknown[]) => void);\n } catch {\n // Silent fail\n }\n },\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => {\n try {\n window.Tchao?.off(event, callback as (...args: unknown[]) => void);\n } catch {\n // Silent fail\n }\n },\n isReady: () => initialized && !!window.Tchao,\n destroy: () => {\n try {\n const script = document.querySelector('script[data-tchao-widget]');\n if (script) script.remove();\n const widget = document.getElementById(\"tchao-widget-root\");\n if (widget) widget.remove();\n scriptLoaded = false;\n scriptPromise = null;\n initialized = false;\n currentInstance = null;\n callQueue.length = 0;\n delete window.__TCHAO_CONFIG__;\n delete window.Tchao;\n } catch {\n // Silent fail\n }\n },\n };\n}\n\nfunction safeCall<T>(fn: () => T, fallback: T): T {\n try {\n return fn();\n } catch {\n return fallback;\n }\n}\n\n/**\n * Safe API that works before initialization.\n * Calls are queued and executed once the widget is ready.\n */\nexport const tchao = {\n /**\n * Initialize the widget. Returns a promise that resolves with the instance.\n */\n init,\n\n /**\n * Show the widget launcher. Safe to call before init.\n */\n show: (): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.show(), undefined);\n } else {\n callQueue.push({ type: \"show\" });\n }\n },\n\n /**\n * Hide the widget launcher. Safe to call before init.\n */\n hide: (): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.hide(), undefined);\n } else {\n callQueue.push({ type: \"hide\" });\n }\n },\n\n /**\n * Toggle the chat window. Safe to call before init.\n */\n toggle: (): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.toggle(), undefined);\n } else {\n callQueue.push({ type: \"toggle\" });\n }\n },\n\n /**\n * Open the chat window. Safe to call before init.\n */\n open: (message?: string): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.open(message), undefined);\n } else {\n callQueue.push({ type: \"open\", message });\n }\n },\n\n /**\n * Identify the visitor. Safe to call before init.\n */\n identify: (info: VisitorInfo): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.identify(info), undefined);\n } else {\n callQueue.push({ type: \"identify\", info });\n }\n },\n\n /**\n * Get the current widget configuration.\n */\n config: (): Partial<WidgetConfig> => {\n return safeCall(() => window.Tchao?.config() ?? {}, {});\n },\n\n /**\n * Subscribe to widget events. Safe to call before init.\n */\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]): void => {\n if (window.Tchao) {\n safeCall(\n () => window.Tchao?.on(event, callback as (...args: unknown[]) => void),\n undefined\n );\n } else {\n callQueue.push({\n type: \"on\",\n event,\n callback: callback as (...args: unknown[]) => void,\n });\n }\n },\n\n /**\n * Unsubscribe from widget events.\n */\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]): void => {\n if (window.Tchao) {\n safeCall(\n () =>\n window.Tchao?.off(event, callback as (...args: unknown[]) => void),\n undefined\n );\n } else {\n callQueue.push({\n type: \"off\",\n event,\n callback: callback as (...args: unknown[]) => void,\n });\n }\n },\n\n /**\n * Destroy the widget and clean up resources.\n */\n destroy: (): void => {\n if (currentInstance) {\n currentInstance.destroy();\n }\n },\n\n /**\n * Check if the widget is ready.\n */\n isReady: (): boolean => initialized && !!window.Tchao,\n\n /**\n * Get the current instance (null if not initialized).\n */\n getInstance: (): TchaoInstance | null => currentInstance,\n};\n\nexport const Tchao = {\n init,\n};\n\nexport { init };\nexport default Tchao;\n"],"mappings":"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","names":["WIDGET_SCRIPT_URL","scriptLoaded","scriptPromise","initialized","currentInstance","callQueue","flushQueue","call","loadScript","config","resolve","reject","script","waitForTchao","attempts","check","init","createInstance","message","info","event","callback","widget","safeCall","fn","fallback","tchao","Tchao","npm_default","Tchao"]}
|
package/dist/react.d.mts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { TchaoConfig, VisitorInfo, TchaoEvent, TchaoEventMap } from './npm.mjs';
|
|
2
|
+
export { TchaoInstance, init, tchao } from './npm.mjs';
|
|
3
|
+
|
|
4
|
+
type UseTchaoOptions = TchaoConfig;
|
|
5
|
+
type UseTchaoReturn = {
|
|
6
|
+
/** Whether the widget is ready */
|
|
7
|
+
isReady: boolean;
|
|
8
|
+
/** Whether the widget is currently loading */
|
|
9
|
+
isLoading: boolean;
|
|
10
|
+
/** Error if initialization failed */
|
|
11
|
+
error: Error | null;
|
|
12
|
+
/** Show the widget launcher */
|
|
13
|
+
show: () => void;
|
|
14
|
+
/** Hide the widget launcher */
|
|
15
|
+
hide: () => void;
|
|
16
|
+
/** Toggle the chat window */
|
|
17
|
+
toggle: () => void;
|
|
18
|
+
/** Open the chat window with optional pre-filled message */
|
|
19
|
+
open: (message?: string) => void;
|
|
20
|
+
/** Identify the visitor */
|
|
21
|
+
identify: (info: VisitorInfo) => void;
|
|
22
|
+
/** Get current widget configuration */
|
|
23
|
+
config: () => Partial<TchaoConfig>;
|
|
24
|
+
/** Subscribe to widget events */
|
|
25
|
+
on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;
|
|
26
|
+
/** Unsubscribe from widget events */
|
|
27
|
+
off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* React hook for using the Tchao chat widget.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* function App() {
|
|
35
|
+
* const { isReady, open, identify } = useTchao({
|
|
36
|
+
* websiteId: "your-website-id",
|
|
37
|
+
* });
|
|
38
|
+
*
|
|
39
|
+
* useEffect(() => {
|
|
40
|
+
* if (isReady) {
|
|
41
|
+
* identify({ email: user.email, name: user.name });
|
|
42
|
+
* }
|
|
43
|
+
* }, [isReady, identify]);
|
|
44
|
+
*
|
|
45
|
+
* return <button onClick={() => open()}>Chat with us</button>;
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
declare function useTchao(options: UseTchaoOptions): UseTchaoReturn;
|
|
50
|
+
/**
|
|
51
|
+
* Simple component that initializes Tchao and optionally identifies the user.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```tsx
|
|
55
|
+
* // In your layout or root component
|
|
56
|
+
* <TchaoProvider
|
|
57
|
+
* websiteId="your-website-id"
|
|
58
|
+
* visitor={{ email: user?.email, name: user?.name }}
|
|
59
|
+
* />
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
declare function TchaoProvider({ visitor, onReady, onError, ...config }: TchaoConfig & {
|
|
63
|
+
visitor?: VisitorInfo;
|
|
64
|
+
onReady?: () => void;
|
|
65
|
+
onError?: (error: Error) => void;
|
|
66
|
+
}): null;
|
|
67
|
+
|
|
68
|
+
export { TchaoConfig, TchaoEvent, TchaoEventMap, TchaoProvider, type UseTchaoOptions, type UseTchaoReturn, VisitorInfo, useTchao };
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { TchaoConfig, VisitorInfo, TchaoEvent, TchaoEventMap } from './npm.js';
|
|
2
|
+
export { TchaoInstance, init, tchao } from './npm.js';
|
|
3
|
+
|
|
4
|
+
type UseTchaoOptions = TchaoConfig;
|
|
5
|
+
type UseTchaoReturn = {
|
|
6
|
+
/** Whether the widget is ready */
|
|
7
|
+
isReady: boolean;
|
|
8
|
+
/** Whether the widget is currently loading */
|
|
9
|
+
isLoading: boolean;
|
|
10
|
+
/** Error if initialization failed */
|
|
11
|
+
error: Error | null;
|
|
12
|
+
/** Show the widget launcher */
|
|
13
|
+
show: () => void;
|
|
14
|
+
/** Hide the widget launcher */
|
|
15
|
+
hide: () => void;
|
|
16
|
+
/** Toggle the chat window */
|
|
17
|
+
toggle: () => void;
|
|
18
|
+
/** Open the chat window with optional pre-filled message */
|
|
19
|
+
open: (message?: string) => void;
|
|
20
|
+
/** Identify the visitor */
|
|
21
|
+
identify: (info: VisitorInfo) => void;
|
|
22
|
+
/** Get current widget configuration */
|
|
23
|
+
config: () => Partial<TchaoConfig>;
|
|
24
|
+
/** Subscribe to widget events */
|
|
25
|
+
on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;
|
|
26
|
+
/** Unsubscribe from widget events */
|
|
27
|
+
off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* React hook for using the Tchao chat widget.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* function App() {
|
|
35
|
+
* const { isReady, open, identify } = useTchao({
|
|
36
|
+
* websiteId: "your-website-id",
|
|
37
|
+
* });
|
|
38
|
+
*
|
|
39
|
+
* useEffect(() => {
|
|
40
|
+
* if (isReady) {
|
|
41
|
+
* identify({ email: user.email, name: user.name });
|
|
42
|
+
* }
|
|
43
|
+
* }, [isReady, identify]);
|
|
44
|
+
*
|
|
45
|
+
* return <button onClick={() => open()}>Chat with us</button>;
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
declare function useTchao(options: UseTchaoOptions): UseTchaoReturn;
|
|
50
|
+
/**
|
|
51
|
+
* Simple component that initializes Tchao and optionally identifies the user.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```tsx
|
|
55
|
+
* // In your layout or root component
|
|
56
|
+
* <TchaoProvider
|
|
57
|
+
* websiteId="your-website-id"
|
|
58
|
+
* visitor={{ email: user?.email, name: user?.name }}
|
|
59
|
+
* />
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
declare function TchaoProvider({ visitor, onReady, onError, ...config }: TchaoConfig & {
|
|
63
|
+
visitor?: VisitorInfo;
|
|
64
|
+
onReady?: () => void;
|
|
65
|
+
onError?: (error: Error) => void;
|
|
66
|
+
}): null;
|
|
67
|
+
|
|
68
|
+
export { TchaoConfig, TchaoEvent, TchaoEventMap, TchaoProvider, type UseTchaoOptions, type UseTchaoReturn, VisitorInfo, useTchao };
|
package/dist/react.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var E=Object.defineProperty;var P=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var V=Object.prototype.hasOwnProperty;var W=(e,o)=>{for(var i in o)E(e,i,{get:o[i],enumerable:!0})},O=(e,o,i,c)=>{if(o&&typeof o=="object"||typeof o=="function")for(let t of S(o))!V.call(e,t)&&t!==i&&E(e,t,{get:()=>o[t],enumerable:!(c=P(o,t))||c.enumerable});return e};var L=e=>O(E({},"__esModule",{value:!0}),e);var Q={};W(Q,{TchaoProvider:()=>H,init:()=>v,tchao:()=>s,useTchao:()=>m});module.exports=L(Q);var n=require("react");var U="https://tchao.app/widget.js",T=!1,f=null,w=!1,h=null,r=[];function q(){for(;r.length>0;){let e=r.shift();if(!(!e||!window.Tchao))try{switch(e.type){case"show":window.Tchao.show();break;case"hide":window.Tchao.hide();break;case"toggle":window.Tchao.toggle();break;case"open":window.Tchao.open(e.message);break;case"identify":window.Tchao.identify(e.info);break;case"on":window.Tchao.on(e.event,e.callback);break;case"off":window.Tchao.off(e.event,e.callback);break}}catch{}}}async function F(e){return f||(f=new Promise((o,i)=>{if(T&&window.Tchao){o();return}if(document.querySelector("script[data-tchao-widget]")){T=!0,o();return}window.__TCHAO_CONFIG__=e;let t=document.createElement("script");t.src=e.host?`${e.host}/widget.js`:U,t.async=!0,t.dataset.websiteId=e.websiteId,t.dataset.tchaoWidget="true",t.onload=()=>{T=!0,o()},t.onerror=()=>{i(new Error("Failed to load Tchao widget script"))},document.head.appendChild(t)}),f)}async function N(){return new Promise((e,o)=>{let i=0,c=()=>{window.Tchao?e():i>=50?o(new Error("Tchao widget failed to initialize")):(i++,setTimeout(c,100))};c()})}async function v(e){if(!e.websiteId)throw new Error("websiteId is required");if(w&&window.Tchao&&h)return h;if(await F(e),await N(),!window.Tchao)throw new Error("Tchao widget failed to initialize");return w=!0,h=G(),q(),h}function G(){return{show:()=>{try{window.Tchao?.show()}catch{}},hide:()=>{try{window.Tchao?.hide()}catch{}},toggle:()=>{try{window.Tchao?.toggle()}catch{}},open:e=>{try{window.Tchao?.open(e)}catch{}},identify:e=>{try{window.Tchao?.identify(e)}catch{}},config:()=>{try{return window.Tchao?.config()??{}}catch{return{}}},on:(e,o)=>{try{window.Tchao?.on(e,o)}catch{}},off:(e,o)=>{try{window.Tchao?.off(e,o)}catch{}},isReady:()=>w&&!!window.Tchao,destroy:()=>{try{let e=document.querySelector("script[data-tchao-widget]");e&&e.remove();let o=document.getElementById("tchao-widget-root");o&&o.remove(),T=!1,f=null,w=!1,h=null,r.length=0,delete window.__TCHAO_CONFIG__,delete window.Tchao}catch{}}}}function d(e,o){try{return e()}catch{return o}}var s={init:v,show:()=>{window.Tchao?d(()=>window.Tchao?.show(),void 0):r.push({type:"show"})},hide:()=>{window.Tchao?d(()=>window.Tchao?.hide(),void 0):r.push({type:"hide"})},toggle:()=>{window.Tchao?d(()=>window.Tchao?.toggle(),void 0):r.push({type:"toggle"})},open:e=>{window.Tchao?d(()=>window.Tchao?.open(e),void 0):r.push({type:"open",message:e})},identify:e=>{window.Tchao?d(()=>window.Tchao?.identify(e),void 0):r.push({type:"identify",info:e})},config:()=>d(()=>window.Tchao?.config()??{},{}),on:(e,o)=>{window.Tchao?d(()=>window.Tchao?.on(e,o),void 0):r.push({type:"on",event:e,callback:o})},off:(e,o)=>{window.Tchao?d(()=>window.Tchao?.off(e,o),void 0):r.push({type:"off",event:e,callback:o})},destroy:()=>{h&&h.destroy()},isReady:()=>w&&!!window.Tchao,getInstance:()=>h};function m(e){let[o,i]=(0,n.useState)(!1),[c,t]=(0,n.useState)(!0),[l,g]=(0,n.useState)(null),u=(0,n.useRef)(null),p=(0,n.useRef)(!0);(0,n.useEffect)(()=>(p.current=!0,v(e).then(a=>{p.current&&(u.current=a,i(!0),t(!1))}).catch(a=>{p.current&&(g(a instanceof Error?a:new Error(String(a))),t(!1))}),()=>{p.current=!1,u.current&&(u.current.destroy(),u.current=null)}),[e.websiteId]);let b=(0,n.useCallback)(()=>s.show(),[]),I=(0,n.useCallback)(()=>s.hide(),[]),k=(0,n.useCallback)(()=>s.toggle(),[]),x=(0,n.useCallback)(a=>s.open(a),[]),C=(0,n.useCallback)(a=>s.identify(a),[]),M=(0,n.useCallback)(()=>s.config(),[]),_=(0,n.useCallback)((a,y)=>s.on(a,y),[]),R=(0,n.useCallback)((a,y)=>s.off(a,y),[]);return{isReady:o,isLoading:c,error:l,show:b,hide:I,toggle:k,open:x,identify:C,config:M,on:_,off:R}}function H({visitor:e,onReady:o,onError:i,...c}){let{isReady:t,error:l,identify:g}=m(c);return(0,n.useEffect)(()=>{t&&e&&g(e)},[t,e,g]),(0,n.useEffect)(()=>{t&&o&&o()},[t,o]),(0,n.useEffect)(()=>{l&&i&&i(l)},[l,i]),null}0&&(module.exports={TchaoProvider,init,tchao,useTchao});
|
|
2
|
+
//# sourceMappingURL=react.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/widget/react.ts","../../../src/widget/npm.ts"],"sourcesContent":["import { useEffect, useRef, useState, useCallback } from \"react\";\nimport {\n tchao,\n init,\n type TchaoConfig,\n type TchaoInstance,\n type VisitorInfo,\n type TchaoEvent,\n type TchaoEventMap,\n} from \"./npm\";\n\nexport type { TchaoConfig, TchaoInstance, VisitorInfo, TchaoEvent, TchaoEventMap };\n\nexport type UseTchaoOptions = TchaoConfig;\n\nexport type UseTchaoReturn = {\n /** Whether the widget is ready */\n isReady: boolean;\n /** Whether the widget is currently loading */\n isLoading: boolean;\n /** Error if initialization failed */\n error: Error | null;\n /** Show the widget launcher */\n show: () => void;\n /** Hide the widget launcher */\n hide: () => void;\n /** Toggle the chat window */\n toggle: () => void;\n /** Open the chat window with optional pre-filled message */\n open: (message?: string) => void;\n /** Identify the visitor */\n identify: (info: VisitorInfo) => void;\n /** Get current widget configuration */\n config: () => Partial<TchaoConfig>;\n /** Subscribe to widget events */\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n /** Unsubscribe from widget events */\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n};\n\n/**\n * React hook for using the Tchao chat widget.\n *\n * @example\n * ```tsx\n * function App() {\n * const { isReady, open, identify } = useTchao({\n * websiteId: \"your-website-id\",\n * });\n *\n * useEffect(() => {\n * if (isReady) {\n * identify({ email: user.email, name: user.name });\n * }\n * }, [isReady, identify]);\n *\n * return <button onClick={() => open()}>Chat with us</button>;\n * }\n * ```\n */\nexport function useTchao(options: UseTchaoOptions): UseTchaoReturn {\n const [isReady, setIsReady] = useState(false);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const instanceRef = useRef<TchaoInstance | null>(null);\n const mountedRef = useRef(true);\n\n useEffect(() => {\n mountedRef.current = true;\n\n init(options)\n .then((instance) => {\n if (!mountedRef.current) return;\n instanceRef.current = instance;\n setIsReady(true);\n setIsLoading(false);\n })\n .catch((err) => {\n if (!mountedRef.current) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n setIsLoading(false);\n });\n\n return () => {\n mountedRef.current = false;\n if (instanceRef.current) {\n instanceRef.current.destroy();\n instanceRef.current = null;\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- Only re-init when websiteId changes\n }, [options.websiteId]);\n\n const show = useCallback(() => tchao.show(), []);\n const hide = useCallback(() => tchao.hide(), []);\n const toggle = useCallback(() => tchao.toggle(), []);\n const open = useCallback((message?: string) => tchao.open(message), []);\n const identify = useCallback((info: VisitorInfo) => tchao.identify(info), []);\n const config = useCallback(() => tchao.config(), []);\n const on = useCallback(\n <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) =>\n tchao.on(event, callback),\n []\n );\n const off = useCallback(\n <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) =>\n tchao.off(event, callback),\n []\n );\n\n return {\n isReady,\n isLoading,\n error,\n show,\n hide,\n toggle,\n open,\n identify,\n config,\n on,\n off,\n };\n}\n\n/**\n * Simple component that initializes Tchao and optionally identifies the user.\n *\n * @example\n * ```tsx\n * // In your layout or root component\n * <TchaoProvider\n * websiteId=\"your-website-id\"\n * visitor={{ email: user?.email, name: user?.name }}\n * />\n * ```\n */\nexport function TchaoProvider({\n visitor,\n onReady,\n onError,\n ...config\n}: TchaoConfig & {\n visitor?: VisitorInfo;\n onReady?: () => void;\n onError?: (error: Error) => void;\n}): null {\n const { isReady, error, identify } = useTchao(config);\n\n useEffect(() => {\n if (isReady && visitor) {\n identify(visitor);\n }\n }, [isReady, visitor, identify]);\n\n useEffect(() => {\n if (isReady && onReady) {\n onReady();\n }\n }, [isReady, onReady]);\n\n useEffect(() => {\n if (error && onError) {\n onError(error);\n }\n }, [error, onError]);\n\n return null;\n}\n\nexport { tchao, init };\n","export type VisitorInfo = {\n name?: string;\n email?: string;\n avatar?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type WidgetConfig = {\n websiteId: string;\n position?: \"bottom-right\" | \"bottom-left\";\n primaryColor?: string;\n widgetStyle?: \"bubble\" | \"name_line\" | \"question_cta\";\n themeMode?: \"light\" | \"dark\" | \"system\";\n agentName?: string;\n agentRole?: string;\n agentImage?: string;\n agentWelcomeMessage?: string;\n hidePoweredBy?: boolean;\n bubbleIcon?: string;\n};\n\nexport type TchaoConfig = {\n websiteId: string;\n host?: string;\n convexUrl?: string;\n position?: \"bottom-right\" | \"bottom-left\";\n primaryColor?: string;\n widgetStyle?: \"bubble\" | \"name_line\" | \"question_cta\";\n themeMode?: \"light\" | \"dark\" | \"system\";\n agentName?: string;\n agentRole?: string;\n agentImage?: string;\n agentWelcomeMessage?: string;\n hidePoweredBy?: boolean;\n bubbleIcon?: string;\n};\n\nexport type Message = {\n content: string;\n sender: string;\n timestamp: number;\n};\n\nexport type TchaoEventMap = {\n message: (message: Message) => void;\n open: () => void;\n close: () => void;\n ready: () => void;\n};\n\nexport type TchaoEvent = keyof TchaoEventMap;\n\nexport type TchaoInstance = {\n show: () => void;\n hide: () => void;\n toggle: () => void;\n open: (message?: string) => void;\n identify: (info: VisitorInfo) => void;\n config: () => Partial<WidgetConfig>;\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n destroy: () => void;\n isReady: () => boolean;\n};\n\ntype InternalTchaoInstance = {\n show: () => void;\n hide: () => void;\n toggle: () => void;\n open: (message?: string) => void;\n identify: (info: VisitorInfo) => void;\n config: () => Partial<WidgetConfig>;\n on: (event: string, callback: (...args: unknown[]) => void) => void;\n off: (event: string, callback: (...args: unknown[]) => void) => void;\n};\n\ndeclare global {\n interface Window {\n Tchao?: InternalTchaoInstance;\n __TCHAO_CONFIG__?: TchaoConfig;\n }\n}\n\nconst WIDGET_SCRIPT_URL = \"https://tchao.app/widget.js\";\n\nlet scriptLoaded = false;\nlet scriptPromise: Promise<void> | null = null;\nlet initialized = false;\nlet currentInstance: TchaoInstance | null = null;\n\ntype QueuedCall =\n | { type: \"show\" }\n | { type: \"hide\" }\n | { type: \"toggle\" }\n | { type: \"open\"; message?: string }\n | { type: \"identify\"; info: VisitorInfo }\n | { type: \"on\"; event: string; callback: (...args: unknown[]) => void }\n | { type: \"off\"; event: string; callback: (...args: unknown[]) => void };\n\nconst callQueue: QueuedCall[] = [];\n\nfunction flushQueue(): void {\n while (callQueue.length > 0) {\n const call = callQueue.shift();\n if (!call || !window.Tchao) continue;\n\n try {\n switch (call.type) {\n case \"show\":\n window.Tchao.show();\n break;\n case \"hide\":\n window.Tchao.hide();\n break;\n case \"toggle\":\n window.Tchao.toggle();\n break;\n case \"open\":\n window.Tchao.open(call.message);\n break;\n case \"identify\":\n window.Tchao.identify(call.info);\n break;\n case \"on\":\n window.Tchao.on(call.event, call.callback);\n break;\n case \"off\":\n window.Tchao.off(call.event, call.callback);\n break;\n }\n } catch {\n // Silent fail\n }\n }\n}\n\nasync function loadScript(config: TchaoConfig): Promise<void> {\n if (scriptPromise) return scriptPromise;\n\n scriptPromise = new Promise((resolve, reject) => {\n if (scriptLoaded && window.Tchao) {\n resolve();\n return;\n }\n\n const existingScript = document.querySelector(\n 'script[data-tchao-widget]'\n ) as HTMLScriptElement | null;\n\n if (existingScript) {\n scriptLoaded = true;\n resolve();\n return;\n }\n\n window.__TCHAO_CONFIG__ = config;\n\n const script = document.createElement(\"script\");\n script.src = config.host ? `${config.host}/widget.js` : WIDGET_SCRIPT_URL;\n script.async = true;\n script.dataset.websiteId = config.websiteId;\n script.dataset.tchaoWidget = \"true\";\n\n script.onload = () => {\n scriptLoaded = true;\n resolve();\n };\n\n script.onerror = () => {\n reject(new Error(\"Failed to load Tchao widget script\"));\n };\n\n document.head.appendChild(script);\n });\n\n return scriptPromise;\n}\n\nasync function waitForTchao(): Promise<void> {\n return new Promise((resolve, reject) => {\n let attempts = 0;\n const check = () => {\n if (window.Tchao) {\n resolve();\n } else if (attempts >= 50) {\n reject(new Error(\"Tchao widget failed to initialize\"));\n } else {\n attempts++;\n setTimeout(check, 100);\n }\n };\n check();\n });\n}\n\nasync function init(config: TchaoConfig): Promise<TchaoInstance> {\n if (!config.websiteId) {\n throw new Error(\"websiteId is required\");\n }\n\n if (initialized && window.Tchao && currentInstance) {\n return currentInstance;\n }\n\n await loadScript(config);\n await waitForTchao();\n\n if (!window.Tchao) {\n throw new Error(\"Tchao widget failed to initialize\");\n }\n\n initialized = true;\n currentInstance = createInstance();\n flushQueue();\n return currentInstance;\n}\n\nfunction createInstance(): TchaoInstance {\n return {\n show: () => {\n try {\n window.Tchao?.show();\n } catch {\n // Silent fail\n }\n },\n hide: () => {\n try {\n window.Tchao?.hide();\n } catch {\n // Silent fail\n }\n },\n toggle: () => {\n try {\n window.Tchao?.toggle();\n } catch {\n // Silent fail\n }\n },\n open: (message?: string) => {\n try {\n window.Tchao?.open(message);\n } catch {\n // Silent fail\n }\n },\n identify: (info: VisitorInfo) => {\n try {\n window.Tchao?.identify(info);\n } catch {\n // Silent fail\n }\n },\n config: () => {\n try {\n return window.Tchao?.config() ?? {};\n } catch {\n return {};\n }\n },\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => {\n try {\n window.Tchao?.on(event, callback as (...args: unknown[]) => void);\n } catch {\n // Silent fail\n }\n },\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => {\n try {\n window.Tchao?.off(event, callback as (...args: unknown[]) => void);\n } catch {\n // Silent fail\n }\n },\n isReady: () => initialized && !!window.Tchao,\n destroy: () => {\n try {\n const script = document.querySelector('script[data-tchao-widget]');\n if (script) script.remove();\n const widget = document.getElementById(\"tchao-widget-root\");\n if (widget) widget.remove();\n scriptLoaded = false;\n scriptPromise = null;\n initialized = false;\n currentInstance = null;\n callQueue.length = 0;\n delete window.__TCHAO_CONFIG__;\n delete window.Tchao;\n } catch {\n // Silent fail\n }\n },\n };\n}\n\nfunction safeCall<T>(fn: () => T, fallback: T): T {\n try {\n return fn();\n } catch {\n return fallback;\n }\n}\n\n/**\n * Safe API that works before initialization.\n * Calls are queued and executed once the widget is ready.\n */\nexport const tchao = {\n /**\n * Initialize the widget. Returns a promise that resolves with the instance.\n */\n init,\n\n /**\n * Show the widget launcher. Safe to call before init.\n */\n show: (): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.show(), undefined);\n } else {\n callQueue.push({ type: \"show\" });\n }\n },\n\n /**\n * Hide the widget launcher. Safe to call before init.\n */\n hide: (): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.hide(), undefined);\n } else {\n callQueue.push({ type: \"hide\" });\n }\n },\n\n /**\n * Toggle the chat window. Safe to call before init.\n */\n toggle: (): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.toggle(), undefined);\n } else {\n callQueue.push({ type: \"toggle\" });\n }\n },\n\n /**\n * Open the chat window. Safe to call before init.\n */\n open: (message?: string): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.open(message), undefined);\n } else {\n callQueue.push({ type: \"open\", message });\n }\n },\n\n /**\n * Identify the visitor. Safe to call before init.\n */\n identify: (info: VisitorInfo): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.identify(info), undefined);\n } else {\n callQueue.push({ type: \"identify\", info });\n }\n },\n\n /**\n * Get the current widget configuration.\n */\n config: (): Partial<WidgetConfig> => {\n return safeCall(() => window.Tchao?.config() ?? {}, {});\n },\n\n /**\n * Subscribe to widget events. Safe to call before init.\n */\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]): void => {\n if (window.Tchao) {\n safeCall(\n () => window.Tchao?.on(event, callback as (...args: unknown[]) => void),\n undefined\n );\n } else {\n callQueue.push({\n type: \"on\",\n event,\n callback: callback as (...args: unknown[]) => void,\n });\n }\n },\n\n /**\n * Unsubscribe from widget events.\n */\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]): void => {\n if (window.Tchao) {\n safeCall(\n () =>\n window.Tchao?.off(event, callback as (...args: unknown[]) => void),\n undefined\n );\n } else {\n callQueue.push({\n type: \"off\",\n event,\n callback: callback as (...args: unknown[]) => void,\n });\n }\n },\n\n /**\n * Destroy the widget and clean up resources.\n */\n destroy: (): void => {\n if (currentInstance) {\n currentInstance.destroy();\n }\n },\n\n /**\n * Check if the widget is ready.\n */\n isReady: (): boolean => initialized && !!window.Tchao,\n\n /**\n * Get the current instance (null if not initialized).\n */\n getInstance: (): TchaoInstance | null => currentInstance,\n};\n\nexport const Tchao = {\n init,\n};\n\nexport { init };\nexport default Tchao;\n"],"mappings":"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","names":["react_exports","__export","TchaoProvider","init","tchao","useTchao","__toCommonJS","import_react","WIDGET_SCRIPT_URL","scriptLoaded","scriptPromise","initialized","currentInstance","callQueue","flushQueue","call","loadScript","config","resolve","reject","script","waitForTchao","attempts","check","init","createInstance","message","info","event","callback","widget","safeCall","fn","fallback","tchao","useTchao","options","isReady","setIsReady","isLoading","setIsLoading","error","setError","instanceRef","mountedRef","init","instance","err","show","tchao","hide","toggle","open","message","identify","info","config","on","event","callback","off","TchaoProvider","visitor","onReady","onError"]}
|
package/dist/react.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{useEffect as v,useRef as b,useState as m,useCallback as d}from"react";var S="https://tchao.app/widget.js",T=!1,f=null,w=!1,s=null,a=[];function V(){for(;a.length>0;){let e=a.shift();if(!(!e||!window.Tchao))try{switch(e.type){case"show":window.Tchao.show();break;case"hide":window.Tchao.hide();break;case"toggle":window.Tchao.toggle();break;case"open":window.Tchao.open(e.message);break;case"identify":window.Tchao.identify(e.info);break;case"on":window.Tchao.on(e.event,e.callback);break;case"off":window.Tchao.off(e.event,e.callback);break}}catch{}}}async function W(e){return f||(f=new Promise((o,i)=>{if(T&&window.Tchao){o();return}if(document.querySelector("script[data-tchao-widget]")){T=!0,o();return}window.__TCHAO_CONFIG__=e;let t=document.createElement("script");t.src=e.host?`${e.host}/widget.js`:S,t.async=!0,t.dataset.websiteId=e.websiteId,t.dataset.tchaoWidget="true",t.onload=()=>{T=!0,o()},t.onerror=()=>{i(new Error("Failed to load Tchao widget script"))},document.head.appendChild(t)}),f)}async function O(){return new Promise((e,o)=>{let i=0,h=()=>{window.Tchao?e():i>=50?o(new Error("Tchao widget failed to initialize")):(i++,setTimeout(h,100))};h()})}async function E(e){if(!e.websiteId)throw new Error("websiteId is required");if(w&&window.Tchao&&s)return s;if(await W(e),await O(),!window.Tchao)throw new Error("Tchao widget failed to initialize");return w=!0,s=L(),V(),s}function L(){return{show:()=>{try{window.Tchao?.show()}catch{}},hide:()=>{try{window.Tchao?.hide()}catch{}},toggle:()=>{try{window.Tchao?.toggle()}catch{}},open:e=>{try{window.Tchao?.open(e)}catch{}},identify:e=>{try{window.Tchao?.identify(e)}catch{}},config:()=>{try{return window.Tchao?.config()??{}}catch{return{}}},on:(e,o)=>{try{window.Tchao?.on(e,o)}catch{}},off:(e,o)=>{try{window.Tchao?.off(e,o)}catch{}},isReady:()=>w&&!!window.Tchao,destroy:()=>{try{let e=document.querySelector("script[data-tchao-widget]");e&&e.remove();let o=document.getElementById("tchao-widget-root");o&&o.remove(),T=!1,f=null,w=!1,s=null,a.length=0,delete window.__TCHAO_CONFIG__,delete window.Tchao}catch{}}}}function r(e,o){try{return e()}catch{return o}}var c={init:E,show:()=>{window.Tchao?r(()=>window.Tchao?.show(),void 0):a.push({type:"show"})},hide:()=>{window.Tchao?r(()=>window.Tchao?.hide(),void 0):a.push({type:"hide"})},toggle:()=>{window.Tchao?r(()=>window.Tchao?.toggle(),void 0):a.push({type:"toggle"})},open:e=>{window.Tchao?r(()=>window.Tchao?.open(e),void 0):a.push({type:"open",message:e})},identify:e=>{window.Tchao?r(()=>window.Tchao?.identify(e),void 0):a.push({type:"identify",info:e})},config:()=>r(()=>window.Tchao?.config()??{},{}),on:(e,o)=>{window.Tchao?r(()=>window.Tchao?.on(e,o),void 0):a.push({type:"on",event:e,callback:o})},off:(e,o)=>{window.Tchao?r(()=>window.Tchao?.off(e,o),void 0):a.push({type:"off",event:e,callback:o})},destroy:()=>{s&&s.destroy()},isReady:()=>w&&!!window.Tchao,getInstance:()=>s};function U(e){let[o,i]=m(!1),[h,t]=m(!0),[l,g]=m(null),u=b(null),p=b(!0);v(()=>(p.current=!0,E(e).then(n=>{p.current&&(u.current=n,i(!0),t(!1))}).catch(n=>{p.current&&(g(n instanceof Error?n:new Error(String(n))),t(!1))}),()=>{p.current=!1,u.current&&(u.current.destroy(),u.current=null)}),[e.websiteId]);let I=d(()=>c.show(),[]),k=d(()=>c.hide(),[]),x=d(()=>c.toggle(),[]),C=d(n=>c.open(n),[]),M=d(n=>c.identify(n),[]),_=d(()=>c.config(),[]),R=d((n,y)=>c.on(n,y),[]),P=d((n,y)=>c.off(n,y),[]);return{isReady:o,isLoading:h,error:l,show:I,hide:k,toggle:x,open:C,identify:M,config:_,on:R,off:P}}function G({visitor:e,onReady:o,onError:i,...h}){let{isReady:t,error:l,identify:g}=U(h);return v(()=>{t&&e&&g(e)},[t,e,g]),v(()=>{t&&o&&o()},[t,o]),v(()=>{l&&i&&i(l)},[l,i]),null}export{G as TchaoProvider,E as init,c as tchao,U as useTchao};
|
|
2
|
+
//# sourceMappingURL=react.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/widget/react.ts","../../../src/widget/npm.ts"],"sourcesContent":["import { useEffect, useRef, useState, useCallback } from \"react\";\nimport {\n tchao,\n init,\n type TchaoConfig,\n type TchaoInstance,\n type VisitorInfo,\n type TchaoEvent,\n type TchaoEventMap,\n} from \"./npm\";\n\nexport type { TchaoConfig, TchaoInstance, VisitorInfo, TchaoEvent, TchaoEventMap };\n\nexport type UseTchaoOptions = TchaoConfig;\n\nexport type UseTchaoReturn = {\n /** Whether the widget is ready */\n isReady: boolean;\n /** Whether the widget is currently loading */\n isLoading: boolean;\n /** Error if initialization failed */\n error: Error | null;\n /** Show the widget launcher */\n show: () => void;\n /** Hide the widget launcher */\n hide: () => void;\n /** Toggle the chat window */\n toggle: () => void;\n /** Open the chat window with optional pre-filled message */\n open: (message?: string) => void;\n /** Identify the visitor */\n identify: (info: VisitorInfo) => void;\n /** Get current widget configuration */\n config: () => Partial<TchaoConfig>;\n /** Subscribe to widget events */\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n /** Unsubscribe from widget events */\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n};\n\n/**\n * React hook for using the Tchao chat widget.\n *\n * @example\n * ```tsx\n * function App() {\n * const { isReady, open, identify } = useTchao({\n * websiteId: \"your-website-id\",\n * });\n *\n * useEffect(() => {\n * if (isReady) {\n * identify({ email: user.email, name: user.name });\n * }\n * }, [isReady, identify]);\n *\n * return <button onClick={() => open()}>Chat with us</button>;\n * }\n * ```\n */\nexport function useTchao(options: UseTchaoOptions): UseTchaoReturn {\n const [isReady, setIsReady] = useState(false);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const instanceRef = useRef<TchaoInstance | null>(null);\n const mountedRef = useRef(true);\n\n useEffect(() => {\n mountedRef.current = true;\n\n init(options)\n .then((instance) => {\n if (!mountedRef.current) return;\n instanceRef.current = instance;\n setIsReady(true);\n setIsLoading(false);\n })\n .catch((err) => {\n if (!mountedRef.current) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n setIsLoading(false);\n });\n\n return () => {\n mountedRef.current = false;\n if (instanceRef.current) {\n instanceRef.current.destroy();\n instanceRef.current = null;\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- Only re-init when websiteId changes\n }, [options.websiteId]);\n\n const show = useCallback(() => tchao.show(), []);\n const hide = useCallback(() => tchao.hide(), []);\n const toggle = useCallback(() => tchao.toggle(), []);\n const open = useCallback((message?: string) => tchao.open(message), []);\n const identify = useCallback((info: VisitorInfo) => tchao.identify(info), []);\n const config = useCallback(() => tchao.config(), []);\n const on = useCallback(\n <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) =>\n tchao.on(event, callback),\n []\n );\n const off = useCallback(\n <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) =>\n tchao.off(event, callback),\n []\n );\n\n return {\n isReady,\n isLoading,\n error,\n show,\n hide,\n toggle,\n open,\n identify,\n config,\n on,\n off,\n };\n}\n\n/**\n * Simple component that initializes Tchao and optionally identifies the user.\n *\n * @example\n * ```tsx\n * // In your layout or root component\n * <TchaoProvider\n * websiteId=\"your-website-id\"\n * visitor={{ email: user?.email, name: user?.name }}\n * />\n * ```\n */\nexport function TchaoProvider({\n visitor,\n onReady,\n onError,\n ...config\n}: TchaoConfig & {\n visitor?: VisitorInfo;\n onReady?: () => void;\n onError?: (error: Error) => void;\n}): null {\n const { isReady, error, identify } = useTchao(config);\n\n useEffect(() => {\n if (isReady && visitor) {\n identify(visitor);\n }\n }, [isReady, visitor, identify]);\n\n useEffect(() => {\n if (isReady && onReady) {\n onReady();\n }\n }, [isReady, onReady]);\n\n useEffect(() => {\n if (error && onError) {\n onError(error);\n }\n }, [error, onError]);\n\n return null;\n}\n\nexport { tchao, init };\n","export type VisitorInfo = {\n name?: string;\n email?: string;\n avatar?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type WidgetConfig = {\n websiteId: string;\n position?: \"bottom-right\" | \"bottom-left\";\n primaryColor?: string;\n widgetStyle?: \"bubble\" | \"name_line\" | \"question_cta\";\n themeMode?: \"light\" | \"dark\" | \"system\";\n agentName?: string;\n agentRole?: string;\n agentImage?: string;\n agentWelcomeMessage?: string;\n hidePoweredBy?: boolean;\n bubbleIcon?: string;\n};\n\nexport type TchaoConfig = {\n websiteId: string;\n host?: string;\n convexUrl?: string;\n position?: \"bottom-right\" | \"bottom-left\";\n primaryColor?: string;\n widgetStyle?: \"bubble\" | \"name_line\" | \"question_cta\";\n themeMode?: \"light\" | \"dark\" | \"system\";\n agentName?: string;\n agentRole?: string;\n agentImage?: string;\n agentWelcomeMessage?: string;\n hidePoweredBy?: boolean;\n bubbleIcon?: string;\n};\n\nexport type Message = {\n content: string;\n sender: string;\n timestamp: number;\n};\n\nexport type TchaoEventMap = {\n message: (message: Message) => void;\n open: () => void;\n close: () => void;\n ready: () => void;\n};\n\nexport type TchaoEvent = keyof TchaoEventMap;\n\nexport type TchaoInstance = {\n show: () => void;\n hide: () => void;\n toggle: () => void;\n open: (message?: string) => void;\n identify: (info: VisitorInfo) => void;\n config: () => Partial<WidgetConfig>;\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n destroy: () => void;\n isReady: () => boolean;\n};\n\ntype InternalTchaoInstance = {\n show: () => void;\n hide: () => void;\n toggle: () => void;\n open: (message?: string) => void;\n identify: (info: VisitorInfo) => void;\n config: () => Partial<WidgetConfig>;\n on: (event: string, callback: (...args: unknown[]) => void) => void;\n off: (event: string, callback: (...args: unknown[]) => void) => void;\n};\n\ndeclare global {\n interface Window {\n Tchao?: InternalTchaoInstance;\n __TCHAO_CONFIG__?: TchaoConfig;\n }\n}\n\nconst WIDGET_SCRIPT_URL = \"https://tchao.app/widget.js\";\n\nlet scriptLoaded = false;\nlet scriptPromise: Promise<void> | null = null;\nlet initialized = false;\nlet currentInstance: TchaoInstance | null = null;\n\ntype QueuedCall =\n | { type: \"show\" }\n | { type: \"hide\" }\n | { type: \"toggle\" }\n | { type: \"open\"; message?: string }\n | { type: \"identify\"; info: VisitorInfo }\n | { type: \"on\"; event: string; callback: (...args: unknown[]) => void }\n | { type: \"off\"; event: string; callback: (...args: unknown[]) => void };\n\nconst callQueue: QueuedCall[] = [];\n\nfunction flushQueue(): void {\n while (callQueue.length > 0) {\n const call = callQueue.shift();\n if (!call || !window.Tchao) continue;\n\n try {\n switch (call.type) {\n case \"show\":\n window.Tchao.show();\n break;\n case \"hide\":\n window.Tchao.hide();\n break;\n case \"toggle\":\n window.Tchao.toggle();\n break;\n case \"open\":\n window.Tchao.open(call.message);\n break;\n case \"identify\":\n window.Tchao.identify(call.info);\n break;\n case \"on\":\n window.Tchao.on(call.event, call.callback);\n break;\n case \"off\":\n window.Tchao.off(call.event, call.callback);\n break;\n }\n } catch {\n // Silent fail\n }\n }\n}\n\nasync function loadScript(config: TchaoConfig): Promise<void> {\n if (scriptPromise) return scriptPromise;\n\n scriptPromise = new Promise((resolve, reject) => {\n if (scriptLoaded && window.Tchao) {\n resolve();\n return;\n }\n\n const existingScript = document.querySelector(\n 'script[data-tchao-widget]'\n ) as HTMLScriptElement | null;\n\n if (existingScript) {\n scriptLoaded = true;\n resolve();\n return;\n }\n\n window.__TCHAO_CONFIG__ = config;\n\n const script = document.createElement(\"script\");\n script.src = config.host ? `${config.host}/widget.js` : WIDGET_SCRIPT_URL;\n script.async = true;\n script.dataset.websiteId = config.websiteId;\n script.dataset.tchaoWidget = \"true\";\n\n script.onload = () => {\n scriptLoaded = true;\n resolve();\n };\n\n script.onerror = () => {\n reject(new Error(\"Failed to load Tchao widget script\"));\n };\n\n document.head.appendChild(script);\n });\n\n return scriptPromise;\n}\n\nasync function waitForTchao(): Promise<void> {\n return new Promise((resolve, reject) => {\n let attempts = 0;\n const check = () => {\n if (window.Tchao) {\n resolve();\n } else if (attempts >= 50) {\n reject(new Error(\"Tchao widget failed to initialize\"));\n } else {\n attempts++;\n setTimeout(check, 100);\n }\n };\n check();\n });\n}\n\nasync function init(config: TchaoConfig): Promise<TchaoInstance> {\n if (!config.websiteId) {\n throw new Error(\"websiteId is required\");\n }\n\n if (initialized && window.Tchao && currentInstance) {\n return currentInstance;\n }\n\n await loadScript(config);\n await waitForTchao();\n\n if (!window.Tchao) {\n throw new Error(\"Tchao widget failed to initialize\");\n }\n\n initialized = true;\n currentInstance = createInstance();\n flushQueue();\n return currentInstance;\n}\n\nfunction createInstance(): TchaoInstance {\n return {\n show: () => {\n try {\n window.Tchao?.show();\n } catch {\n // Silent fail\n }\n },\n hide: () => {\n try {\n window.Tchao?.hide();\n } catch {\n // Silent fail\n }\n },\n toggle: () => {\n try {\n window.Tchao?.toggle();\n } catch {\n // Silent fail\n }\n },\n open: (message?: string) => {\n try {\n window.Tchao?.open(message);\n } catch {\n // Silent fail\n }\n },\n identify: (info: VisitorInfo) => {\n try {\n window.Tchao?.identify(info);\n } catch {\n // Silent fail\n }\n },\n config: () => {\n try {\n return window.Tchao?.config() ?? {};\n } catch {\n return {};\n }\n },\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => {\n try {\n window.Tchao?.on(event, callback as (...args: unknown[]) => void);\n } catch {\n // Silent fail\n }\n },\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => {\n try {\n window.Tchao?.off(event, callback as (...args: unknown[]) => void);\n } catch {\n // Silent fail\n }\n },\n isReady: () => initialized && !!window.Tchao,\n destroy: () => {\n try {\n const script = document.querySelector('script[data-tchao-widget]');\n if (script) script.remove();\n const widget = document.getElementById(\"tchao-widget-root\");\n if (widget) widget.remove();\n scriptLoaded = false;\n scriptPromise = null;\n initialized = false;\n currentInstance = null;\n callQueue.length = 0;\n delete window.__TCHAO_CONFIG__;\n delete window.Tchao;\n } catch {\n // Silent fail\n }\n },\n };\n}\n\nfunction safeCall<T>(fn: () => T, fallback: T): T {\n try {\n return fn();\n } catch {\n return fallback;\n }\n}\n\n/**\n * Safe API that works before initialization.\n * Calls are queued and executed once the widget is ready.\n */\nexport const tchao = {\n /**\n * Initialize the widget. Returns a promise that resolves with the instance.\n */\n init,\n\n /**\n * Show the widget launcher. Safe to call before init.\n */\n show: (): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.show(), undefined);\n } else {\n callQueue.push({ type: \"show\" });\n }\n },\n\n /**\n * Hide the widget launcher. Safe to call before init.\n */\n hide: (): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.hide(), undefined);\n } else {\n callQueue.push({ type: \"hide\" });\n }\n },\n\n /**\n * Toggle the chat window. Safe to call before init.\n */\n toggle: (): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.toggle(), undefined);\n } else {\n callQueue.push({ type: \"toggle\" });\n }\n },\n\n /**\n * Open the chat window. Safe to call before init.\n */\n open: (message?: string): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.open(message), undefined);\n } else {\n callQueue.push({ type: \"open\", message });\n }\n },\n\n /**\n * Identify the visitor. Safe to call before init.\n */\n identify: (info: VisitorInfo): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.identify(info), undefined);\n } else {\n callQueue.push({ type: \"identify\", info });\n }\n },\n\n /**\n * Get the current widget configuration.\n */\n config: (): Partial<WidgetConfig> => {\n return safeCall(() => window.Tchao?.config() ?? {}, {});\n },\n\n /**\n * Subscribe to widget events. Safe to call before init.\n */\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]): void => {\n if (window.Tchao) {\n safeCall(\n () => window.Tchao?.on(event, callback as (...args: unknown[]) => void),\n undefined\n );\n } else {\n callQueue.push({\n type: \"on\",\n event,\n callback: callback as (...args: unknown[]) => void,\n });\n }\n },\n\n /**\n * Unsubscribe from widget events.\n */\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]): void => {\n if (window.Tchao) {\n safeCall(\n () =>\n window.Tchao?.off(event, callback as (...args: unknown[]) => void),\n undefined\n );\n } else {\n callQueue.push({\n type: \"off\",\n event,\n callback: callback as (...args: unknown[]) => void,\n });\n }\n },\n\n /**\n * Destroy the widget and clean up resources.\n */\n destroy: (): void => {\n if (currentInstance) {\n currentInstance.destroy();\n }\n },\n\n /**\n * Check if the widget is ready.\n */\n isReady: (): boolean => initialized && !!window.Tchao,\n\n /**\n * Get the current instance (null if not initialized).\n */\n getInstance: (): TchaoInstance | null => currentInstance,\n};\n\nexport const Tchao = {\n init,\n};\n\nexport { init };\nexport default Tchao;\n"],"mappings":"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","names":["useEffect","useRef","useState","useCallback","WIDGET_SCRIPT_URL","scriptLoaded","scriptPromise","initialized","currentInstance","callQueue","flushQueue","call","loadScript","config","resolve","reject","script","waitForTchao","attempts","check","init","createInstance","message","info","event","callback","widget","safeCall","fn","fallback","tchao","useTchao","options","isReady","setIsReady","useState","isLoading","setIsLoading","error","setError","instanceRef","useRef","mountedRef","useEffect","init","instance","err","show","useCallback","tchao","hide","toggle","open","message","identify","info","config","on","event","callback","off","TchaoProvider","visitor","onReady","onError"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tchao",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "JavaScript SDK for Tchao chat widget",
|
|
5
5
|
"main": "./dist/npm.js",
|
|
6
6
|
"module": "./dist/npm.mjs",
|
|
@@ -10,6 +10,11 @@
|
|
|
10
10
|
"types": "./dist/npm.d.ts",
|
|
11
11
|
"import": "./dist/npm.mjs",
|
|
12
12
|
"require": "./dist/npm.js"
|
|
13
|
+
},
|
|
14
|
+
"./react": {
|
|
15
|
+
"types": "./dist/react.d.ts",
|
|
16
|
+
"import": "./dist/react.mjs",
|
|
17
|
+
"require": "./dist/react.js"
|
|
13
18
|
}
|
|
14
19
|
},
|
|
15
20
|
"files": [
|
|
@@ -21,11 +26,22 @@
|
|
|
21
26
|
"widget",
|
|
22
27
|
"sdk",
|
|
23
28
|
"customer-support",
|
|
24
|
-
"live-chat"
|
|
29
|
+
"live-chat",
|
|
30
|
+
"react"
|
|
25
31
|
],
|
|
26
32
|
"author": "Tchao",
|
|
27
33
|
"license": "MIT",
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"react": ">=17.0.0"
|
|
36
|
+
},
|
|
37
|
+
"peerDependenciesMeta": {
|
|
38
|
+
"react": {
|
|
39
|
+
"optional": true
|
|
40
|
+
}
|
|
41
|
+
},
|
|
28
42
|
"devDependencies": {
|
|
43
|
+
"@types/react": "^19.1.8",
|
|
44
|
+
"react": "^19.1.0",
|
|
29
45
|
"tsup": "^8.5.0",
|
|
30
46
|
"typescript": "^5.9.3"
|
|
31
47
|
},
|