tchao 0.1.3 → 1.0.2

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 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
- ### Option 2: Script tag
15
+ ## Quick Start
18
16
 
19
- ```html
20
- <script
21
- src="https://tchao.app/widget.js"
22
- data-website-id="your-website-id"
23
- ></script>
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
- ## Usage
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
- ### npm package
56
+ ### Vanilla JavaScript
29
57
 
30
58
  ```typescript
31
- import { Tchao } from "tchao";
59
+ import { tchao } from "tchao";
32
60
 
33
- // Initialize the widget
34
- const widget = await Tchao.init({
35
- websiteId: "your-website-id",
36
- });
61
+ // Initialize (call once)
62
+ await tchao.init({ websiteId: "your-website-id" });
37
63
 
38
- // Open the chat window
39
- widget.open();
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 tag (global object)
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, access via global object
51
- window.Tchao.open();
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
- ### `Tchao.init(config)` (npm only)
63
-
64
- Initialize the Tchao widget programmatically.
65
-
66
- ```typescript
67
- const widget = await Tchao.init({
68
- websiteId: "your-website-id", // Required
69
- host: "https://tchao.app", // Optional, for self-hosted instances
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
- Returns a `Promise<TchaoInstance>`.
74
-
75
- ### Instance Methods
76
-
77
- #### `widget.show()`
78
-
79
- Show the widget launcher button.
104
+ ### Safe API: `tchao`
80
105
 
81
- #### `widget.hide()`
106
+ All methods are safe to call at any time - they will queue and execute when ready.
82
107
 
83
- Hide the widget launcher button.
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
- #### `widget.identify(info)`
111
+ // Initialize
112
+ await tchao.init({ websiteId: "your-website-id" });
94
113
 
95
- Identify the visitor with their information.
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
- ```typescript
98
- widget.identify({
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
- #### `widget.config(options)`
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
- Update widget configuration.
135
+ // Cleanup
136
+ tchao.destroy();
112
137
 
113
- ```typescript
114
- widget.config({
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
- #### `widget.on(event, callback)`
122
-
123
- Subscribe to widget events.
142
+ ### Init Config
124
143
 
125
144
  ```typescript
126
- widget.on("message", (message) => {
127
- console.log("New message:", message.content);
128
- });
129
-
130
- widget.on("open", () => {
131
- console.log("Chat opened");
132
- });
133
-
134
- widget.on("close", () => {
135
- console.log("Chat closed");
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
- #### `widget.off(event, callback)`
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
- Unsubscribe from widget events.
169
+ ### TypeScript
146
170
 
147
171
  ```typescript
148
- const handleMessage = (message) => console.log(message);
149
- widget.on("message", handleMessage);
150
- widget.off("message", handleMessage);
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
- #### `widget.destroy()` (npm only)
186
+ ## Migration from v0.1.3
154
187
 
155
- Clean up and remove the widget from the page.
188
+ The API is backward compatible. New additions:
156
189
 
157
190
  ```typescript
158
- widget.destroy();
159
- ```
191
+ // New: Safe API (no try/catch needed)
192
+ import { tchao } from "tchao";
193
+ tchao.identify({ email: "..." }); // Works before init!
160
194
 
161
- ## TypeScript
195
+ // New: React hook
196
+ import { useTchao } from "tchao/react";
162
197
 
163
- Full TypeScript support is included. Import types as needed:
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: (opts: Partial<WidgetConfig>) => void;
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?: TchaoInstance;
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: (opts: Partial<WidgetConfig>) => void;
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?: TchaoInstance;
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 c=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var p=(e,o)=>{for(var t in o)c(e,t,{get:o[t],enumerable:!0})},f=(e,o,t,i)=>{if(o&&typeof o=="object"||typeof o=="function")for(let r of h(o))!l.call(e,r)&&r!==t&&c(e,r,{get:()=>o[r],enumerable:!(i=g(o,r))||i.enumerable});return e};var u=e=>f(c({},"__esModule",{value:!0}),e);var y={};p(y,{Tchao:()=>w,default:()=>v,init:()=>s});module.exports=u(y);var m="https://tchao.app/widget.js",d=!1,a=null;function T(e,o){return a||(a=new Promise((t,i)=>{if(d&&window.Tchao){t();return}if(document.querySelector("script[data-tchao-widget]")){d=!0,t();return}let n=document.createElement("script");n.src=o?`${o}/widget.js`:m,n.async=!0,n.dataset.websiteId=e,n.dataset.tchaoWidget="true",n.onload=()=>{d=!0,t()},n.onerror=()=>{i(new Error("Failed to load Tchao widget script"))},document.head.appendChild(n)}),a)}async function s(e){if(!e.websiteId)throw new Error("websiteId is required");await T(e.websiteId,e.host);let o=0;for(;!window.Tchao&&o<50;)await new Promise(t=>setTimeout(t,100)),o++;if(!window.Tchao)throw new Error("Tchao widget failed to initialize");return{show:()=>window.Tchao?.show(),hide:()=>window.Tchao?.hide(),toggle:()=>window.Tchao?.toggle(),open:()=>window.Tchao?.open(),identify:t=>window.Tchao?.identify(t),config:t=>window.Tchao?.config(t),on:(t,i)=>window.Tchao?.on(t,i),off:(t,i)=>window.Tchao?.off(t,i),destroy:()=>{let t=document.querySelector("script[data-tchao-widget]");t&&t.remove();let i=document.getElementById("tchao-widget");i&&i.remove(),d=!1,a=null}}}var w={init:s},v=w;0&&(module.exports={Tchao,init});
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 d="https://tchao.app/widget.js",a=!1,r=null;function c(i,n){return r||(r=new Promise((t,o)=>{if(a&&window.Tchao){t();return}if(document.querySelector("script[data-tchao-widget]")){a=!0,t();return}let e=document.createElement("script");e.src=n?`${n}/widget.js`:d,e.async=!0,e.dataset.websiteId=i,e.dataset.tchaoWidget="true",e.onload=()=>{a=!0,t()},e.onerror=()=>{o(new Error("Failed to load Tchao widget script"))},document.head.appendChild(e)}),r)}async function s(i){if(!i.websiteId)throw new Error("websiteId is required");await c(i.websiteId,i.host);let n=0;for(;!window.Tchao&&n<50;)await new Promise(t=>setTimeout(t,100)),n++;if(!window.Tchao)throw new Error("Tchao widget failed to initialize");return{show:()=>window.Tchao?.show(),hide:()=>window.Tchao?.hide(),toggle:()=>window.Tchao?.toggle(),open:()=>window.Tchao?.open(),identify:t=>window.Tchao?.identify(t),config:t=>window.Tchao?.config(t),on:(t,o)=>window.Tchao?.on(t,o),off:(t,o)=>window.Tchao?.off(t,o),destroy:()=>{let t=document.querySelector("script[data-tchao-widget]");t&&t.remove();let o=document.getElementById("tchao-widget");o&&o.remove(),a=!1,r=null}}}var w={init:s},h=w;export{w as Tchao,h as default,s as init};
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"]}
@@ -0,0 +1,73 @@
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
+ * visitorEmail={user?.email}
59
+ * visitorName={user?.name}
60
+ * visitorAvatar={user?.image}
61
+ * />
62
+ * ```
63
+ */
64
+ declare function TchaoProvider({ visitorEmail, visitorName, visitorAvatar, visitorMetadata, onReady, onError, ...config }: TchaoConfig & {
65
+ visitorEmail?: string;
66
+ visitorName?: string;
67
+ visitorAvatar?: string;
68
+ visitorMetadata?: Record<string, unknown>;
69
+ onReady?: () => void;
70
+ onError?: (error: Error) => void;
71
+ }): null;
72
+
73
+ export { TchaoConfig, TchaoEvent, TchaoEventMap, TchaoProvider, type UseTchaoOptions, type UseTchaoReturn, VisitorInfo, useTchao };
@@ -0,0 +1,73 @@
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
+ * visitorEmail={user?.email}
59
+ * visitorName={user?.name}
60
+ * visitorAvatar={user?.image}
61
+ * />
62
+ * ```
63
+ */
64
+ declare function TchaoProvider({ visitorEmail, visitorName, visitorAvatar, visitorMetadata, onReady, onError, ...config }: TchaoConfig & {
65
+ visitorEmail?: string;
66
+ visitorName?: string;
67
+ visitorAvatar?: string;
68
+ visitorMetadata?: Record<string, unknown>;
69
+ onReady?: () => void;
70
+ onError?: (error: Error) => void;
71
+ }): null;
72
+
73
+ export { TchaoConfig, TchaoEvent, TchaoEventMap, TchaoProvider, type UseTchaoOptions, type UseTchaoReturn, VisitorInfo, useTchao };
package/dist/react.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";var m=Object.defineProperty;var P=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var V=Object.prototype.hasOwnProperty;var W=(e,o)=>{for(var i in o)m(e,i,{get:o[i],enumerable:!0})},O=(e,o,i,r)=>{if(o&&typeof o=="object"||typeof o=="function")for(let n of S(o))!V.call(e,n)&&n!==i&&m(e,n,{get:()=>o[n],enumerable:!(r=P(o,n))||r.enumerable});return e};var L=e=>O(m({},"__esModule",{value:!0}),e);var Q={};W(Q,{TchaoProvider:()=>N,init:()=>y,tchao:()=>s,useTchao:()=>b});module.exports=L(Q);var t=require("react");var U="https://tchao.app/widget.js",T=!1,f=null,u=!1,g=null,c=[];function q(){for(;c.length>0;){let e=c.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 n=document.createElement("script");n.src=e.host?`${e.host}/widget.js`:U,n.async=!0,n.dataset.websiteId=e.websiteId,n.dataset.tchaoWidget="true",n.onload=()=>{T=!0,o()},n.onerror=()=>{i(new Error("Failed to load Tchao widget script"))},document.head.appendChild(n)}),f)}async function G(){return new Promise((e,o)=>{let i=0,r=()=>{window.Tchao?e():i>=50?o(new Error("Tchao widget failed to initialize")):(i++,setTimeout(r,100))};r()})}async function y(e){if(!e.websiteId)throw new Error("websiteId is required");if(u&&window.Tchao&&g)return g;if(await F(e),await G(),!window.Tchao)throw new Error("Tchao widget failed to initialize");return u=!0,g=H(),q(),g}function H(){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:()=>u&&!!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,u=!1,g=null,c.length=0,delete window.__TCHAO_CONFIG__,delete window.Tchao}catch{}}}}function l(e,o){try{return e()}catch{return o}}var s={init:y,show:()=>{window.Tchao?l(()=>window.Tchao?.show(),void 0):c.push({type:"show"})},hide:()=>{window.Tchao?l(()=>window.Tchao?.hide(),void 0):c.push({type:"hide"})},toggle:()=>{window.Tchao?l(()=>window.Tchao?.toggle(),void 0):c.push({type:"toggle"})},open:e=>{window.Tchao?l(()=>window.Tchao?.open(e),void 0):c.push({type:"open",message:e})},identify:e=>{window.Tchao?l(()=>window.Tchao?.identify(e),void 0):c.push({type:"identify",info:e})},config:()=>l(()=>window.Tchao?.config()??{},{}),on:(e,o)=>{window.Tchao?l(()=>window.Tchao?.on(e,o),void 0):c.push({type:"on",event:e,callback:o})},off:(e,o)=>{window.Tchao?l(()=>window.Tchao?.off(e,o),void 0):c.push({type:"off",event:e,callback:o})},destroy:()=>{g&&g.destroy()},isReady:()=>u&&!!window.Tchao,getInstance:()=>g};function b(e){let[o,i]=(0,t.useState)(!1),[r,n]=(0,t.useState)(!0),[w,v]=(0,t.useState)(null),d=(0,t.useRef)(null),h=(0,t.useRef)(!0);(0,t.useEffect)(()=>(h.current=!0,y(e).then(a=>{h.current&&(d.current=a,i(!0),n(!1))}).catch(a=>{h.current&&(v(a instanceof Error?a:new Error(String(a))),n(!1))}),()=>{h.current=!1,d.current&&(d.current.destroy(),d.current=null)}),[e.websiteId]);let p=(0,t.useCallback)(()=>s.show(),[]),I=(0,t.useCallback)(()=>s.hide(),[]),k=(0,t.useCallback)(()=>s.toggle(),[]),x=(0,t.useCallback)(a=>s.open(a),[]),C=(0,t.useCallback)(a=>s.identify(a),[]),_=(0,t.useCallback)(()=>s.config(),[]),M=(0,t.useCallback)((a,E)=>s.on(a,E),[]),R=(0,t.useCallback)((a,E)=>s.off(a,E),[]);return{isReady:o,isLoading:r,error:w,show:p,hide:I,toggle:k,open:x,identify:C,config:_,on:M,off:R}}function N({visitorEmail:e,visitorName:o,visitorAvatar:i,visitorMetadata:r,onReady:n,onError:w,...v}){let{isReady:d,error:h,identify:p}=b(v);return(0,t.useEffect)(()=>{d&&(!e&&!o&&!i&&!r||p({email:e,name:o,avatar:i,metadata:r}))},[d,e,o,i,r,p]),(0,t.useEffect)(()=>{d&&n&&n()},[d,n]),(0,t.useEffect)(()=>{h&&w&&w(h)},[h,w]),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 {\n TchaoConfig,\n TchaoInstance,\n VisitorInfo,\n TchaoEvent,\n TchaoEventMap,\n};\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 * visitorEmail={user?.email}\n * visitorName={user?.name}\n * visitorAvatar={user?.image}\n * />\n * ```\n */\nexport function TchaoProvider({\n visitorEmail,\n visitorName,\n visitorAvatar,\n visitorMetadata,\n onReady,\n onError,\n ...config\n}: TchaoConfig & {\n visitorEmail?: string;\n visitorName?: string;\n visitorAvatar?: string;\n visitorMetadata?: Record<string, unknown>;\n onReady?: () => void;\n onError?: (error: Error) => void;\n}): null {\n const { isReady, error, identify } = useTchao(config);\n\n useEffect(() => {\n if (!isReady) return;\n if (!visitorEmail && !visitorName && !visitorAvatar && !visitorMetadata)\n return;\n\n identify({\n email: visitorEmail,\n name: visitorName,\n avatar: visitorAvatar,\n metadata: visitorMetadata,\n });\n }, [isReady, visitorEmail, visitorName, visitorAvatar, visitorMetadata, 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","visitorEmail","visitorName","visitorAvatar","visitorMetadata","onReady","onError"]}
package/dist/react.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import{useEffect as y,useRef as I,useState as b,useCallback as g}from"react";var S="https://tchao.app/widget.js",T=!1,f=null,u=!1,l=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,r=()=>{window.Tchao?e():i>=50?o(new Error("Tchao widget failed to initialize")):(i++,setTimeout(r,100))};r()})}async function m(e){if(!e.websiteId)throw new Error("websiteId is required");if(u&&window.Tchao&&l)return l;if(await W(e),await O(),!window.Tchao)throw new Error("Tchao widget failed to initialize");return u=!0,l=L(),V(),l}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:()=>u&&!!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,u=!1,l=null,a.length=0,delete window.__TCHAO_CONFIG__,delete window.Tchao}catch{}}}}function h(e,o){try{return e()}catch{return o}}var s={init:m,show:()=>{window.Tchao?h(()=>window.Tchao?.show(),void 0):a.push({type:"show"})},hide:()=>{window.Tchao?h(()=>window.Tchao?.hide(),void 0):a.push({type:"hide"})},toggle:()=>{window.Tchao?h(()=>window.Tchao?.toggle(),void 0):a.push({type:"toggle"})},open:e=>{window.Tchao?h(()=>window.Tchao?.open(e),void 0):a.push({type:"open",message:e})},identify:e=>{window.Tchao?h(()=>window.Tchao?.identify(e),void 0):a.push({type:"identify",info:e})},config:()=>h(()=>window.Tchao?.config()??{},{}),on:(e,o)=>{window.Tchao?h(()=>window.Tchao?.on(e,o),void 0):a.push({type:"on",event:e,callback:o})},off:(e,o)=>{window.Tchao?h(()=>window.Tchao?.off(e,o),void 0):a.push({type:"off",event:e,callback:o})},destroy:()=>{l&&l.destroy()},isReady:()=>u&&!!window.Tchao,getInstance:()=>l};function U(e){let[o,i]=b(!1),[r,t]=b(!0),[w,v]=b(null),c=I(null),d=I(!0);y(()=>(d.current=!0,m(e).then(n=>{d.current&&(c.current=n,i(!0),t(!1))}).catch(n=>{d.current&&(v(n instanceof Error?n:new Error(String(n))),t(!1))}),()=>{d.current=!1,c.current&&(c.current.destroy(),c.current=null)}),[e.websiteId]);let p=g(()=>s.show(),[]),k=g(()=>s.hide(),[]),x=g(()=>s.toggle(),[]),C=g(n=>s.open(n),[]),_=g(n=>s.identify(n),[]),M=g(()=>s.config(),[]),R=g((n,E)=>s.on(n,E),[]),P=g((n,E)=>s.off(n,E),[]);return{isReady:o,isLoading:r,error:w,show:p,hide:k,toggle:x,open:C,identify:_,config:M,on:R,off:P}}function H({visitorEmail:e,visitorName:o,visitorAvatar:i,visitorMetadata:r,onReady:t,onError:w,...v}){let{isReady:c,error:d,identify:p}=U(v);return y(()=>{c&&(!e&&!o&&!i&&!r||p({email:e,name:o,avatar:i,metadata:r}))},[c,e,o,i,r,p]),y(()=>{c&&t&&t()},[c,t]),y(()=>{d&&w&&w(d)},[d,w]),null}export{H as TchaoProvider,m as init,s 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 {\n TchaoConfig,\n TchaoInstance,\n VisitorInfo,\n TchaoEvent,\n TchaoEventMap,\n};\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 * visitorEmail={user?.email}\n * visitorName={user?.name}\n * visitorAvatar={user?.image}\n * />\n * ```\n */\nexport function TchaoProvider({\n visitorEmail,\n visitorName,\n visitorAvatar,\n visitorMetadata,\n onReady,\n onError,\n ...config\n}: TchaoConfig & {\n visitorEmail?: string;\n visitorName?: string;\n visitorAvatar?: string;\n visitorMetadata?: Record<string, unknown>;\n onReady?: () => void;\n onError?: (error: Error) => void;\n}): null {\n const { isReady, error, identify } = useTchao(config);\n\n useEffect(() => {\n if (!isReady) return;\n if (!visitorEmail && !visitorName && !visitorAvatar && !visitorMetadata)\n return;\n\n identify({\n email: visitorEmail,\n name: visitorName,\n avatar: visitorAvatar,\n metadata: visitorMetadata,\n });\n }, [isReady, visitorEmail, visitorName, visitorAvatar, visitorMetadata, 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","visitorEmail","visitorName","visitorAvatar","visitorMetadata","onReady","onError"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tchao",
3
- "version": "0.1.3",
3
+ "version": "1.0.2",
4
4
  "description": "JavaScript SDK for Tchao chat widget",
5
5
  "main": "./dist/npm.js",
6
6
  "module": "./dist/npm.mjs",
@@ -10,35 +10,52 @@
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": [
16
21
  "dist"
17
22
  ],
23
+ "scripts": {
24
+ "build": "tsup",
25
+ "dev": "tsup --watch",
26
+ "typecheck": "tsc --noEmit",
27
+ "prepublishOnly": "pnpm build",
28
+ "release": "release-it"
29
+ },
18
30
  "keywords": [
19
31
  "tchao",
20
32
  "chat",
21
33
  "widget",
22
34
  "sdk",
23
35
  "customer-support",
24
- "live-chat"
36
+ "live-chat",
37
+ "react"
25
38
  ],
26
39
  "author": "Tchao",
27
40
  "license": "MIT",
41
+ "peerDependencies": {
42
+ "react": ">=17.0.0"
43
+ },
44
+ "peerDependenciesMeta": {
45
+ "react": {
46
+ "optional": true
47
+ }
48
+ },
28
49
  "devDependencies": {
50
+ "@release-it/conventional-changelog": "^10.0.1",
51
+ "@types/react": "^19.1.8",
52
+ "react": "^19.1.0",
53
+ "release-it": "^19.0.4",
29
54
  "tsup": "^8.5.0",
30
55
  "typescript": "^5.9.3"
31
56
  },
32
57
  "repository": {
33
58
  "type": "git",
34
59
  "url": "https://github.com/tchao-app/tchao"
35
- },
36
- "scripts": {
37
- "build": "tsup",
38
- "dev": "tsup --watch",
39
- "typecheck": "tsc --noEmit",
40
- "release:patch": "npm version patch && pnpm publish --access public",
41
- "release:minor": "npm version minor && pnpm publish --access public",
42
- "release:major": "npm version major && pnpm publish --access public"
43
60
  }
44
- }
61
+ }
package/LICENSE.TXT DELETED
@@ -1,20 +0,0 @@
1
- Licence Agreement for Now.ts, Version 1.1
2
-
3
- This Licence Agreement ("Agreement") is made between Codelynx, LLC, the copyright holder ("Licensor") and the user ("Licensee") of the Now.ts software ("Software"), version 1.1.
4
-
5
- Grant of Licence: Licensor hereby grants Licensee a non-exclusive, non-transferable, perpetual licence to use the Software for the purpose of developing commercial applications. Licensee is permitted to use the Software in the creation of applications that the Licensee may commercialize.
6
-
7
- Restrictions: Licensee is expressly prohibited from modifying, distributing, sublicensing, or making available the Software to any third party. The Licensee shall not use the Software for any other purpose than as explicitly provided in this Agreement without the prior written consent of Licensor.
8
-
9
- Ownership: The Software and all intellectual property rights therein are and shall remain the property of Licensor. The Licensee does not acquire any ownership rights to the Software under this Agreement.
10
-
11
- No Warranty: The Software is provided "as is," without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and non-infringement. In no event shall the Licensor be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the Software.
12
-
13
- Limitation of Liability: Licensor shall not be liable for any direct, indirect, incidental, special, consequential or exemplary damages, including but not limited to, damages for loss of profits, goodwill, use, data or other intangible losses (even if Licensor has been advised of the possibility of such damages), resulting from the Licensee's use of the Software.
14
-
15
- Jurisdiction: This Agreement shall be governed by and construed in accordance with the laws of the United States of America, without giving effect to any principles of conflicts of law.
16
-
17
- By using the Software, Licensee agrees to be bound by the terms of this Agreement. If Licensee does not agree to the terms of this Agreement, they must not use the Software.
18
-
19
- Melvyn Malherbe, Codelynx LLC
20
- 3 February 2024