tchao 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -19
- package/dist/npm.d.mts +11 -0
- package/dist/npm.d.ts +11 -0
- package/dist/npm.js +1 -1
- package/dist/npm.js.map +1 -1
- package/dist/npm.mjs +1 -1
- package/dist/npm.mjs.map +1 -1
- package/dist/react.d.mts +44 -8
- package/dist/react.d.ts +44 -8
- package/dist/react.js +1 -1
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +1 -1
- package/dist/react.mjs.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -87,17 +87,17 @@ tchao.open();
|
|
|
87
87
|
import { useTchao } from "tchao/react";
|
|
88
88
|
|
|
89
89
|
const {
|
|
90
|
-
isReady,
|
|
90
|
+
isReady, // boolean - widget is initialized
|
|
91
91
|
isLoading, // boolean - widget is loading
|
|
92
|
-
error,
|
|
93
|
-
show,
|
|
94
|
-
hide,
|
|
95
|
-
toggle,
|
|
96
|
-
open,
|
|
97
|
-
identify,
|
|
98
|
-
config,
|
|
99
|
-
on,
|
|
100
|
-
off,
|
|
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
101
|
} = useTchao({ websiteId: "..." });
|
|
102
102
|
```
|
|
103
103
|
|
|
@@ -144,11 +144,11 @@ tchao.isReady(); // boolean
|
|
|
144
144
|
```typescript
|
|
145
145
|
tchao.init({
|
|
146
146
|
websiteId: "required",
|
|
147
|
-
host: "https://tchao.app",
|
|
148
|
-
position: "bottom-right",
|
|
147
|
+
host: "https://tchao.app", // optional, for self-hosted
|
|
148
|
+
position: "bottom-right", // "bottom-right" | "bottom-left"
|
|
149
149
|
primaryColor: "#6366f1",
|
|
150
|
-
themeMode: "system",
|
|
151
|
-
widgetStyle: "bubble",
|
|
150
|
+
themeMode: "system", // "light" | "dark" | "system"
|
|
151
|
+
widgetStyle: "bubble", // "bubble" | "name_line" | "question_cta"
|
|
152
152
|
agentName: "Support",
|
|
153
153
|
agentRole: "Customer Support",
|
|
154
154
|
agentImage: "https://...",
|
|
@@ -159,12 +159,12 @@ tchao.init({
|
|
|
159
159
|
|
|
160
160
|
### Events
|
|
161
161
|
|
|
162
|
-
| Event
|
|
163
|
-
|
|
162
|
+
| Event | Callback | Description |
|
|
163
|
+
| --------- | ---------------------------- | -------------------- |
|
|
164
164
|
| `message` | `(message: Message) => void` | New message received |
|
|
165
|
-
| `open`
|
|
166
|
-
| `close`
|
|
167
|
-
| `ready`
|
|
165
|
+
| `open` | `() => void` | Chat window opened |
|
|
166
|
+
| `close` | `() => void` | Chat window closed |
|
|
167
|
+
| `ready` | `() => void` | Widget initialized |
|
|
168
168
|
|
|
169
169
|
### TypeScript
|
|
170
170
|
|
package/dist/npm.d.mts
CHANGED
|
@@ -31,6 +31,9 @@ type TchaoConfig = {
|
|
|
31
31
|
agentWelcomeMessage?: string;
|
|
32
32
|
hidePoweredBy?: boolean;
|
|
33
33
|
bubbleIcon?: string;
|
|
34
|
+
debug?: boolean;
|
|
35
|
+
/** When true, disables identify/setMetadata to prevent data pollution during impersonation */
|
|
36
|
+
impersonate?: boolean;
|
|
34
37
|
};
|
|
35
38
|
type Message = {
|
|
36
39
|
content: string;
|
|
@@ -50,6 +53,7 @@ type TchaoInstance = {
|
|
|
50
53
|
toggle: () => void;
|
|
51
54
|
open: (message?: string) => void;
|
|
52
55
|
identify: (info: VisitorInfo) => void;
|
|
56
|
+
setMetadata: (metadata: Record<string, unknown>) => void;
|
|
53
57
|
config: () => Partial<WidgetConfig>;
|
|
54
58
|
on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;
|
|
55
59
|
off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;
|
|
@@ -62,6 +66,7 @@ type InternalTchaoInstance = {
|
|
|
62
66
|
toggle: () => void;
|
|
63
67
|
open: (message?: string) => void;
|
|
64
68
|
identify: (info: VisitorInfo) => void;
|
|
69
|
+
setMetadata: (metadata: Record<string, unknown>) => void;
|
|
65
70
|
config: () => Partial<WidgetConfig>;
|
|
66
71
|
on: (event: string, callback: (...args: unknown[]) => void) => void;
|
|
67
72
|
off: (event: string, callback: (...args: unknown[]) => void) => void;
|
|
@@ -100,8 +105,14 @@ declare const tchao: {
|
|
|
100
105
|
open: (message?: string) => void;
|
|
101
106
|
/**
|
|
102
107
|
* Identify the visitor. Safe to call before init.
|
|
108
|
+
* Disabled when impersonate mode is enabled.
|
|
103
109
|
*/
|
|
104
110
|
identify: (info: VisitorInfo) => void;
|
|
111
|
+
/**
|
|
112
|
+
* Set custom metadata for the visitor. Safe to call before init.
|
|
113
|
+
* Disabled when impersonate mode is enabled.
|
|
114
|
+
*/
|
|
115
|
+
setMetadata: (metadata: Record<string, unknown>) => void;
|
|
105
116
|
/**
|
|
106
117
|
* Get the current widget configuration.
|
|
107
118
|
*/
|
package/dist/npm.d.ts
CHANGED
|
@@ -31,6 +31,9 @@ type TchaoConfig = {
|
|
|
31
31
|
agentWelcomeMessage?: string;
|
|
32
32
|
hidePoweredBy?: boolean;
|
|
33
33
|
bubbleIcon?: string;
|
|
34
|
+
debug?: boolean;
|
|
35
|
+
/** When true, disables identify/setMetadata to prevent data pollution during impersonation */
|
|
36
|
+
impersonate?: boolean;
|
|
34
37
|
};
|
|
35
38
|
type Message = {
|
|
36
39
|
content: string;
|
|
@@ -50,6 +53,7 @@ type TchaoInstance = {
|
|
|
50
53
|
toggle: () => void;
|
|
51
54
|
open: (message?: string) => void;
|
|
52
55
|
identify: (info: VisitorInfo) => void;
|
|
56
|
+
setMetadata: (metadata: Record<string, unknown>) => void;
|
|
53
57
|
config: () => Partial<WidgetConfig>;
|
|
54
58
|
on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;
|
|
55
59
|
off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;
|
|
@@ -62,6 +66,7 @@ type InternalTchaoInstance = {
|
|
|
62
66
|
toggle: () => void;
|
|
63
67
|
open: (message?: string) => void;
|
|
64
68
|
identify: (info: VisitorInfo) => void;
|
|
69
|
+
setMetadata: (metadata: Record<string, unknown>) => void;
|
|
65
70
|
config: () => Partial<WidgetConfig>;
|
|
66
71
|
on: (event: string, callback: (...args: unknown[]) => void) => void;
|
|
67
72
|
off: (event: string, callback: (...args: unknown[]) => void) => void;
|
|
@@ -100,8 +105,14 @@ declare const tchao: {
|
|
|
100
105
|
open: (message?: string) => void;
|
|
101
106
|
/**
|
|
102
107
|
* Identify the visitor. Safe to call before init.
|
|
108
|
+
* Disabled when impersonate mode is enabled.
|
|
103
109
|
*/
|
|
104
110
|
identify: (info: VisitorInfo) => void;
|
|
111
|
+
/**
|
|
112
|
+
* Set custom metadata for the visitor. Safe to call before init.
|
|
113
|
+
* Disabled when impersonate mode is enabled.
|
|
114
|
+
*/
|
|
115
|
+
setMetadata: (metadata: Record<string, unknown>) => void;
|
|
105
116
|
/**
|
|
106
117
|
* Get the current widget configuration.
|
|
107
118
|
*/
|
package/dist/npm.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var u=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var v=Object.getOwnPropertyNames;var m=Object.prototype.hasOwnProperty;var E=(e,o)=>{for(var a in o)u(e,a,{get:o[a],enumerable:!0})},k=(e,o,a,c)=>{if(o&&typeof o=="object"||typeof o=="function")for(let n of v(o))!m.call(e,n)&&n!==a&&u(e,n,{get:()=>o[n],enumerable:!(c=y(o,n))||c.enumerable});return e};var I=e=>k(u({},"__esModule",{value:!0}),e);var W={};E(W,{Tchao:()=>b,default:()=>S,init:()=>p,tchao:()=>R});module.exports=I(W);var s=!1;function T(e){s=e}function w(e,o){return`[tchao.app] [${new Date().toISOString().split("T")[1].slice(0,-1)}] [${e.toUpperCase()}] ${o}`}var t={debug:(e,...o)=>{s&&console.log(w("debug",e),...o)},info:(e,...o)=>{s&&console.info(w("info",e),...o)},warn:(e,...o)=>{s&&console.warn(w("warn",e),...o)},error:(e,...o)=>{console.error(w("error",e),...o)},group:e=>{s&&console.group(`[tchao.app] ${e}`)},groupEnd:()=>{s&&console.groupEnd()},table:e=>{s&&console.table(e)}};var M="https://tchao.app/widget.js",h=!1,l=null,g=!1,r=null,f=!1,i=[];function x(){for(;i.length>0;){let e=i.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"setMetadata":window.Tchao.setMetadata(e.metadata);break;case"on":window.Tchao.on(e.event,e.callback);break;case"off":window.Tchao.off(e.event,e.callback);break}}catch{}}}async function C(e){return l||(l=new Promise((o,a)=>{if(h&&window.Tchao){o();return}if(document.querySelector("script[data-tchao-widget]")){h=!0,o();return}window.__TCHAO_CONFIG__=e;let n=document.createElement("script");n.src=e.host?`${e.host}/widget.js`:M,n.async=!0,n.dataset.websiteId=e.websiteId,n.dataset.tchaoWidget="true",n.onload=()=>{h=!0,o()},n.onerror=()=>{a(new Error("Failed to load Tchao widget script"))},document.head.appendChild(n)}),l)}async function _(){return new Promise((e,o)=>{let a=0,c=()=>{window.Tchao?e():a>=50?o(new Error("Tchao widget failed to initialize")):(a++,setTimeout(c,100))};c()})}async function p(e){if(e.debug&&(T(!0),t.debug("Debug mode enabled")),e.impersonate&&(f=!0,t.debug("Impersonate mode enabled - identify/setMetadata will be disabled")),t.debug("init() called",{websiteId:e.websiteId,host:e.host}),!e.websiteId)throw new Error("websiteId is required");if(g&&window.Tchao&&r)return t.debug("Already initialized, returning existing instance"),r;if(t.debug("Loading widget script..."),await C(e),t.debug("Widget script loaded, waiting for Tchao..."),await _(),t.debug("Tchao ready"),!window.Tchao)throw new Error("Tchao widget failed to initialize");return g=!0,r=P(),t.debug("Flushing queued calls...",{queueLength:i.length}),x(),t.debug("Init complete"),r}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{}},setMetadata:e=>{try{window.Tchao?.setMetadata(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:()=>g&&!!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,l=null,g=!1,r=null,i.length=0,delete window.__TCHAO_CONFIG__,delete window.Tchao}catch{}}}}function d(e,o){try{return e()}catch{return o}}var R={init:p,show:()=>{window.Tchao?d(()=>window.Tchao?.show(),void 0):i.push({type:"show"})},hide:()=>{window.Tchao?d(()=>window.Tchao?.hide(),void 0):i.push({type:"hide"})},toggle:()=>{window.Tchao?d(()=>window.Tchao?.toggle(),void 0):i.push({type:"toggle"})},open:e=>{window.Tchao?d(()=>window.Tchao?.open(e),void 0):i.push({type:"open",message:e})},identify:e=>{if(f){t.debug("identify() blocked - impersonate mode is enabled");return}t.debug("identify() called",e),t.debug("window.Tchao exists:",!!window.Tchao),window.Tchao?(t.debug("calling window.Tchao.identify()"),d(()=>window.Tchao?.identify(e),void 0)):(t.debug("window.Tchao not ready, queuing call"),i.push({type:"identify",info:e}))},setMetadata:e=>{if(f){t.debug("setMetadata() blocked - impersonate mode is enabled");return}t.debug("setMetadata() called",e),window.Tchao?d(()=>window.Tchao?.setMetadata(e),void 0):i.push({type:"setMetadata",metadata:e})},config:()=>d(()=>window.Tchao?.config()??{},{}),on:(e,o)=>{window.Tchao?d(()=>window.Tchao?.on(e,o),void 0):i.push({type:"on",event:e,callback:o})},off:(e,o)=>{window.Tchao?d(()=>window.Tchao?.off(e,o),void 0):i.push({type:"off",event:e,callback:o})},destroy:()=>{r&&r.destroy()},isReady:()=>g&&!!window.Tchao,getInstance:()=>r},b={init:p};var S=b;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 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"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/widget/npm.ts","../../../src/widget-preact/logger.ts"],"sourcesContent":["import { logger, setDebugEnabled } from \"../widget-preact/logger\";\n\nexport 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 debug?: boolean;\n /** When true, disables identify/setMetadata to prevent data pollution during impersonation */\n impersonate?: boolean;\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 setMetadata: (metadata: Record<string, unknown>) => 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 setMetadata: (metadata: Record<string, unknown>) => 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;\nlet impersonateMode = false;\n\ntype QueuedCall =\n | { type: \"show\" }\n | { type: \"hide\" }\n | { type: \"toggle\" }\n | { type: \"open\"; message?: string }\n | { type: \"identify\"; info: VisitorInfo }\n | { type: \"setMetadata\"; metadata: Record<string, unknown> }\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 \"setMetadata\":\n window.Tchao.setMetadata(call.metadata);\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.debug) {\n setDebugEnabled(true);\n logger.debug(\"Debug mode enabled\");\n }\n\n if (config.impersonate) {\n impersonateMode = true;\n logger.debug(\"Impersonate mode enabled - identify/setMetadata will be disabled\");\n }\n\n logger.debug(\"init() called\", { websiteId: config.websiteId, host: config.host });\n\n if (!config.websiteId) {\n throw new Error(\"websiteId is required\");\n }\n\n if (initialized && window.Tchao && currentInstance) {\n logger.debug(\"Already initialized, returning existing instance\");\n return currentInstance;\n }\n\n logger.debug(\"Loading widget script...\");\n await loadScript(config);\n logger.debug(\"Widget script loaded, waiting for Tchao...\");\n await waitForTchao();\n logger.debug(\"Tchao ready\");\n\n if (!window.Tchao) {\n throw new Error(\"Tchao widget failed to initialize\");\n }\n\n initialized = true;\n currentInstance = createInstance();\n logger.debug(\"Flushing queued calls...\", { queueLength: callQueue.length });\n flushQueue();\n logger.debug(\"Init complete\");\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 setMetadata: (metadata: Record<string, unknown>) => {\n try {\n window.Tchao?.setMetadata(metadata);\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 * Disabled when impersonate mode is enabled.\n */\n identify: (info: VisitorInfo): void => {\n if (impersonateMode) {\n logger.debug(\"identify() blocked - impersonate mode is enabled\");\n return;\n }\n logger.debug(\"identify() called\", info);\n logger.debug(\"window.Tchao exists:\", !!window.Tchao);\n if (window.Tchao) {\n logger.debug(\"calling window.Tchao.identify()\");\n safeCall(() => window.Tchao?.identify(info), undefined);\n } else {\n logger.debug(\"window.Tchao not ready, queuing call\");\n callQueue.push({ type: \"identify\", info });\n }\n },\n\n /**\n * Set custom metadata for the visitor. Safe to call before init.\n * Disabled when impersonate mode is enabled.\n */\n setMetadata: (metadata: Record<string, unknown>): void => {\n if (impersonateMode) {\n logger.debug(\"setMetadata() blocked - impersonate mode is enabled\");\n return;\n }\n logger.debug(\"setMetadata() called\", metadata);\n if (window.Tchao) {\n safeCall(() => window.Tchao?.setMetadata(metadata), undefined);\n } else {\n callQueue.push({ type: \"setMetadata\", metadata });\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","/* eslint-disable no-console */\ntype LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nlet debugEnabled = false;\n\nexport function setDebugEnabled(enabled: boolean): void {\n debugEnabled = enabled;\n}\n\nexport function isDebugEnabled(): boolean {\n return debugEnabled;\n}\n\nfunction formatMessage(level: LogLevel, message: string): string {\n const timestamp = new Date().toISOString().split(\"T\")[1].slice(0, -1);\n return `[tchao.app] [${timestamp}] [${level.toUpperCase()}] ${message}`;\n}\n\nexport const logger = {\n debug: (message: string, ...args: unknown[]): void => {\n if (!debugEnabled) return;\n console.log(formatMessage(\"debug\", message), ...args);\n },\n\n info: (message: string, ...args: unknown[]): void => {\n if (!debugEnabled) return;\n console.info(formatMessage(\"info\", message), ...args);\n },\n\n warn: (message: string, ...args: unknown[]): void => {\n if (!debugEnabled) return;\n console.warn(formatMessage(\"warn\", message), ...args);\n },\n\n error: (message: string, ...args: unknown[]): void => {\n // Always show errors\n console.error(formatMessage(\"error\", message), ...args);\n },\n\n group: (label: string): void => {\n if (!debugEnabled) return;\n console.group(`[tchao.app] ${label}`);\n },\n\n groupEnd: (): void => {\n if (!debugEnabled) return;\n console.groupEnd();\n },\n\n table: (data: unknown): void => {\n if (!debugEnabled) return;\n console.table(data);\n },\n};\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,WAAAE,EAAA,YAAAC,EAAA,SAAAC,EAAA,UAAAC,IAAA,eAAAC,EAAAN,GCGA,IAAIO,EAAe,GAEZ,SAASC,EAAgBC,EAAwB,CACtDF,EAAeE,CACjB,CAMA,SAASC,EAAcC,EAAiBC,EAAyB,CAE/D,MAAO,gBADW,IAAI,KAAK,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE,MAAM,EAAG,EAAE,CACpC,MAAMD,EAAM,YAAY,CAAC,KAAKC,CAAO,EACvE,CAEO,IAAMC,EAAS,CACpB,MAAO,CAACD,KAAoBE,IAA0B,CAC/CC,GACL,QAAQ,IAAIL,EAAc,QAASE,CAAO,EAAG,GAAGE,CAAI,CACtD,EAEA,KAAM,CAACF,KAAoBE,IAA0B,CAC9CC,GACL,QAAQ,KAAKL,EAAc,OAAQE,CAAO,EAAG,GAAGE,CAAI,CACtD,EAEA,KAAM,CAACF,KAAoBE,IAA0B,CAC9CC,GACL,QAAQ,KAAKL,EAAc,OAAQE,CAAO,EAAG,GAAGE,CAAI,CACtD,EAEA,MAAO,CAACF,KAAoBE,IAA0B,CAEpD,QAAQ,MAAMJ,EAAc,QAASE,CAAO,EAAG,GAAGE,CAAI,CACxD,EAEA,MAAQE,GAAwB,CACzBD,GACL,QAAQ,MAAM,eAAeC,CAAK,EAAE,CACtC,EAEA,SAAU,IAAY,CACfD,GACL,QAAQ,SAAS,CACnB,EAEA,MAAQE,GAAwB,CACzBF,GACL,QAAQ,MAAME,CAAI,CACpB,CACF,EDqCA,IAAMC,EAAoB,8BAEtBC,EAAe,GACfC,EAAsC,KACtCC,EAAc,GACdC,EAAwC,KACxCC,EAAkB,GAYhBC,EAA0B,CAAC,EAEjC,SAASC,GAAmB,CAC1B,KAAOD,EAAU,OAAS,GAAG,CAC3B,IAAME,EAAOF,EAAU,MAAM,EAC7B,GAAI,GAACE,GAAQ,CAAC,OAAO,OAErB,GAAI,CACF,OAAQA,EAAK,KAAM,CACjB,IAAK,OACH,OAAO,MAAM,KAAK,EAClB,MACF,IAAK,OACH,OAAO,MAAM,KAAK,EAClB,MACF,IAAK,SACH,OAAO,MAAM,OAAO,EACpB,MACF,IAAK,OACH,OAAO,MAAM,KAAKA,EAAK,OAAO,EAC9B,MACF,IAAK,WACH,OAAO,MAAM,SAASA,EAAK,IAAI,EAC/B,MACF,IAAK,cACH,OAAO,MAAM,YAAYA,EAAK,QAAQ,EACtC,MACF,IAAK,KACH,OAAO,MAAM,GAAGA,EAAK,MAAOA,EAAK,QAAQ,EACzC,MACF,IAAK,MACH,OAAO,MAAM,IAAIA,EAAK,MAAOA,EAAK,QAAQ,EAC1C,KACJ,CACF,MAAQ,CAER,CACF,CACF,CAEA,eAAeC,EAAWC,EAAoC,CAC5D,OAAIR,IAEJA,EAAgB,IAAI,QAAQ,CAACS,EAASC,IAAW,CAC/C,GAAIX,GAAgB,OAAO,MAAO,CAChCU,EAAQ,EACR,MACF,CAMA,GAJuB,SAAS,cAC9B,2BACF,EAEoB,CAClBV,EAAe,GACfU,EAAQ,EACR,MACF,CAEA,OAAO,iBAAmBD,EAE1B,IAAMG,EAAS,SAAS,cAAc,QAAQ,EAC9CA,EAAO,IAAMH,EAAO,KAAO,GAAGA,EAAO,IAAI,aAAeV,EACxDa,EAAO,MAAQ,GACfA,EAAO,QAAQ,UAAYH,EAAO,UAClCG,EAAO,QAAQ,YAAc,OAE7BA,EAAO,OAAS,IAAM,CACpBZ,EAAe,GACfU,EAAQ,CACV,EAEAE,EAAO,QAAU,IAAM,CACrBD,EAAO,IAAI,MAAM,oCAAoC,CAAC,CACxD,EAEA,SAAS,KAAK,YAAYC,CAAM,CAClC,CAAC,EAEMX,EACT,CAEA,eAAeY,GAA8B,CAC3C,OAAO,IAAI,QAAQ,CAACH,EAASC,IAAW,CACtC,IAAIG,EAAW,EACTC,EAAQ,IAAM,CACd,OAAO,MACTL,EAAQ,EACCI,GAAY,GACrBH,EAAO,IAAI,MAAM,mCAAmC,CAAC,GAErDG,IACA,WAAWC,EAAO,GAAG,EAEzB,EACAA,EAAM,CACR,CAAC,CACH,CAEA,eAAeC,EAAKP,EAA6C,CAa/D,GAZIA,EAAO,QACTQ,EAAgB,EAAI,EACpBC,EAAO,MAAM,oBAAoB,GAG/BT,EAAO,cACTL,EAAkB,GAClBc,EAAO,MAAM,kEAAkE,GAGjFA,EAAO,MAAM,gBAAiB,CAAE,UAAWT,EAAO,UAAW,KAAMA,EAAO,IAAK,CAAC,EAE5E,CAACA,EAAO,UACV,MAAM,IAAI,MAAM,uBAAuB,EAGzC,GAAIP,GAAe,OAAO,OAASC,EACjC,OAAAe,EAAO,MAAM,kDAAkD,EACxDf,EAST,GANAe,EAAO,MAAM,0BAA0B,EACvC,MAAMV,EAAWC,CAAM,EACvBS,EAAO,MAAM,4CAA4C,EACzD,MAAML,EAAa,EACnBK,EAAO,MAAM,aAAa,EAEtB,CAAC,OAAO,MACV,MAAM,IAAI,MAAM,mCAAmC,EAGrD,OAAAhB,EAAc,GACdC,EAAkBgB,EAAe,EACjCD,EAAO,MAAM,2BAA4B,CAAE,YAAab,EAAU,MAAO,CAAC,EAC1EC,EAAW,EACXY,EAAO,MAAM,eAAe,EACrBf,CACT,CAEA,SAASgB,GAAgC,CACvC,MAAO,CACL,KAAM,IAAM,CACV,GAAI,CACF,OAAO,OAAO,KAAK,CACrB,MAAQ,CAER,CACF,EACA,KAAM,IAAM,CACV,GAAI,CACF,OAAO,OAAO,KAAK,CACrB,MAAQ,CAER,CACF,EACA,OAAQ,IAAM,CACZ,GAAI,CACF,OAAO,OAAO,OAAO,CACvB,MAAQ,CAER,CACF,EACA,KAAOC,GAAqB,CAC1B,GAAI,CACF,OAAO,OAAO,KAAKA,CAAO,CAC5B,MAAQ,CAER,CACF,EACA,SAAWC,GAAsB,CAC/B,GAAI,CACF,OAAO,OAAO,SAASA,CAAI,CAC7B,MAAQ,CAER,CACF,EACA,YAAcC,GAAsC,CAClD,GAAI,CACF,OAAO,OAAO,YAAYA,CAAQ,CACpC,MAAQ,CAER,CACF,EACA,OAAQ,IAAM,CACZ,GAAI,CACF,OAAO,OAAO,OAAO,OAAO,GAAK,CAAC,CACpC,MAAQ,CACN,MAAO,CAAC,CACV,CACF,EACA,GAAI,CAAuBC,EAAUC,IAA+B,CAClE,GAAI,CACF,OAAO,OAAO,GAAGD,EAAOC,CAAwC,CAClE,MAAQ,CAER,CACF,EACA,IAAK,CAAuBD,EAAUC,IAA+B,CACnE,GAAI,CACF,OAAO,OAAO,IAAID,EAAOC,CAAwC,CACnE,MAAQ,CAER,CACF,EACA,QAAS,IAAMtB,GAAe,CAAC,CAAC,OAAO,MACvC,QAAS,IAAM,CACb,GAAI,CACF,IAAMU,EAAS,SAAS,cAAc,2BAA2B,EAC7DA,GAAQA,EAAO,OAAO,EAC1B,IAAMa,EAAS,SAAS,eAAe,mBAAmB,EACtDA,GAAQA,EAAO,OAAO,EAC1BzB,EAAe,GACfC,EAAgB,KAChBC,EAAc,GACdC,EAAkB,KAClBE,EAAU,OAAS,EACnB,OAAO,OAAO,iBACd,OAAO,OAAO,KAChB,MAAQ,CAER,CACF,CACF,CACF,CAEA,SAASqB,EAAYC,EAAaC,EAAgB,CAChD,GAAI,CACF,OAAOD,EAAG,CACZ,MAAQ,CACN,OAAOC,CACT,CACF,CAMO,IAAMC,EAAQ,CAInB,KAAAb,EAKA,KAAM,IAAY,CACZ,OAAO,MACTU,EAAS,IAAM,OAAO,OAAO,KAAK,EAAG,MAAS,EAE9CrB,EAAU,KAAK,CAAE,KAAM,MAAO,CAAC,CAEnC,EAKA,KAAM,IAAY,CACZ,OAAO,MACTqB,EAAS,IAAM,OAAO,OAAO,KAAK,EAAG,MAAS,EAE9CrB,EAAU,KAAK,CAAE,KAAM,MAAO,CAAC,CAEnC,EAKA,OAAQ,IAAY,CACd,OAAO,MACTqB,EAAS,IAAM,OAAO,OAAO,OAAO,EAAG,MAAS,EAEhDrB,EAAU,KAAK,CAAE,KAAM,QAAS,CAAC,CAErC,EAKA,KAAOe,GAA2B,CAC5B,OAAO,MACTM,EAAS,IAAM,OAAO,OAAO,KAAKN,CAAO,EAAG,MAAS,EAErDf,EAAU,KAAK,CAAE,KAAM,OAAQ,QAAAe,CAAQ,CAAC,CAE5C,EAMA,SAAWC,GAA4B,CACrC,GAAIjB,EAAiB,CACnBc,EAAO,MAAM,kDAAkD,EAC/D,MACF,CACAA,EAAO,MAAM,oBAAqBG,CAAI,EACtCH,EAAO,MAAM,uBAAwB,CAAC,CAAC,OAAO,KAAK,EAC/C,OAAO,OACTA,EAAO,MAAM,iCAAiC,EAC9CQ,EAAS,IAAM,OAAO,OAAO,SAASL,CAAI,EAAG,MAAS,IAEtDH,EAAO,MAAM,sCAAsC,EACnDb,EAAU,KAAK,CAAE,KAAM,WAAY,KAAAgB,CAAK,CAAC,EAE7C,EAMA,YAAcC,GAA4C,CACxD,GAAIlB,EAAiB,CACnBc,EAAO,MAAM,qDAAqD,EAClE,MACF,CACAA,EAAO,MAAM,uBAAwBI,CAAQ,EACzC,OAAO,MACTI,EAAS,IAAM,OAAO,OAAO,YAAYJ,CAAQ,EAAG,MAAS,EAE7DjB,EAAU,KAAK,CAAE,KAAM,cAAe,SAAAiB,CAAS,CAAC,CAEpD,EAKA,OAAQ,IACCI,EAAS,IAAM,OAAO,OAAO,OAAO,GAAK,CAAC,EAAG,CAAC,CAAC,EAMxD,GAAI,CAAuBH,EAAUC,IAAqC,CACpE,OAAO,MACTE,EACE,IAAM,OAAO,OAAO,GAAGH,EAAOC,CAAwC,EACtE,MACF,EAEAnB,EAAU,KAAK,CACb,KAAM,KACN,MAAAkB,EACA,SAAUC,CACZ,CAAC,CAEL,EAKA,IAAK,CAAuBD,EAAUC,IAAqC,CACrE,OAAO,MACTE,EACE,IACE,OAAO,OAAO,IAAIH,EAAOC,CAAwC,EACnE,MACF,EAEAnB,EAAU,KAAK,CACb,KAAM,MACN,MAAAkB,EACA,SAAUC,CACZ,CAAC,CAEL,EAKA,QAAS,IAAY,CACfrB,GACFA,EAAgB,QAAQ,CAE5B,EAKA,QAAS,IAAeD,GAAe,CAAC,CAAC,OAAO,MAKhD,YAAa,IAA4BC,CAC3C,EAEa2B,EAAQ,CACnB,KAAAd,CACF,EAGA,IAAOe,EAAQC","names":["npm_exports","__export","Tchao","npm_default","init","tchao","__toCommonJS","debugEnabled","setDebugEnabled","enabled","formatMessage","level","message","logger","args","debugEnabled","label","data","WIDGET_SCRIPT_URL","scriptLoaded","scriptPromise","initialized","currentInstance","impersonateMode","callQueue","flushQueue","call","loadScript","config","resolve","reject","script","waitForTchao","attempts","check","init","setDebugEnabled","logger","createInstance","message","info","metadata","event","callback","widget","safeCall","fn","fallback","tchao","Tchao","npm_default","Tchao"]}
|
package/dist/npm.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var
|
|
1
|
+
var r=!1;function f(e){r=e}function g(e,o){return`[tchao.app] [${new Date().toISOString().split("T")[1].slice(0,-1)}] [${e.toUpperCase()}] ${o}`}var t={debug:(e,...o)=>{r&&console.log(g("debug",e),...o)},info:(e,...o)=>{r&&console.info(g("info",e),...o)},warn:(e,...o)=>{r&&console.warn(g("warn",e),...o)},error:(e,...o)=>{console.error(g("error",e),...o)},group:e=>{r&&console.group(`[tchao.app] ${e}`)},groupEnd:()=>{r&&console.groupEnd()},table:e=>{r&&console.table(e)}};var T="https://tchao.app/widget.js",w=!1,c=null,l=!1,a=null,u=!1,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"setMetadata":window.Tchao.setMetadata(e.metadata);break;case"on":window.Tchao.on(e.event,e.callback);break;case"off":window.Tchao.off(e.event,e.callback);break}}catch{}}}async function y(e){return c||(c=new Promise((o,s)=>{if(w&&window.Tchao){o();return}if(document.querySelector("script[data-tchao-widget]")){w=!0,o();return}window.__TCHAO_CONFIG__=e;let d=document.createElement("script");d.src=e.host?`${e.host}/widget.js`:T,d.async=!0,d.dataset.websiteId=e.websiteId,d.dataset.tchaoWidget="true",d.onload=()=>{w=!0,o()},d.onerror=()=>{s(new Error("Failed to load Tchao widget script"))},document.head.appendChild(d)}),c)}async function v(){return new Promise((e,o)=>{let s=0,h=()=>{window.Tchao?e():s>=50?o(new Error("Tchao widget failed to initialize")):(s++,setTimeout(h,100))};h()})}async function p(e){if(e.debug&&(f(!0),t.debug("Debug mode enabled")),e.impersonate&&(u=!0,t.debug("Impersonate mode enabled - identify/setMetadata will be disabled")),t.debug("init() called",{websiteId:e.websiteId,host:e.host}),!e.websiteId)throw new Error("websiteId is required");if(l&&window.Tchao&&a)return t.debug("Already initialized, returning existing instance"),a;if(t.debug("Loading widget script..."),await y(e),t.debug("Widget script loaded, waiting for Tchao..."),await v(),t.debug("Tchao ready"),!window.Tchao)throw new Error("Tchao widget failed to initialize");return l=!0,a=m(),t.debug("Flushing queued calls...",{queueLength:n.length}),b(),t.debug("Init complete"),a}function m(){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{}},setMetadata:e=>{try{window.Tchao?.setMetadata(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:()=>l&&!!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(),w=!1,c=null,l=!1,a=null,n.length=0,delete window.__TCHAO_CONFIG__,delete window.Tchao}catch{}}}}function i(e,o){try{return e()}catch{return o}}var M={init:p,show:()=>{window.Tchao?i(()=>window.Tchao?.show(),void 0):n.push({type:"show"})},hide:()=>{window.Tchao?i(()=>window.Tchao?.hide(),void 0):n.push({type:"hide"})},toggle:()=>{window.Tchao?i(()=>window.Tchao?.toggle(),void 0):n.push({type:"toggle"})},open:e=>{window.Tchao?i(()=>window.Tchao?.open(e),void 0):n.push({type:"open",message:e})},identify:e=>{if(u){t.debug("identify() blocked - impersonate mode is enabled");return}t.debug("identify() called",e),t.debug("window.Tchao exists:",!!window.Tchao),window.Tchao?(t.debug("calling window.Tchao.identify()"),i(()=>window.Tchao?.identify(e),void 0)):(t.debug("window.Tchao not ready, queuing call"),n.push({type:"identify",info:e}))},setMetadata:e=>{if(u){t.debug("setMetadata() blocked - impersonate mode is enabled");return}t.debug("setMetadata() called",e),window.Tchao?i(()=>window.Tchao?.setMetadata(e),void 0):n.push({type:"setMetadata",metadata:e})},config:()=>i(()=>window.Tchao?.config()??{},{}),on:(e,o)=>{window.Tchao?i(()=>window.Tchao?.on(e,o),void 0):n.push({type:"on",event:e,callback:o})},off:(e,o)=>{window.Tchao?i(()=>window.Tchao?.off(e,o),void 0):n.push({type:"off",event:e,callback:o})},destroy:()=>{a&&a.destroy()},isReady:()=>l&&!!window.Tchao,getInstance:()=>a},E={init:p};var x=E;export{E as Tchao,x as default,p as init,M 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 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":"AAmFA,IAAMA,EAAoB,8BAEtBC,EAAe,GACfC,EAAsC,KACtCC,EAAc,GACdC,EAAwC,KAWtCC,EAA0B,CAAC,EAEjC,SAASC,GAAmB,CAC1B,KAAOD,EAAU,OAAS,GAAG,CAC3B,IAAME,EAAOF,EAAU,MAAM,EAC7B,GAAI,GAACE,GAAQ,CAAC,OAAO,OAErB,GAAI,CACF,OAAQA,EAAK,KAAM,CACjB,IAAK,OACH,OAAO,MAAM,KAAK,EAClB,MACF,IAAK,OACH,OAAO,MAAM,KAAK,EAClB,MACF,IAAK,SACH,OAAO,MAAM,OAAO,EACpB,MACF,IAAK,OACH,OAAO,MAAM,KAAKA,EAAK,OAAO,EAC9B,MACF,IAAK,WACH,OAAO,MAAM,SAASA,EAAK,IAAI,EAC/B,MACF,IAAK,KACH,OAAO,MAAM,GAAGA,EAAK,MAAOA,EAAK,QAAQ,EACzC,MACF,IAAK,MACH,OAAO,MAAM,IAAIA,EAAK,MAAOA,EAAK,QAAQ,EAC1C,KACJ,CACF,MAAQ,CAER,CACF,CACF,CAEA,eAAeC,EAAWC,EAAoC,CAC5D,OAAIP,IAEJA,EAAgB,IAAI,QAAQ,CAACQ,EAASC,IAAW,CAC/C,GAAIV,GAAgB,OAAO,MAAO,CAChCS,EAAQ,EACR,MACF,CAMA,GAJuB,SAAS,cAC9B,2BACF,EAEoB,CAClBT,EAAe,GACfS,EAAQ,EACR,MACF,CAEA,OAAO,iBAAmBD,EAE1B,IAAMG,EAAS,SAAS,cAAc,QAAQ,EAC9CA,EAAO,IAAMH,EAAO,KAAO,GAAGA,EAAO,IAAI,aAAeT,EACxDY,EAAO,MAAQ,GACfA,EAAO,QAAQ,UAAYH,EAAO,UAClCG,EAAO,QAAQ,YAAc,OAE7BA,EAAO,OAAS,IAAM,CACpBX,EAAe,GACfS,EAAQ,CACV,EAEAE,EAAO,QAAU,IAAM,CACrBD,EAAO,IAAI,MAAM,oCAAoC,CAAC,CACxD,EAEA,SAAS,KAAK,YAAYC,CAAM,CAClC,CAAC,EAEMV,EACT,CAEA,eAAeW,GAA8B,CAC3C,OAAO,IAAI,QAAQ,CAACH,EAASC,IAAW,CACtC,IAAIG,EAAW,EACTC,EAAQ,IAAM,CACd,OAAO,MACTL,EAAQ,EACCI,GAAY,GACrBH,EAAO,IAAI,MAAM,mCAAmC,CAAC,GAErDG,IACA,WAAWC,EAAO,GAAG,EAEzB,EACAA,EAAM,CACR,CAAC,CACH,CAEA,eAAeC,EAAKP,EAA6C,CAC/D,GAAI,CAACA,EAAO,UACV,MAAM,IAAI,MAAM,uBAAuB,EAGzC,GAAIN,GAAe,OAAO,OAASC,EACjC,OAAOA,EAMT,GAHA,MAAMI,EAAWC,CAAM,EACvB,MAAMI,EAAa,EAEf,CAAC,OAAO,MACV,MAAM,IAAI,MAAM,mCAAmC,EAGrD,OAAAV,EAAc,GACdC,EAAkBa,EAAe,EACjCX,EAAW,EACJF,CACT,CAEA,SAASa,GAAgC,CACvC,MAAO,CACL,KAAM,IAAM,CACV,GAAI,CACF,OAAO,OAAO,KAAK,CACrB,MAAQ,CAER,CACF,EACA,KAAM,IAAM,CACV,GAAI,CACF,OAAO,OAAO,KAAK,CACrB,MAAQ,CAER,CACF,EACA,OAAQ,IAAM,CACZ,GAAI,CACF,OAAO,OAAO,OAAO,CACvB,MAAQ,CAER,CACF,EACA,KAAOC,GAAqB,CAC1B,GAAI,CACF,OAAO,OAAO,KAAKA,CAAO,CAC5B,MAAQ,CAER,CACF,EACA,SAAWC,GAAsB,CAC/B,GAAI,CACF,OAAO,OAAO,SAASA,CAAI,CAC7B,MAAQ,CAER,CACF,EACA,OAAQ,IAAM,CACZ,GAAI,CACF,OAAO,OAAO,OAAO,OAAO,GAAK,CAAC,CACpC,MAAQ,CACN,MAAO,CAAC,CACV,CACF,EACA,GAAI,CAAuBC,EAAUC,IAA+B,CAClE,GAAI,CACF,OAAO,OAAO,GAAGD,EAAOC,CAAwC,CAClE,MAAQ,CAER,CACF,EACA,IAAK,CAAuBD,EAAUC,IAA+B,CACnE,GAAI,CACF,OAAO,OAAO,IAAID,EAAOC,CAAwC,CACnE,MAAQ,CAER,CACF,EACA,QAAS,IAAMlB,GAAe,CAAC,CAAC,OAAO,MACvC,QAAS,IAAM,CACb,GAAI,CACF,IAAMS,EAAS,SAAS,cAAc,2BAA2B,EAC7DA,GAAQA,EAAO,OAAO,EAC1B,IAAMU,EAAS,SAAS,eAAe,mBAAmB,EACtDA,GAAQA,EAAO,OAAO,EAC1BrB,EAAe,GACfC,EAAgB,KAChBC,EAAc,GACdC,EAAkB,KAClBC,EAAU,OAAS,EACnB,OAAO,OAAO,iBACd,OAAO,OAAO,KAChB,MAAQ,CAER,CACF,CACF,CACF,CAEA,SAASkB,EAAYC,EAAaC,EAAgB,CAChD,GAAI,CACF,OAAOD,EAAG,CACZ,MAAQ,CACN,OAAOC,CACT,CACF,CAMO,IAAMC,EAAQ,CAInB,KAAAV,EAKA,KAAM,IAAY,CACZ,OAAO,MACTO,EAAS,IAAM,OAAO,OAAO,KAAK,EAAG,MAAS,EAE9ClB,EAAU,KAAK,CAAE,KAAM,MAAO,CAAC,CAEnC,EAKA,KAAM,IAAY,CACZ,OAAO,MACTkB,EAAS,IAAM,OAAO,OAAO,KAAK,EAAG,MAAS,EAE9ClB,EAAU,KAAK,CAAE,KAAM,MAAO,CAAC,CAEnC,EAKA,OAAQ,IAAY,CACd,OAAO,MACTkB,EAAS,IAAM,OAAO,OAAO,OAAO,EAAG,MAAS,EAEhDlB,EAAU,KAAK,CAAE,KAAM,QAAS,CAAC,CAErC,EAKA,KAAOa,GAA2B,CAC5B,OAAO,MACTK,EAAS,IAAM,OAAO,OAAO,KAAKL,CAAO,EAAG,MAAS,EAErDb,EAAU,KAAK,CAAE,KAAM,OAAQ,QAAAa,CAAQ,CAAC,CAE5C,EAKA,SAAWC,GAA4B,CACjC,OAAO,MACTI,EAAS,IAAM,OAAO,OAAO,SAASJ,CAAI,EAAG,MAAS,EAEtDd,EAAU,KAAK,CAAE,KAAM,WAAY,KAAAc,CAAK,CAAC,CAE7C,EAKA,OAAQ,IACCI,EAAS,IAAM,OAAO,OAAO,OAAO,GAAK,CAAC,EAAG,CAAC,CAAC,EAMxD,GAAI,CAAuBH,EAAUC,IAAqC,CACpE,OAAO,MACTE,EACE,IAAM,OAAO,OAAO,GAAGH,EAAOC,CAAwC,EACtE,MACF,EAEAhB,EAAU,KAAK,CACb,KAAM,KACN,MAAAe,EACA,SAAUC,CACZ,CAAC,CAEL,EAKA,IAAK,CAAuBD,EAAUC,IAAqC,CACrE,OAAO,MACTE,EACE,IACE,OAAO,OAAO,IAAIH,EAAOC,CAAwC,EACnE,MACF,EAEAhB,EAAU,KAAK,CACb,KAAM,MACN,MAAAe,EACA,SAAUC,CACZ,CAAC,CAEL,EAKA,QAAS,IAAY,CACfjB,GACFA,EAAgB,QAAQ,CAE5B,EAKA,QAAS,IAAeD,GAAe,CAAC,CAAC,OAAO,MAKhD,YAAa,IAA4BC,CAC3C,EAEauB,EAAQ,CACnB,KAAAX,CACF,EAGA,IAAOY,EAAQC","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"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/widget-preact/logger.ts","../../../src/widget/npm.ts"],"sourcesContent":["/* eslint-disable no-console */\ntype LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nlet debugEnabled = false;\n\nexport function setDebugEnabled(enabled: boolean): void {\n debugEnabled = enabled;\n}\n\nexport function isDebugEnabled(): boolean {\n return debugEnabled;\n}\n\nfunction formatMessage(level: LogLevel, message: string): string {\n const timestamp = new Date().toISOString().split(\"T\")[1].slice(0, -1);\n return `[tchao.app] [${timestamp}] [${level.toUpperCase()}] ${message}`;\n}\n\nexport const logger = {\n debug: (message: string, ...args: unknown[]): void => {\n if (!debugEnabled) return;\n console.log(formatMessage(\"debug\", message), ...args);\n },\n\n info: (message: string, ...args: unknown[]): void => {\n if (!debugEnabled) return;\n console.info(formatMessage(\"info\", message), ...args);\n },\n\n warn: (message: string, ...args: unknown[]): void => {\n if (!debugEnabled) return;\n console.warn(formatMessage(\"warn\", message), ...args);\n },\n\n error: (message: string, ...args: unknown[]): void => {\n // Always show errors\n console.error(formatMessage(\"error\", message), ...args);\n },\n\n group: (label: string): void => {\n if (!debugEnabled) return;\n console.group(`[tchao.app] ${label}`);\n },\n\n groupEnd: (): void => {\n if (!debugEnabled) return;\n console.groupEnd();\n },\n\n table: (data: unknown): void => {\n if (!debugEnabled) return;\n console.table(data);\n },\n};\n","import { logger, setDebugEnabled } from \"../widget-preact/logger\";\n\nexport 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 debug?: boolean;\n /** When true, disables identify/setMetadata to prevent data pollution during impersonation */\n impersonate?: boolean;\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 setMetadata: (metadata: Record<string, unknown>) => 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 setMetadata: (metadata: Record<string, unknown>) => 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;\nlet impersonateMode = false;\n\ntype QueuedCall =\n | { type: \"show\" }\n | { type: \"hide\" }\n | { type: \"toggle\" }\n | { type: \"open\"; message?: string }\n | { type: \"identify\"; info: VisitorInfo }\n | { type: \"setMetadata\"; metadata: Record<string, unknown> }\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 \"setMetadata\":\n window.Tchao.setMetadata(call.metadata);\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.debug) {\n setDebugEnabled(true);\n logger.debug(\"Debug mode enabled\");\n }\n\n if (config.impersonate) {\n impersonateMode = true;\n logger.debug(\"Impersonate mode enabled - identify/setMetadata will be disabled\");\n }\n\n logger.debug(\"init() called\", { websiteId: config.websiteId, host: config.host });\n\n if (!config.websiteId) {\n throw new Error(\"websiteId is required\");\n }\n\n if (initialized && window.Tchao && currentInstance) {\n logger.debug(\"Already initialized, returning existing instance\");\n return currentInstance;\n }\n\n logger.debug(\"Loading widget script...\");\n await loadScript(config);\n logger.debug(\"Widget script loaded, waiting for Tchao...\");\n await waitForTchao();\n logger.debug(\"Tchao ready\");\n\n if (!window.Tchao) {\n throw new Error(\"Tchao widget failed to initialize\");\n }\n\n initialized = true;\n currentInstance = createInstance();\n logger.debug(\"Flushing queued calls...\", { queueLength: callQueue.length });\n flushQueue();\n logger.debug(\"Init complete\");\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 setMetadata: (metadata: Record<string, unknown>) => {\n try {\n window.Tchao?.setMetadata(metadata);\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 * Disabled when impersonate mode is enabled.\n */\n identify: (info: VisitorInfo): void => {\n if (impersonateMode) {\n logger.debug(\"identify() blocked - impersonate mode is enabled\");\n return;\n }\n logger.debug(\"identify() called\", info);\n logger.debug(\"window.Tchao exists:\", !!window.Tchao);\n if (window.Tchao) {\n logger.debug(\"calling window.Tchao.identify()\");\n safeCall(() => window.Tchao?.identify(info), undefined);\n } else {\n logger.debug(\"window.Tchao not ready, queuing call\");\n callQueue.push({ type: \"identify\", info });\n }\n },\n\n /**\n * Set custom metadata for the visitor. Safe to call before init.\n * Disabled when impersonate mode is enabled.\n */\n setMetadata: (metadata: Record<string, unknown>): void => {\n if (impersonateMode) {\n logger.debug(\"setMetadata() blocked - impersonate mode is enabled\");\n return;\n }\n logger.debug(\"setMetadata() called\", metadata);\n if (window.Tchao) {\n safeCall(() => window.Tchao?.setMetadata(metadata), undefined);\n } else {\n callQueue.push({ type: \"setMetadata\", metadata });\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":["debugEnabled","setDebugEnabled","enabled","formatMessage","level","message","logger","args","debugEnabled","label","data","WIDGET_SCRIPT_URL","scriptLoaded","scriptPromise","initialized","currentInstance","impersonateMode","callQueue","flushQueue","call","loadScript","config","resolve","reject","script","waitForTchao","attempts","check","init","setDebugEnabled","logger","createInstance","message","info","metadata","event","callback","widget","safeCall","fn","fallback","tchao","Tchao","npm_default","Tchao"]}
|
package/dist/react.d.mts
CHANGED
|
@@ -19,6 +19,8 @@ type UseTchaoReturn = {
|
|
|
19
19
|
open: (message?: string) => void;
|
|
20
20
|
/** Identify the visitor */
|
|
21
21
|
identify: (info: VisitorInfo) => void;
|
|
22
|
+
/** Set custom metadata for the visitor */
|
|
23
|
+
setMetadata: (metadata: Record<string, unknown>) => void;
|
|
22
24
|
/** Get current widget configuration */
|
|
23
25
|
config: () => Partial<TchaoConfig>;
|
|
24
26
|
/** Subscribe to widget events */
|
|
@@ -47,22 +49,56 @@ type UseTchaoReturn = {
|
|
|
47
49
|
* ```
|
|
48
50
|
*/
|
|
49
51
|
declare function useTchao(options: UseTchaoOptions): UseTchaoReturn;
|
|
52
|
+
type TchaoProviderProps = TchaoConfig & {
|
|
53
|
+
/** Visitor's email address */
|
|
54
|
+
visitorEmail?: string;
|
|
55
|
+
/** Visitor's display name */
|
|
56
|
+
visitorName?: string;
|
|
57
|
+
/** Visitor's avatar URL */
|
|
58
|
+
visitorAvatar?: string;
|
|
59
|
+
/** Visitor's unique identifier (added to metadata) */
|
|
60
|
+
visitorId?: string;
|
|
61
|
+
/** Visitor's role (added to metadata) */
|
|
62
|
+
visitorRole?: string;
|
|
63
|
+
/** Visitor's phone number (added to metadata) */
|
|
64
|
+
visitorPhone?: string;
|
|
65
|
+
/** Visitor's company name (added to metadata) */
|
|
66
|
+
visitorCompany?: string;
|
|
67
|
+
/** Custom metadata to merge with visitor info */
|
|
68
|
+
visitorMetadata?: Record<string, unknown>;
|
|
69
|
+
/** Callback when widget is ready */
|
|
70
|
+
onReady?: () => void;
|
|
71
|
+
/** Callback when an error occurs */
|
|
72
|
+
onError?: (error: Error) => void;
|
|
73
|
+
};
|
|
50
74
|
/**
|
|
51
75
|
* Simple component that initializes Tchao and optionally identifies the user.
|
|
52
76
|
*
|
|
53
77
|
* @example
|
|
54
78
|
* ```tsx
|
|
55
|
-
* //
|
|
79
|
+
* // Basic usage
|
|
56
80
|
* <TchaoProvider
|
|
57
81
|
* websiteId="your-website-id"
|
|
58
|
-
*
|
|
82
|
+
* visitorEmail={user?.email}
|
|
83
|
+
* visitorName={user?.name}
|
|
84
|
+
* visitorAvatar={user?.image}
|
|
85
|
+
* />
|
|
86
|
+
*
|
|
87
|
+
* // With metadata
|
|
88
|
+
* <TchaoProvider
|
|
89
|
+
* websiteId="your-website-id"
|
|
90
|
+
* visitorEmail={user?.email}
|
|
91
|
+
* visitorName={user?.name}
|
|
92
|
+
* visitorId={user?.id}
|
|
93
|
+
* visitorRole={user?.role}
|
|
94
|
+
* visitorCompany={user?.company}
|
|
95
|
+
* visitorMetadata={{
|
|
96
|
+
* plan: user?.plan,
|
|
97
|
+
* impersonatedBy: admin?.email,
|
|
98
|
+
* }}
|
|
59
99
|
* />
|
|
60
100
|
* ```
|
|
61
101
|
*/
|
|
62
|
-
declare function TchaoProvider({
|
|
63
|
-
visitor?: VisitorInfo;
|
|
64
|
-
onReady?: () => void;
|
|
65
|
-
onError?: (error: Error) => void;
|
|
66
|
-
}): null;
|
|
102
|
+
declare function TchaoProvider({ visitorEmail, visitorName, visitorAvatar, visitorId, visitorRole, visitorPhone, visitorCompany, visitorMetadata, onReady, onError, ...config }: TchaoProviderProps): null;
|
|
67
103
|
|
|
68
|
-
export { TchaoConfig, TchaoEvent, TchaoEventMap, TchaoProvider, type UseTchaoOptions, type UseTchaoReturn, VisitorInfo, useTchao };
|
|
104
|
+
export { TchaoConfig, TchaoEvent, TchaoEventMap, TchaoProvider, type TchaoProviderProps, type UseTchaoOptions, type UseTchaoReturn, VisitorInfo, useTchao };
|
package/dist/react.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ type UseTchaoReturn = {
|
|
|
19
19
|
open: (message?: string) => void;
|
|
20
20
|
/** Identify the visitor */
|
|
21
21
|
identify: (info: VisitorInfo) => void;
|
|
22
|
+
/** Set custom metadata for the visitor */
|
|
23
|
+
setMetadata: (metadata: Record<string, unknown>) => void;
|
|
22
24
|
/** Get current widget configuration */
|
|
23
25
|
config: () => Partial<TchaoConfig>;
|
|
24
26
|
/** Subscribe to widget events */
|
|
@@ -47,22 +49,56 @@ type UseTchaoReturn = {
|
|
|
47
49
|
* ```
|
|
48
50
|
*/
|
|
49
51
|
declare function useTchao(options: UseTchaoOptions): UseTchaoReturn;
|
|
52
|
+
type TchaoProviderProps = TchaoConfig & {
|
|
53
|
+
/** Visitor's email address */
|
|
54
|
+
visitorEmail?: string;
|
|
55
|
+
/** Visitor's display name */
|
|
56
|
+
visitorName?: string;
|
|
57
|
+
/** Visitor's avatar URL */
|
|
58
|
+
visitorAvatar?: string;
|
|
59
|
+
/** Visitor's unique identifier (added to metadata) */
|
|
60
|
+
visitorId?: string;
|
|
61
|
+
/** Visitor's role (added to metadata) */
|
|
62
|
+
visitorRole?: string;
|
|
63
|
+
/** Visitor's phone number (added to metadata) */
|
|
64
|
+
visitorPhone?: string;
|
|
65
|
+
/** Visitor's company name (added to metadata) */
|
|
66
|
+
visitorCompany?: string;
|
|
67
|
+
/** Custom metadata to merge with visitor info */
|
|
68
|
+
visitorMetadata?: Record<string, unknown>;
|
|
69
|
+
/** Callback when widget is ready */
|
|
70
|
+
onReady?: () => void;
|
|
71
|
+
/** Callback when an error occurs */
|
|
72
|
+
onError?: (error: Error) => void;
|
|
73
|
+
};
|
|
50
74
|
/**
|
|
51
75
|
* Simple component that initializes Tchao and optionally identifies the user.
|
|
52
76
|
*
|
|
53
77
|
* @example
|
|
54
78
|
* ```tsx
|
|
55
|
-
* //
|
|
79
|
+
* // Basic usage
|
|
56
80
|
* <TchaoProvider
|
|
57
81
|
* websiteId="your-website-id"
|
|
58
|
-
*
|
|
82
|
+
* visitorEmail={user?.email}
|
|
83
|
+
* visitorName={user?.name}
|
|
84
|
+
* visitorAvatar={user?.image}
|
|
85
|
+
* />
|
|
86
|
+
*
|
|
87
|
+
* // With metadata
|
|
88
|
+
* <TchaoProvider
|
|
89
|
+
* websiteId="your-website-id"
|
|
90
|
+
* visitorEmail={user?.email}
|
|
91
|
+
* visitorName={user?.name}
|
|
92
|
+
* visitorId={user?.id}
|
|
93
|
+
* visitorRole={user?.role}
|
|
94
|
+
* visitorCompany={user?.company}
|
|
95
|
+
* visitorMetadata={{
|
|
96
|
+
* plan: user?.plan,
|
|
97
|
+
* impersonatedBy: admin?.email,
|
|
98
|
+
* }}
|
|
59
99
|
* />
|
|
60
100
|
* ```
|
|
61
101
|
*/
|
|
62
|
-
declare function TchaoProvider({
|
|
63
|
-
visitor?: VisitorInfo;
|
|
64
|
-
onReady?: () => void;
|
|
65
|
-
onError?: (error: Error) => void;
|
|
66
|
-
}): null;
|
|
102
|
+
declare function TchaoProvider({ visitorEmail, visitorName, visitorAvatar, visitorId, visitorRole, visitorPhone, visitorCompany, visitorMetadata, onReady, onError, ...config }: TchaoProviderProps): null;
|
|
67
103
|
|
|
68
|
-
export { TchaoConfig, TchaoEvent, TchaoEventMap, TchaoProvider, type UseTchaoOptions, type UseTchaoReturn, VisitorInfo, useTchao };
|
|
104
|
+
export { TchaoConfig, TchaoEvent, TchaoEventMap, TchaoProvider, type TchaoProviderProps, type UseTchaoOptions, type UseTchaoReturn, VisitorInfo, useTchao };
|
package/dist/react.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var P=Object.defineProperty;var q=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var F=(e,t)=>{for(var a in t)P(e,a,{get:t[a],enumerable:!0})},$=(e,t,a,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of D(t))!U.call(e,n)&&n!==a&&P(e,n,{get:()=>t[n],enumerable:!(s=q(t,n))||s.enumerable});return e};var j=e=>$(P({},"__esModule",{value:!0}),e);var B={};F(B,{TchaoProvider:()=>A,init:()=>R,tchao:()=>c,useTchao:()=>V});module.exports=j(B);var o=require("react");var f=!1;function O(e){f=e}function x(e,t){return`[tchao.app] [${new Date().toISOString().split("T")[1].slice(0,-1)}] [${e.toUpperCase()}] ${t}`}var i={debug:(e,...t)=>{f&&console.log(x("debug",e),...t)},info:(e,...t)=>{f&&console.info(x("info",e),...t)},warn:(e,...t)=>{f&&console.warn(x("warn",e),...t)},error:(e,...t)=>{console.error(x("error",e),...t)},group:e=>{f&&console.group(`[tchao.app] ${e}`)},groupEnd:()=>{f&&console.groupEnd()},table:e=>{f&&console.table(e)}};var z="https://tchao.app/widget.js",C=!1,m=null,E=!1,u=null,S=!1,d=[];function G(){for(;d.length>0;){let e=d.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"setMetadata":window.Tchao.setMetadata(e.metadata);break;case"on":window.Tchao.on(e.event,e.callback);break;case"off":window.Tchao.off(e.event,e.callback);break}}catch{}}}async function H(e){return m||(m=new Promise((t,a)=>{if(C&&window.Tchao){t();return}if(document.querySelector("script[data-tchao-widget]")){C=!0,t();return}window.__TCHAO_CONFIG__=e;let n=document.createElement("script");n.src=e.host?`${e.host}/widget.js`:z,n.async=!0,n.dataset.websiteId=e.websiteId,n.dataset.tchaoWidget="true",n.onload=()=>{C=!0,t()},n.onerror=()=>{a(new Error("Failed to load Tchao widget script"))},document.head.appendChild(n)}),m)}async function N(){return new Promise((e,t)=>{let a=0,s=()=>{window.Tchao?e():a>=50?t(new Error("Tchao widget failed to initialize")):(a++,setTimeout(s,100))};s()})}async function R(e){if(e.debug&&(O(!0),i.debug("Debug mode enabled")),e.impersonate&&(S=!0,i.debug("Impersonate mode enabled - identify/setMetadata will be disabled")),i.debug("init() called",{websiteId:e.websiteId,host:e.host}),!e.websiteId)throw new Error("websiteId is required");if(E&&window.Tchao&&u)return i.debug("Already initialized, returning existing instance"),u;if(i.debug("Loading widget script..."),await H(e),i.debug("Widget script loaded, waiting for Tchao..."),await N(),i.debug("Tchao ready"),!window.Tchao)throw new Error("Tchao widget failed to initialize");return E=!0,u=Q(),i.debug("Flushing queued calls...",{queueLength:d.length}),G(),i.debug("Init complete"),u}function Q(){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{}},setMetadata:e=>{try{window.Tchao?.setMetadata(e)}catch{}},config:()=>{try{return window.Tchao?.config()??{}}catch{return{}}},on:(e,t)=>{try{window.Tchao?.on(e,t)}catch{}},off:(e,t)=>{try{window.Tchao?.off(e,t)}catch{}},isReady:()=>E&&!!window.Tchao,destroy:()=>{try{let e=document.querySelector("script[data-tchao-widget]");e&&e.remove();let t=document.getElementById("tchao-widget-root");t&&t.remove(),C=!1,m=null,E=!1,u=null,d.length=0,delete window.__TCHAO_CONFIG__,delete window.Tchao}catch{}}}}function g(e,t){try{return e()}catch{return t}}var c={init:R,show:()=>{window.Tchao?g(()=>window.Tchao?.show(),void 0):d.push({type:"show"})},hide:()=>{window.Tchao?g(()=>window.Tchao?.hide(),void 0):d.push({type:"hide"})},toggle:()=>{window.Tchao?g(()=>window.Tchao?.toggle(),void 0):d.push({type:"toggle"})},open:e=>{window.Tchao?g(()=>window.Tchao?.open(e),void 0):d.push({type:"open",message:e})},identify:e=>{if(S){i.debug("identify() blocked - impersonate mode is enabled");return}i.debug("identify() called",e),i.debug("window.Tchao exists:",!!window.Tchao),window.Tchao?(i.debug("calling window.Tchao.identify()"),g(()=>window.Tchao?.identify(e),void 0)):(i.debug("window.Tchao not ready, queuing call"),d.push({type:"identify",info:e}))},setMetadata:e=>{if(S){i.debug("setMetadata() blocked - impersonate mode is enabled");return}i.debug("setMetadata() called",e),window.Tchao?g(()=>window.Tchao?.setMetadata(e),void 0):d.push({type:"setMetadata",metadata:e})},config:()=>g(()=>window.Tchao?.config()??{},{}),on:(e,t)=>{window.Tchao?g(()=>window.Tchao?.on(e,t),void 0):d.push({type:"on",event:e,callback:t})},off:(e,t)=>{window.Tchao?g(()=>window.Tchao?.off(e,t),void 0):d.push({type:"off",event:e,callback:t})},destroy:()=>{u&&u.destroy()},isReady:()=>E&&!!window.Tchao,getInstance:()=>u};function V(e){let[t,a]=(0,o.useState)(!1),[s,n]=(0,o.useState)(!0),[p,T]=(0,o.useState)(null),h=(0,o.useRef)(null),w=(0,o.useRef)(!0);(0,o.useEffect)(()=>(w.current=!0,R(e).then(r=>{w.current&&(h.current=r,a(!0),n(!1))}).catch(r=>{w.current&&(T(r instanceof Error?r:new Error(String(r))),n(!1))}),()=>{w.current=!1,h.current&&(h.current.destroy(),h.current=null)}),[e.websiteId]);let k=(0,o.useCallback)(()=>c.show(),[]),y=(0,o.useCallback)(()=>c.hide(),[]),I=(0,o.useCallback)(()=>c.toggle(),[]),b=(0,o.useCallback)(r=>c.open(r),[]),M=(0,o.useCallback)(r=>c.identify(r),[]),v=(0,o.useCallback)(r=>c.setMetadata(r),[]),l=(0,o.useCallback)(()=>c.config(),[]),L=(0,o.useCallback)((r,_)=>c.on(r,_),[]),W=(0,o.useCallback)((r,_)=>c.off(r,_),[]);return{isReady:t,isLoading:s,error:p,show:k,hide:y,toggle:I,open:b,identify:M,setMetadata:v,config:l,on:L,off:W}}function A({visitorEmail:e,visitorName:t,visitorAvatar:a,visitorId:s,visitorRole:n,visitorPhone:p,visitorCompany:T,visitorMetadata:h,onReady:w,onError:k,...y}){let{isReady:I,error:b,identify:M}=V(y),v=(0,o.useMemo)(()=>{if(y.impersonate)return null;let l={...h};return s&&(l.userId=s),n&&(l.role=n),p&&(l.phone=p),T&&(l.company=T),e||t||a||Object.keys(l).length>0?{email:e,name:t,avatar:a,metadata:Object.keys(l).length>0?l:void 0}:null},[e,t,a,s,n,p,T,h,y.impersonate]);return(0,o.useEffect)(()=>{I&&(v&&M(v),w?.())},[I,v,M,w]),(0,o.useEffect)(()=>{b&&k?.(b)},[b,k]),null}0&&(module.exports={TchaoProvider,init,tchao,useTchao});
|
|
2
2
|
//# sourceMappingURL=react.js.map
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/widget/react.ts","../../../src/widget/npm.ts"],"sourcesContent":["import { useEffect, useRef, useState, useCallback } from \"react\";\nimport {\n tchao,\n init,\n type TchaoConfig,\n type TchaoInstance,\n type VisitorInfo,\n type TchaoEvent,\n type TchaoEventMap,\n} from \"./npm\";\n\nexport type { TchaoConfig, TchaoInstance, VisitorInfo, TchaoEvent, TchaoEventMap };\n\nexport type UseTchaoOptions = TchaoConfig;\n\nexport type UseTchaoReturn = {\n /** Whether the widget is ready */\n isReady: boolean;\n /** Whether the widget is currently loading */\n isLoading: boolean;\n /** Error if initialization failed */\n error: Error | null;\n /** Show the widget launcher */\n show: () => void;\n /** Hide the widget launcher */\n hide: () => void;\n /** Toggle the chat window */\n toggle: () => void;\n /** Open the chat window with optional pre-filled message */\n open: (message?: string) => void;\n /** Identify the visitor */\n identify: (info: VisitorInfo) => void;\n /** Get current widget configuration */\n config: () => Partial<TchaoConfig>;\n /** Subscribe to widget events */\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n /** Unsubscribe from widget events */\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n};\n\n/**\n * React hook for using the Tchao chat widget.\n *\n * @example\n * ```tsx\n * function App() {\n * const { isReady, open, identify } = useTchao({\n * websiteId: \"your-website-id\",\n * });\n *\n * useEffect(() => {\n * if (isReady) {\n * identify({ email: user.email, name: user.name });\n * }\n * }, [isReady, identify]);\n *\n * return <button onClick={() => open()}>Chat with us</button>;\n * }\n * ```\n */\nexport function useTchao(options: UseTchaoOptions): UseTchaoReturn {\n const [isReady, setIsReady] = useState(false);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const instanceRef = useRef<TchaoInstance | null>(null);\n const mountedRef = useRef(true);\n\n useEffect(() => {\n mountedRef.current = true;\n\n init(options)\n .then((instance) => {\n if (!mountedRef.current) return;\n instanceRef.current = instance;\n setIsReady(true);\n setIsLoading(false);\n })\n .catch((err) => {\n if (!mountedRef.current) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n setIsLoading(false);\n });\n\n return () => {\n mountedRef.current = false;\n if (instanceRef.current) {\n instanceRef.current.destroy();\n instanceRef.current = null;\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- Only re-init when websiteId changes\n }, [options.websiteId]);\n\n const show = useCallback(() => tchao.show(), []);\n const hide = useCallback(() => tchao.hide(), []);\n const toggle = useCallback(() => tchao.toggle(), []);\n const open = useCallback((message?: string) => tchao.open(message), []);\n const identify = useCallback((info: VisitorInfo) => tchao.identify(info), []);\n const config = useCallback(() => tchao.config(), []);\n const on = useCallback(\n <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) =>\n tchao.on(event, callback),\n []\n );\n const off = useCallback(\n <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) =>\n tchao.off(event, callback),\n []\n );\n\n return {\n isReady,\n isLoading,\n error,\n show,\n hide,\n toggle,\n open,\n identify,\n config,\n on,\n off,\n };\n}\n\n/**\n * Simple component that initializes Tchao and optionally identifies the user.\n *\n * @example\n * ```tsx\n * // In your layout or root component\n * <TchaoProvider\n * websiteId=\"your-website-id\"\n * visitor={{ email: user?.email, name: user?.name }}\n * />\n * ```\n */\nexport function TchaoProvider({\n visitor,\n onReady,\n onError,\n ...config\n}: TchaoConfig & {\n visitor?: VisitorInfo;\n onReady?: () => void;\n onError?: (error: Error) => void;\n}): null {\n const { isReady, error, identify } = useTchao(config);\n\n useEffect(() => {\n if (isReady && visitor) {\n identify(visitor);\n }\n }, [isReady, visitor, identify]);\n\n useEffect(() => {\n if (isReady && onReady) {\n onReady();\n }\n }, [isReady, onReady]);\n\n useEffect(() => {\n if (error && onError) {\n onError(error);\n }\n }, [error, onError]);\n\n return null;\n}\n\nexport { tchao, init };\n","export type VisitorInfo = {\n name?: string;\n email?: string;\n avatar?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type WidgetConfig = {\n websiteId: string;\n position?: \"bottom-right\" | \"bottom-left\";\n primaryColor?: string;\n widgetStyle?: \"bubble\" | \"name_line\" | \"question_cta\";\n themeMode?: \"light\" | \"dark\" | \"system\";\n agentName?: string;\n agentRole?: string;\n agentImage?: string;\n agentWelcomeMessage?: string;\n hidePoweredBy?: boolean;\n bubbleIcon?: string;\n};\n\nexport type TchaoConfig = {\n websiteId: string;\n host?: string;\n convexUrl?: string;\n position?: \"bottom-right\" | \"bottom-left\";\n primaryColor?: string;\n widgetStyle?: \"bubble\" | \"name_line\" | \"question_cta\";\n themeMode?: \"light\" | \"dark\" | \"system\";\n agentName?: string;\n agentRole?: string;\n agentImage?: string;\n agentWelcomeMessage?: string;\n hidePoweredBy?: boolean;\n bubbleIcon?: string;\n};\n\nexport type Message = {\n content: string;\n sender: string;\n timestamp: number;\n};\n\nexport type TchaoEventMap = {\n message: (message: Message) => void;\n open: () => void;\n close: () => void;\n ready: () => void;\n};\n\nexport type TchaoEvent = keyof TchaoEventMap;\n\nexport type TchaoInstance = {\n show: () => void;\n hide: () => void;\n toggle: () => void;\n open: (message?: string) => void;\n identify: (info: VisitorInfo) => void;\n config: () => Partial<WidgetConfig>;\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n destroy: () => void;\n isReady: () => boolean;\n};\n\ntype InternalTchaoInstance = {\n show: () => void;\n hide: () => void;\n toggle: () => void;\n open: (message?: string) => void;\n identify: (info: VisitorInfo) => void;\n config: () => Partial<WidgetConfig>;\n on: (event: string, callback: (...args: unknown[]) => void) => void;\n off: (event: string, callback: (...args: unknown[]) => void) => void;\n};\n\ndeclare global {\n interface Window {\n Tchao?: InternalTchaoInstance;\n __TCHAO_CONFIG__?: TchaoConfig;\n }\n}\n\nconst WIDGET_SCRIPT_URL = \"https://tchao.app/widget.js\";\n\nlet scriptLoaded = false;\nlet scriptPromise: Promise<void> | null = null;\nlet initialized = false;\nlet currentInstance: TchaoInstance | null = null;\n\ntype QueuedCall =\n | { type: \"show\" }\n | { type: \"hide\" }\n | { type: \"toggle\" }\n | { type: \"open\"; message?: string }\n | { type: \"identify\"; info: VisitorInfo }\n | { type: \"on\"; event: string; callback: (...args: unknown[]) => void }\n | { type: \"off\"; event: string; callback: (...args: unknown[]) => void };\n\nconst callQueue: QueuedCall[] = [];\n\nfunction flushQueue(): void {\n while (callQueue.length > 0) {\n const call = callQueue.shift();\n if (!call || !window.Tchao) continue;\n\n try {\n switch (call.type) {\n case \"show\":\n window.Tchao.show();\n break;\n case \"hide\":\n window.Tchao.hide();\n break;\n case \"toggle\":\n window.Tchao.toggle();\n break;\n case \"open\":\n window.Tchao.open(call.message);\n break;\n case \"identify\":\n window.Tchao.identify(call.info);\n break;\n case \"on\":\n window.Tchao.on(call.event, call.callback);\n break;\n case \"off\":\n window.Tchao.off(call.event, call.callback);\n break;\n }\n } catch {\n // Silent fail\n }\n }\n}\n\nasync function loadScript(config: TchaoConfig): Promise<void> {\n if (scriptPromise) return scriptPromise;\n\n scriptPromise = new Promise((resolve, reject) => {\n if (scriptLoaded && window.Tchao) {\n resolve();\n return;\n }\n\n const existingScript = document.querySelector(\n 'script[data-tchao-widget]'\n ) as HTMLScriptElement | null;\n\n if (existingScript) {\n scriptLoaded = true;\n resolve();\n return;\n }\n\n window.__TCHAO_CONFIG__ = config;\n\n const script = document.createElement(\"script\");\n script.src = config.host ? `${config.host}/widget.js` : WIDGET_SCRIPT_URL;\n script.async = true;\n script.dataset.websiteId = config.websiteId;\n script.dataset.tchaoWidget = \"true\";\n\n script.onload = () => {\n scriptLoaded = true;\n resolve();\n };\n\n script.onerror = () => {\n reject(new Error(\"Failed to load Tchao widget script\"));\n };\n\n document.head.appendChild(script);\n });\n\n return scriptPromise;\n}\n\nasync function waitForTchao(): Promise<void> {\n return new Promise((resolve, reject) => {\n let attempts = 0;\n const check = () => {\n if (window.Tchao) {\n resolve();\n } else if (attempts >= 50) {\n reject(new Error(\"Tchao widget failed to initialize\"));\n } else {\n attempts++;\n setTimeout(check, 100);\n }\n };\n check();\n });\n}\n\nasync function init(config: TchaoConfig): Promise<TchaoInstance> {\n if (!config.websiteId) {\n throw new Error(\"websiteId is required\");\n }\n\n if (initialized && window.Tchao && currentInstance) {\n return currentInstance;\n }\n\n await loadScript(config);\n await waitForTchao();\n\n if (!window.Tchao) {\n throw new Error(\"Tchao widget failed to initialize\");\n }\n\n initialized = true;\n currentInstance = createInstance();\n flushQueue();\n return currentInstance;\n}\n\nfunction createInstance(): TchaoInstance {\n return {\n show: () => {\n try {\n window.Tchao?.show();\n } catch {\n // Silent fail\n }\n },\n hide: () => {\n try {\n window.Tchao?.hide();\n } catch {\n // Silent fail\n }\n },\n toggle: () => {\n try {\n window.Tchao?.toggle();\n } catch {\n // Silent fail\n }\n },\n open: (message?: string) => {\n try {\n window.Tchao?.open(message);\n } catch {\n // Silent fail\n }\n },\n identify: (info: VisitorInfo) => {\n try {\n window.Tchao?.identify(info);\n } catch {\n // Silent fail\n }\n },\n config: () => {\n try {\n return window.Tchao?.config() ?? {};\n } catch {\n return {};\n }\n },\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => {\n try {\n window.Tchao?.on(event, callback as (...args: unknown[]) => void);\n } catch {\n // Silent fail\n }\n },\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => {\n try {\n window.Tchao?.off(event, callback as (...args: unknown[]) => void);\n } catch {\n // Silent fail\n }\n },\n isReady: () => initialized && !!window.Tchao,\n destroy: () => {\n try {\n const script = document.querySelector('script[data-tchao-widget]');\n if (script) script.remove();\n const widget = document.getElementById(\"tchao-widget-root\");\n if (widget) widget.remove();\n scriptLoaded = false;\n scriptPromise = null;\n initialized = false;\n currentInstance = null;\n callQueue.length = 0;\n delete window.__TCHAO_CONFIG__;\n delete window.Tchao;\n } catch {\n // Silent fail\n }\n },\n };\n}\n\nfunction safeCall<T>(fn: () => T, fallback: T): T {\n try {\n return fn();\n } catch {\n return fallback;\n }\n}\n\n/**\n * Safe API that works before initialization.\n * Calls are queued and executed once the widget is ready.\n */\nexport const tchao = {\n /**\n * Initialize the widget. Returns a promise that resolves with the instance.\n */\n init,\n\n /**\n * Show the widget launcher. Safe to call before init.\n */\n show: (): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.show(), undefined);\n } else {\n callQueue.push({ type: \"show\" });\n }\n },\n\n /**\n * Hide the widget launcher. Safe to call before init.\n */\n hide: (): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.hide(), undefined);\n } else {\n callQueue.push({ type: \"hide\" });\n }\n },\n\n /**\n * Toggle the chat window. Safe to call before init.\n */\n toggle: (): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.toggle(), undefined);\n } else {\n callQueue.push({ type: \"toggle\" });\n }\n },\n\n /**\n * Open the chat window. Safe to call before init.\n */\n open: (message?: string): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.open(message), undefined);\n } else {\n callQueue.push({ type: \"open\", message });\n }\n },\n\n /**\n * Identify the visitor. Safe to call before init.\n */\n identify: (info: VisitorInfo): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.identify(info), undefined);\n } else {\n callQueue.push({ type: \"identify\", info });\n }\n },\n\n /**\n * Get the current widget configuration.\n */\n config: (): Partial<WidgetConfig> => {\n return safeCall(() => window.Tchao?.config() ?? {}, {});\n },\n\n /**\n * Subscribe to widget events. Safe to call before init.\n */\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]): void => {\n if (window.Tchao) {\n safeCall(\n () => window.Tchao?.on(event, callback as (...args: unknown[]) => void),\n undefined\n );\n } else {\n callQueue.push({\n type: \"on\",\n event,\n callback: callback as (...args: unknown[]) => void,\n });\n }\n },\n\n /**\n * Unsubscribe from widget events.\n */\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]): void => {\n if (window.Tchao) {\n safeCall(\n () =>\n window.Tchao?.off(event, callback as (...args: unknown[]) => void),\n undefined\n );\n } else {\n callQueue.push({\n type: \"off\",\n event,\n callback: callback as (...args: unknown[]) => void,\n });\n }\n },\n\n /**\n * Destroy the widget and clean up resources.\n */\n destroy: (): void => {\n if (currentInstance) {\n currentInstance.destroy();\n }\n },\n\n /**\n * Check if the widget is ready.\n */\n isReady: (): boolean => initialized && !!window.Tchao,\n\n /**\n * Get the current instance (null if not initialized).\n */\n getInstance: (): TchaoInstance | null => currentInstance,\n};\n\nexport const Tchao = {\n init,\n};\n\nexport { init };\nexport default Tchao;\n"],"mappings":"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","names":["react_exports","__export","TchaoProvider","init","tchao","useTchao","__toCommonJS","import_react","WIDGET_SCRIPT_URL","scriptLoaded","scriptPromise","initialized","currentInstance","callQueue","flushQueue","call","loadScript","config","resolve","reject","script","waitForTchao","attempts","check","init","createInstance","message","info","event","callback","widget","safeCall","fn","fallback","tchao","useTchao","options","isReady","setIsReady","isLoading","setIsLoading","error","setError","instanceRef","mountedRef","init","instance","err","show","tchao","hide","toggle","open","message","identify","info","config","on","event","callback","off","TchaoProvider","visitor","onReady","onError"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/widget/react.ts","../../../src/widget-preact/logger.ts","../../../src/widget/npm.ts"],"sourcesContent":["import { useEffect, useRef, useState, useCallback, useMemo } 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 /** Set custom metadata for the visitor */\n setMetadata: (metadata: Record<string, unknown>) => 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 setMetadata = useCallback(\n (metadata: Record<string, unknown>) => tchao.setMetadata(metadata),\n [],\n );\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 setMetadata,\n config,\n on,\n off,\n };\n}\n\nexport type TchaoProviderProps = TchaoConfig & {\n /** Visitor's email address */\n visitorEmail?: string;\n /** Visitor's display name */\n visitorName?: string;\n /** Visitor's avatar URL */\n visitorAvatar?: string;\n /** Visitor's unique identifier (added to metadata) */\n visitorId?: string;\n /** Visitor's role (added to metadata) */\n visitorRole?: string;\n /** Visitor's phone number (added to metadata) */\n visitorPhone?: string;\n /** Visitor's company name (added to metadata) */\n visitorCompany?: string;\n /** Custom metadata to merge with visitor info */\n visitorMetadata?: Record<string, unknown>;\n /** Callback when widget is ready */\n onReady?: () => void;\n /** Callback when an error occurs */\n onError?: (error: Error) => void;\n};\n\n/**\n * Simple component that initializes Tchao and optionally identifies the user.\n *\n * @example\n * ```tsx\n * // Basic usage\n * <TchaoProvider\n * websiteId=\"your-website-id\"\n * visitorEmail={user?.email}\n * visitorName={user?.name}\n * visitorAvatar={user?.image}\n * />\n *\n * // With metadata\n * <TchaoProvider\n * websiteId=\"your-website-id\"\n * visitorEmail={user?.email}\n * visitorName={user?.name}\n * visitorId={user?.id}\n * visitorRole={user?.role}\n * visitorCompany={user?.company}\n * visitorMetadata={{\n * plan: user?.plan,\n * impersonatedBy: admin?.email,\n * }}\n * />\n * ```\n */\nexport function TchaoProvider({\n visitorEmail,\n visitorName,\n visitorAvatar,\n visitorId,\n visitorRole,\n visitorPhone,\n visitorCompany,\n visitorMetadata,\n onReady,\n onError,\n ...config\n}: TchaoProviderProps): null {\n const { isReady, error, identify } = useTchao(config);\n\n const visitorInfo = useMemo<VisitorInfo | null>(() => {\n if (config.impersonate) return null;\n\n const metadata: Record<string, unknown> = { ...visitorMetadata };\n if (visitorId) metadata.userId = visitorId;\n if (visitorRole) metadata.role = visitorRole;\n if (visitorPhone) metadata.phone = visitorPhone;\n if (visitorCompany) metadata.company = visitorCompany;\n\n const hasData = visitorEmail || visitorName || visitorAvatar || Object.keys(metadata).length > 0;\n if (!hasData) return null;\n\n return {\n email: visitorEmail,\n name: visitorName,\n avatar: visitorAvatar,\n metadata: Object.keys(metadata).length > 0 ? metadata : undefined,\n };\n }, [visitorEmail, visitorName, visitorAvatar, visitorId, visitorRole, visitorPhone, visitorCompany, visitorMetadata, config.impersonate]);\n\n useEffect(() => {\n if (!isReady) return;\n if (visitorInfo) identify(visitorInfo);\n onReady?.();\n }, [isReady, visitorInfo, identify, onReady]);\n\n useEffect(() => {\n if (error) onError?.(error);\n }, [error, onError]);\n\n return null;\n}\n\nexport { tchao, init };\n","/* eslint-disable no-console */\ntype LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nlet debugEnabled = false;\n\nexport function setDebugEnabled(enabled: boolean): void {\n debugEnabled = enabled;\n}\n\nexport function isDebugEnabled(): boolean {\n return debugEnabled;\n}\n\nfunction formatMessage(level: LogLevel, message: string): string {\n const timestamp = new Date().toISOString().split(\"T\")[1].slice(0, -1);\n return `[tchao.app] [${timestamp}] [${level.toUpperCase()}] ${message}`;\n}\n\nexport const logger = {\n debug: (message: string, ...args: unknown[]): void => {\n if (!debugEnabled) return;\n console.log(formatMessage(\"debug\", message), ...args);\n },\n\n info: (message: string, ...args: unknown[]): void => {\n if (!debugEnabled) return;\n console.info(formatMessage(\"info\", message), ...args);\n },\n\n warn: (message: string, ...args: unknown[]): void => {\n if (!debugEnabled) return;\n console.warn(formatMessage(\"warn\", message), ...args);\n },\n\n error: (message: string, ...args: unknown[]): void => {\n // Always show errors\n console.error(formatMessage(\"error\", message), ...args);\n },\n\n group: (label: string): void => {\n if (!debugEnabled) return;\n console.group(`[tchao.app] ${label}`);\n },\n\n groupEnd: (): void => {\n if (!debugEnabled) return;\n console.groupEnd();\n },\n\n table: (data: unknown): void => {\n if (!debugEnabled) return;\n console.table(data);\n },\n};\n","import { logger, setDebugEnabled } from \"../widget-preact/logger\";\n\nexport 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 debug?: boolean;\n /** When true, disables identify/setMetadata to prevent data pollution during impersonation */\n impersonate?: boolean;\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 setMetadata: (metadata: Record<string, unknown>) => 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 setMetadata: (metadata: Record<string, unknown>) => 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;\nlet impersonateMode = false;\n\ntype QueuedCall =\n | { type: \"show\" }\n | { type: \"hide\" }\n | { type: \"toggle\" }\n | { type: \"open\"; message?: string }\n | { type: \"identify\"; info: VisitorInfo }\n | { type: \"setMetadata\"; metadata: Record<string, unknown> }\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 \"setMetadata\":\n window.Tchao.setMetadata(call.metadata);\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.debug) {\n setDebugEnabled(true);\n logger.debug(\"Debug mode enabled\");\n }\n\n if (config.impersonate) {\n impersonateMode = true;\n logger.debug(\"Impersonate mode enabled - identify/setMetadata will be disabled\");\n }\n\n logger.debug(\"init() called\", { websiteId: config.websiteId, host: config.host });\n\n if (!config.websiteId) {\n throw new Error(\"websiteId is required\");\n }\n\n if (initialized && window.Tchao && currentInstance) {\n logger.debug(\"Already initialized, returning existing instance\");\n return currentInstance;\n }\n\n logger.debug(\"Loading widget script...\");\n await loadScript(config);\n logger.debug(\"Widget script loaded, waiting for Tchao...\");\n await waitForTchao();\n logger.debug(\"Tchao ready\");\n\n if (!window.Tchao) {\n throw new Error(\"Tchao widget failed to initialize\");\n }\n\n initialized = true;\n currentInstance = createInstance();\n logger.debug(\"Flushing queued calls...\", { queueLength: callQueue.length });\n flushQueue();\n logger.debug(\"Init complete\");\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 setMetadata: (metadata: Record<string, unknown>) => {\n try {\n window.Tchao?.setMetadata(metadata);\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 * Disabled when impersonate mode is enabled.\n */\n identify: (info: VisitorInfo): void => {\n if (impersonateMode) {\n logger.debug(\"identify() blocked - impersonate mode is enabled\");\n return;\n }\n logger.debug(\"identify() called\", info);\n logger.debug(\"window.Tchao exists:\", !!window.Tchao);\n if (window.Tchao) {\n logger.debug(\"calling window.Tchao.identify()\");\n safeCall(() => window.Tchao?.identify(info), undefined);\n } else {\n logger.debug(\"window.Tchao not ready, queuing call\");\n callQueue.push({ type: \"identify\", info });\n }\n },\n\n /**\n * Set custom metadata for the visitor. Safe to call before init.\n * Disabled when impersonate mode is enabled.\n */\n setMetadata: (metadata: Record<string, unknown>): void => {\n if (impersonateMode) {\n logger.debug(\"setMetadata() blocked - impersonate mode is enabled\");\n return;\n }\n logger.debug(\"setMetadata() called\", metadata);\n if (window.Tchao) {\n safeCall(() => window.Tchao?.setMetadata(metadata), undefined);\n } else {\n callQueue.push({ type: \"setMetadata\", metadata });\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","debugEnabled","setDebugEnabled","enabled","formatMessage","level","message","logger","args","debugEnabled","label","data","WIDGET_SCRIPT_URL","scriptLoaded","scriptPromise","initialized","currentInstance","impersonateMode","callQueue","flushQueue","call","loadScript","config","resolve","reject","script","waitForTchao","attempts","check","init","setDebugEnabled","logger","createInstance","message","info","metadata","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","setMetadata","metadata","config","on","event","callback","off","TchaoProvider","visitorEmail","visitorName","visitorAvatar","visitorId","visitorRole","visitorPhone","visitorCompany","visitorMetadata","onReady","onError","visitorInfo"]}
|
package/dist/react.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{useEffect as
|
|
1
|
+
import{useEffect as L,useRef as W,useState as S,useCallback as g,useMemo as z}from"react";var f=!1;function V(e){f=e}function x(e,t){return`[tchao.app] [${new Date().toISOString().split("T")[1].slice(0,-1)}] [${e.toUpperCase()}] ${t}`}var o={debug:(e,...t)=>{f&&console.log(x("debug",e),...t)},info:(e,...t)=>{f&&console.info(x("info",e),...t)},warn:(e,...t)=>{f&&console.warn(x("warn",e),...t)},error:(e,...t)=>{console.error(x("error",e),...t)},group:e=>{f&&console.group(`[tchao.app] ${e}`)},groupEnd:()=>{f&&console.groupEnd()},table:e=>{f&&console.table(e)}};var D="https://tchao.app/widget.js",C=!1,m=null,E=!1,u=null,_=!1,a=[];function U(){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"setMetadata":window.Tchao.setMetadata(e.metadata);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 m||(m=new Promise((t,r)=>{if(C&&window.Tchao){t();return}if(document.querySelector("script[data-tchao-widget]")){C=!0,t();return}window.__TCHAO_CONFIG__=e;let i=document.createElement("script");i.src=e.host?`${e.host}/widget.js`:D,i.async=!0,i.dataset.websiteId=e.websiteId,i.dataset.tchaoWidget="true",i.onload=()=>{C=!0,t()},i.onerror=()=>{r(new Error("Failed to load Tchao widget script"))},document.head.appendChild(i)}),m)}async function $(){return new Promise((e,t)=>{let r=0,d=()=>{window.Tchao?e():r>=50?t(new Error("Tchao widget failed to initialize")):(r++,setTimeout(d,100))};d()})}async function P(e){if(e.debug&&(V(!0),o.debug("Debug mode enabled")),e.impersonate&&(_=!0,o.debug("Impersonate mode enabled - identify/setMetadata will be disabled")),o.debug("init() called",{websiteId:e.websiteId,host:e.host}),!e.websiteId)throw new Error("websiteId is required");if(E&&window.Tchao&&u)return o.debug("Already initialized, returning existing instance"),u;if(o.debug("Loading widget script..."),await F(e),o.debug("Widget script loaded, waiting for Tchao..."),await $(),o.debug("Tchao ready"),!window.Tchao)throw new Error("Tchao widget failed to initialize");return E=!0,u=j(),o.debug("Flushing queued calls...",{queueLength:a.length}),U(),o.debug("Init complete"),u}function j(){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{}},setMetadata:e=>{try{window.Tchao?.setMetadata(e)}catch{}},config:()=>{try{return window.Tchao?.config()??{}}catch{return{}}},on:(e,t)=>{try{window.Tchao?.on(e,t)}catch{}},off:(e,t)=>{try{window.Tchao?.off(e,t)}catch{}},isReady:()=>E&&!!window.Tchao,destroy:()=>{try{let e=document.querySelector("script[data-tchao-widget]");e&&e.remove();let t=document.getElementById("tchao-widget-root");t&&t.remove(),C=!1,m=null,E=!1,u=null,a.length=0,delete window.__TCHAO_CONFIG__,delete window.Tchao}catch{}}}}function l(e,t){try{return e()}catch{return t}}var s={init:P,show:()=>{window.Tchao?l(()=>window.Tchao?.show(),void 0):a.push({type:"show"})},hide:()=>{window.Tchao?l(()=>window.Tchao?.hide(),void 0):a.push({type:"hide"})},toggle:()=>{window.Tchao?l(()=>window.Tchao?.toggle(),void 0):a.push({type:"toggle"})},open:e=>{window.Tchao?l(()=>window.Tchao?.open(e),void 0):a.push({type:"open",message:e})},identify:e=>{if(_){o.debug("identify() blocked - impersonate mode is enabled");return}o.debug("identify() called",e),o.debug("window.Tchao exists:",!!window.Tchao),window.Tchao?(o.debug("calling window.Tchao.identify()"),l(()=>window.Tchao?.identify(e),void 0)):(o.debug("window.Tchao not ready, queuing call"),a.push({type:"identify",info:e}))},setMetadata:e=>{if(_){o.debug("setMetadata() blocked - impersonate mode is enabled");return}o.debug("setMetadata() called",e),window.Tchao?l(()=>window.Tchao?.setMetadata(e),void 0):a.push({type:"setMetadata",metadata:e})},config:()=>l(()=>window.Tchao?.config()??{},{}),on:(e,t)=>{window.Tchao?l(()=>window.Tchao?.on(e,t),void 0):a.push({type:"on",event:e,callback:t})},off:(e,t)=>{window.Tchao?l(()=>window.Tchao?.off(e,t),void 0):a.push({type:"off",event:e,callback:t})},destroy:()=>{u&&u.destroy()},isReady:()=>E&&!!window.Tchao,getInstance:()=>u};function G(e){let[t,r]=S(!1),[d,i]=S(!0),[p,T]=S(null),h=W(null),w=W(!0);L(()=>(w.current=!0,P(e).then(n=>{w.current&&(h.current=n,r(!0),i(!1))}).catch(n=>{w.current&&(T(n instanceof Error?n:new Error(String(n))),i(!1))}),()=>{w.current=!1,h.current&&(h.current.destroy(),h.current=null)}),[e.websiteId]);let k=g(()=>s.show(),[]),y=g(()=>s.hide(),[]),I=g(()=>s.toggle(),[]),b=g(n=>s.open(n),[]),M=g(n=>s.identify(n),[]),v=g(n=>s.setMetadata(n),[]),c=g(()=>s.config(),[]),O=g((n,R)=>s.on(n,R),[]),q=g((n,R)=>s.off(n,R),[]);return{isReady:t,isLoading:d,error:p,show:k,hide:y,toggle:I,open:b,identify:M,setMetadata:v,config:c,on:O,off:q}}function J({visitorEmail:e,visitorName:t,visitorAvatar:r,visitorId:d,visitorRole:i,visitorPhone:p,visitorCompany:T,visitorMetadata:h,onReady:w,onError:k,...y}){let{isReady:I,error:b,identify:M}=G(y),v=z(()=>{if(y.impersonate)return null;let c={...h};return d&&(c.userId=d),i&&(c.role=i),p&&(c.phone=p),T&&(c.company=T),e||t||r||Object.keys(c).length>0?{email:e,name:t,avatar:r,metadata:Object.keys(c).length>0?c:void 0}:null},[e,t,r,d,i,p,T,h,y.impersonate]);return L(()=>{I&&(v&&M(v),w?.())},[I,v,M,w]),L(()=>{b&&k?.(b)},[b,k]),null}export{J as TchaoProvider,P as init,s as tchao,G as useTchao};
|
|
2
2
|
//# sourceMappingURL=react.mjs.map
|
package/dist/react.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/widget/react.ts","../../../src/widget/npm.ts"],"sourcesContent":["import { useEffect, useRef, useState, useCallback } from \"react\";\nimport {\n tchao,\n init,\n type TchaoConfig,\n type TchaoInstance,\n type VisitorInfo,\n type TchaoEvent,\n type TchaoEventMap,\n} from \"./npm\";\n\nexport type { TchaoConfig, TchaoInstance, VisitorInfo, TchaoEvent, TchaoEventMap };\n\nexport type UseTchaoOptions = TchaoConfig;\n\nexport type UseTchaoReturn = {\n /** Whether the widget is ready */\n isReady: boolean;\n /** Whether the widget is currently loading */\n isLoading: boolean;\n /** Error if initialization failed */\n error: Error | null;\n /** Show the widget launcher */\n show: () => void;\n /** Hide the widget launcher */\n hide: () => void;\n /** Toggle the chat window */\n toggle: () => void;\n /** Open the chat window with optional pre-filled message */\n open: (message?: string) => void;\n /** Identify the visitor */\n identify: (info: VisitorInfo) => void;\n /** Get current widget configuration */\n config: () => Partial<TchaoConfig>;\n /** Subscribe to widget events */\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n /** Unsubscribe from widget events */\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n};\n\n/**\n * React hook for using the Tchao chat widget.\n *\n * @example\n * ```tsx\n * function App() {\n * const { isReady, open, identify } = useTchao({\n * websiteId: \"your-website-id\",\n * });\n *\n * useEffect(() => {\n * if (isReady) {\n * identify({ email: user.email, name: user.name });\n * }\n * }, [isReady, identify]);\n *\n * return <button onClick={() => open()}>Chat with us</button>;\n * }\n * ```\n */\nexport function useTchao(options: UseTchaoOptions): UseTchaoReturn {\n const [isReady, setIsReady] = useState(false);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const instanceRef = useRef<TchaoInstance | null>(null);\n const mountedRef = useRef(true);\n\n useEffect(() => {\n mountedRef.current = true;\n\n init(options)\n .then((instance) => {\n if (!mountedRef.current) return;\n instanceRef.current = instance;\n setIsReady(true);\n setIsLoading(false);\n })\n .catch((err) => {\n if (!mountedRef.current) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n setIsLoading(false);\n });\n\n return () => {\n mountedRef.current = false;\n if (instanceRef.current) {\n instanceRef.current.destroy();\n instanceRef.current = null;\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- Only re-init when websiteId changes\n }, [options.websiteId]);\n\n const show = useCallback(() => tchao.show(), []);\n const hide = useCallback(() => tchao.hide(), []);\n const toggle = useCallback(() => tchao.toggle(), []);\n const open = useCallback((message?: string) => tchao.open(message), []);\n const identify = useCallback((info: VisitorInfo) => tchao.identify(info), []);\n const config = useCallback(() => tchao.config(), []);\n const on = useCallback(\n <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) =>\n tchao.on(event, callback),\n []\n );\n const off = useCallback(\n <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) =>\n tchao.off(event, callback),\n []\n );\n\n return {\n isReady,\n isLoading,\n error,\n show,\n hide,\n toggle,\n open,\n identify,\n config,\n on,\n off,\n };\n}\n\n/**\n * Simple component that initializes Tchao and optionally identifies the user.\n *\n * @example\n * ```tsx\n * // In your layout or root component\n * <TchaoProvider\n * websiteId=\"your-website-id\"\n * visitor={{ email: user?.email, name: user?.name }}\n * />\n * ```\n */\nexport function TchaoProvider({\n visitor,\n onReady,\n onError,\n ...config\n}: TchaoConfig & {\n visitor?: VisitorInfo;\n onReady?: () => void;\n onError?: (error: Error) => void;\n}): null {\n const { isReady, error, identify } = useTchao(config);\n\n useEffect(() => {\n if (isReady && visitor) {\n identify(visitor);\n }\n }, [isReady, visitor, identify]);\n\n useEffect(() => {\n if (isReady && onReady) {\n onReady();\n }\n }, [isReady, onReady]);\n\n useEffect(() => {\n if (error && onError) {\n onError(error);\n }\n }, [error, onError]);\n\n return null;\n}\n\nexport { tchao, init };\n","export type VisitorInfo = {\n name?: string;\n email?: string;\n avatar?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type WidgetConfig = {\n websiteId: string;\n position?: \"bottom-right\" | \"bottom-left\";\n primaryColor?: string;\n widgetStyle?: \"bubble\" | \"name_line\" | \"question_cta\";\n themeMode?: \"light\" | \"dark\" | \"system\";\n agentName?: string;\n agentRole?: string;\n agentImage?: string;\n agentWelcomeMessage?: string;\n hidePoweredBy?: boolean;\n bubbleIcon?: string;\n};\n\nexport type TchaoConfig = {\n websiteId: string;\n host?: string;\n convexUrl?: string;\n position?: \"bottom-right\" | \"bottom-left\";\n primaryColor?: string;\n widgetStyle?: \"bubble\" | \"name_line\" | \"question_cta\";\n themeMode?: \"light\" | \"dark\" | \"system\";\n agentName?: string;\n agentRole?: string;\n agentImage?: string;\n agentWelcomeMessage?: string;\n hidePoweredBy?: boolean;\n bubbleIcon?: string;\n};\n\nexport type Message = {\n content: string;\n sender: string;\n timestamp: number;\n};\n\nexport type TchaoEventMap = {\n message: (message: Message) => void;\n open: () => void;\n close: () => void;\n ready: () => void;\n};\n\nexport type TchaoEvent = keyof TchaoEventMap;\n\nexport type TchaoInstance = {\n show: () => void;\n hide: () => void;\n toggle: () => void;\n open: (message?: string) => void;\n identify: (info: VisitorInfo) => void;\n config: () => Partial<WidgetConfig>;\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => void;\n destroy: () => void;\n isReady: () => boolean;\n};\n\ntype InternalTchaoInstance = {\n show: () => void;\n hide: () => void;\n toggle: () => void;\n open: (message?: string) => void;\n identify: (info: VisitorInfo) => void;\n config: () => Partial<WidgetConfig>;\n on: (event: string, callback: (...args: unknown[]) => void) => void;\n off: (event: string, callback: (...args: unknown[]) => void) => void;\n};\n\ndeclare global {\n interface Window {\n Tchao?: InternalTchaoInstance;\n __TCHAO_CONFIG__?: TchaoConfig;\n }\n}\n\nconst WIDGET_SCRIPT_URL = \"https://tchao.app/widget.js\";\n\nlet scriptLoaded = false;\nlet scriptPromise: Promise<void> | null = null;\nlet initialized = false;\nlet currentInstance: TchaoInstance | null = null;\n\ntype QueuedCall =\n | { type: \"show\" }\n | { type: \"hide\" }\n | { type: \"toggle\" }\n | { type: \"open\"; message?: string }\n | { type: \"identify\"; info: VisitorInfo }\n | { type: \"on\"; event: string; callback: (...args: unknown[]) => void }\n | { type: \"off\"; event: string; callback: (...args: unknown[]) => void };\n\nconst callQueue: QueuedCall[] = [];\n\nfunction flushQueue(): void {\n while (callQueue.length > 0) {\n const call = callQueue.shift();\n if (!call || !window.Tchao) continue;\n\n try {\n switch (call.type) {\n case \"show\":\n window.Tchao.show();\n break;\n case \"hide\":\n window.Tchao.hide();\n break;\n case \"toggle\":\n window.Tchao.toggle();\n break;\n case \"open\":\n window.Tchao.open(call.message);\n break;\n case \"identify\":\n window.Tchao.identify(call.info);\n break;\n case \"on\":\n window.Tchao.on(call.event, call.callback);\n break;\n case \"off\":\n window.Tchao.off(call.event, call.callback);\n break;\n }\n } catch {\n // Silent fail\n }\n }\n}\n\nasync function loadScript(config: TchaoConfig): Promise<void> {\n if (scriptPromise) return scriptPromise;\n\n scriptPromise = new Promise((resolve, reject) => {\n if (scriptLoaded && window.Tchao) {\n resolve();\n return;\n }\n\n const existingScript = document.querySelector(\n 'script[data-tchao-widget]'\n ) as HTMLScriptElement | null;\n\n if (existingScript) {\n scriptLoaded = true;\n resolve();\n return;\n }\n\n window.__TCHAO_CONFIG__ = config;\n\n const script = document.createElement(\"script\");\n script.src = config.host ? `${config.host}/widget.js` : WIDGET_SCRIPT_URL;\n script.async = true;\n script.dataset.websiteId = config.websiteId;\n script.dataset.tchaoWidget = \"true\";\n\n script.onload = () => {\n scriptLoaded = true;\n resolve();\n };\n\n script.onerror = () => {\n reject(new Error(\"Failed to load Tchao widget script\"));\n };\n\n document.head.appendChild(script);\n });\n\n return scriptPromise;\n}\n\nasync function waitForTchao(): Promise<void> {\n return new Promise((resolve, reject) => {\n let attempts = 0;\n const check = () => {\n if (window.Tchao) {\n resolve();\n } else if (attempts >= 50) {\n reject(new Error(\"Tchao widget failed to initialize\"));\n } else {\n attempts++;\n setTimeout(check, 100);\n }\n };\n check();\n });\n}\n\nasync function init(config: TchaoConfig): Promise<TchaoInstance> {\n if (!config.websiteId) {\n throw new Error(\"websiteId is required\");\n }\n\n if (initialized && window.Tchao && currentInstance) {\n return currentInstance;\n }\n\n await loadScript(config);\n await waitForTchao();\n\n if (!window.Tchao) {\n throw new Error(\"Tchao widget failed to initialize\");\n }\n\n initialized = true;\n currentInstance = createInstance();\n flushQueue();\n return currentInstance;\n}\n\nfunction createInstance(): TchaoInstance {\n return {\n show: () => {\n try {\n window.Tchao?.show();\n } catch {\n // Silent fail\n }\n },\n hide: () => {\n try {\n window.Tchao?.hide();\n } catch {\n // Silent fail\n }\n },\n toggle: () => {\n try {\n window.Tchao?.toggle();\n } catch {\n // Silent fail\n }\n },\n open: (message?: string) => {\n try {\n window.Tchao?.open(message);\n } catch {\n // Silent fail\n }\n },\n identify: (info: VisitorInfo) => {\n try {\n window.Tchao?.identify(info);\n } catch {\n // Silent fail\n }\n },\n config: () => {\n try {\n return window.Tchao?.config() ?? {};\n } catch {\n return {};\n }\n },\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => {\n try {\n window.Tchao?.on(event, callback as (...args: unknown[]) => void);\n } catch {\n // Silent fail\n }\n },\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]) => {\n try {\n window.Tchao?.off(event, callback as (...args: unknown[]) => void);\n } catch {\n // Silent fail\n }\n },\n isReady: () => initialized && !!window.Tchao,\n destroy: () => {\n try {\n const script = document.querySelector('script[data-tchao-widget]');\n if (script) script.remove();\n const widget = document.getElementById(\"tchao-widget-root\");\n if (widget) widget.remove();\n scriptLoaded = false;\n scriptPromise = null;\n initialized = false;\n currentInstance = null;\n callQueue.length = 0;\n delete window.__TCHAO_CONFIG__;\n delete window.Tchao;\n } catch {\n // Silent fail\n }\n },\n };\n}\n\nfunction safeCall<T>(fn: () => T, fallback: T): T {\n try {\n return fn();\n } catch {\n return fallback;\n }\n}\n\n/**\n * Safe API that works before initialization.\n * Calls are queued and executed once the widget is ready.\n */\nexport const tchao = {\n /**\n * Initialize the widget. Returns a promise that resolves with the instance.\n */\n init,\n\n /**\n * Show the widget launcher. Safe to call before init.\n */\n show: (): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.show(), undefined);\n } else {\n callQueue.push({ type: \"show\" });\n }\n },\n\n /**\n * Hide the widget launcher. Safe to call before init.\n */\n hide: (): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.hide(), undefined);\n } else {\n callQueue.push({ type: \"hide\" });\n }\n },\n\n /**\n * Toggle the chat window. Safe to call before init.\n */\n toggle: (): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.toggle(), undefined);\n } else {\n callQueue.push({ type: \"toggle\" });\n }\n },\n\n /**\n * Open the chat window. Safe to call before init.\n */\n open: (message?: string): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.open(message), undefined);\n } else {\n callQueue.push({ type: \"open\", message });\n }\n },\n\n /**\n * Identify the visitor. Safe to call before init.\n */\n identify: (info: VisitorInfo): void => {\n if (window.Tchao) {\n safeCall(() => window.Tchao?.identify(info), undefined);\n } else {\n callQueue.push({ type: \"identify\", info });\n }\n },\n\n /**\n * Get the current widget configuration.\n */\n config: (): Partial<WidgetConfig> => {\n return safeCall(() => window.Tchao?.config() ?? {}, {});\n },\n\n /**\n * Subscribe to widget events. Safe to call before init.\n */\n on: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]): void => {\n if (window.Tchao) {\n safeCall(\n () => window.Tchao?.on(event, callback as (...args: unknown[]) => void),\n undefined\n );\n } else {\n callQueue.push({\n type: \"on\",\n event,\n callback: callback as (...args: unknown[]) => void,\n });\n }\n },\n\n /**\n * Unsubscribe from widget events.\n */\n off: <E extends TchaoEvent>(event: E, callback: TchaoEventMap[E]): void => {\n if (window.Tchao) {\n safeCall(\n () =>\n window.Tchao?.off(event, callback as (...args: unknown[]) => void),\n undefined\n );\n } else {\n callQueue.push({\n type: \"off\",\n event,\n callback: callback as (...args: unknown[]) => void,\n });\n }\n },\n\n /**\n * Destroy the widget and clean up resources.\n */\n destroy: (): void => {\n if (currentInstance) {\n currentInstance.destroy();\n }\n },\n\n /**\n * Check if the widget is ready.\n */\n isReady: (): boolean => initialized && !!window.Tchao,\n\n /**\n * Get the current instance (null if not initialized).\n */\n getInstance: (): TchaoInstance | null => currentInstance,\n};\n\nexport const Tchao = {\n init,\n};\n\nexport { init };\nexport default Tchao;\n"],"mappings":"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","names":["useEffect","useRef","useState","useCallback","WIDGET_SCRIPT_URL","scriptLoaded","scriptPromise","initialized","currentInstance","callQueue","flushQueue","call","loadScript","config","resolve","reject","script","waitForTchao","attempts","check","init","createInstance","message","info","event","callback","widget","safeCall","fn","fallback","tchao","useTchao","options","isReady","setIsReady","useState","isLoading","setIsLoading","error","setError","instanceRef","useRef","mountedRef","useEffect","init","instance","err","show","useCallback","tchao","hide","toggle","open","message","identify","info","config","on","event","callback","off","TchaoProvider","visitor","onReady","onError"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/widget/react.ts","../../../src/widget-preact/logger.ts","../../../src/widget/npm.ts"],"sourcesContent":["import { useEffect, useRef, useState, useCallback, useMemo } 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 /** Set custom metadata for the visitor */\n setMetadata: (metadata: Record<string, unknown>) => 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 setMetadata = useCallback(\n (metadata: Record<string, unknown>) => tchao.setMetadata(metadata),\n [],\n );\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 setMetadata,\n config,\n on,\n off,\n };\n}\n\nexport type TchaoProviderProps = TchaoConfig & {\n /** Visitor's email address */\n visitorEmail?: string;\n /** Visitor's display name */\n visitorName?: string;\n /** Visitor's avatar URL */\n visitorAvatar?: string;\n /** Visitor's unique identifier (added to metadata) */\n visitorId?: string;\n /** Visitor's role (added to metadata) */\n visitorRole?: string;\n /** Visitor's phone number (added to metadata) */\n visitorPhone?: string;\n /** Visitor's company name (added to metadata) */\n visitorCompany?: string;\n /** Custom metadata to merge with visitor info */\n visitorMetadata?: Record<string, unknown>;\n /** Callback when widget is ready */\n onReady?: () => void;\n /** Callback when an error occurs */\n onError?: (error: Error) => void;\n};\n\n/**\n * Simple component that initializes Tchao and optionally identifies the user.\n *\n * @example\n * ```tsx\n * // Basic usage\n * <TchaoProvider\n * websiteId=\"your-website-id\"\n * visitorEmail={user?.email}\n * visitorName={user?.name}\n * visitorAvatar={user?.image}\n * />\n *\n * // With metadata\n * <TchaoProvider\n * websiteId=\"your-website-id\"\n * visitorEmail={user?.email}\n * visitorName={user?.name}\n * visitorId={user?.id}\n * visitorRole={user?.role}\n * visitorCompany={user?.company}\n * visitorMetadata={{\n * plan: user?.plan,\n * impersonatedBy: admin?.email,\n * }}\n * />\n * ```\n */\nexport function TchaoProvider({\n visitorEmail,\n visitorName,\n visitorAvatar,\n visitorId,\n visitorRole,\n visitorPhone,\n visitorCompany,\n visitorMetadata,\n onReady,\n onError,\n ...config\n}: TchaoProviderProps): null {\n const { isReady, error, identify } = useTchao(config);\n\n const visitorInfo = useMemo<VisitorInfo | null>(() => {\n if (config.impersonate) return null;\n\n const metadata: Record<string, unknown> = { ...visitorMetadata };\n if (visitorId) metadata.userId = visitorId;\n if (visitorRole) metadata.role = visitorRole;\n if (visitorPhone) metadata.phone = visitorPhone;\n if (visitorCompany) metadata.company = visitorCompany;\n\n const hasData = visitorEmail || visitorName || visitorAvatar || Object.keys(metadata).length > 0;\n if (!hasData) return null;\n\n return {\n email: visitorEmail,\n name: visitorName,\n avatar: visitorAvatar,\n metadata: Object.keys(metadata).length > 0 ? metadata : undefined,\n };\n }, [visitorEmail, visitorName, visitorAvatar, visitorId, visitorRole, visitorPhone, visitorCompany, visitorMetadata, config.impersonate]);\n\n useEffect(() => {\n if (!isReady) return;\n if (visitorInfo) identify(visitorInfo);\n onReady?.();\n }, [isReady, visitorInfo, identify, onReady]);\n\n useEffect(() => {\n if (error) onError?.(error);\n }, [error, onError]);\n\n return null;\n}\n\nexport { tchao, init };\n","/* eslint-disable no-console */\ntype LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nlet debugEnabled = false;\n\nexport function setDebugEnabled(enabled: boolean): void {\n debugEnabled = enabled;\n}\n\nexport function isDebugEnabled(): boolean {\n return debugEnabled;\n}\n\nfunction formatMessage(level: LogLevel, message: string): string {\n const timestamp = new Date().toISOString().split(\"T\")[1].slice(0, -1);\n return `[tchao.app] [${timestamp}] [${level.toUpperCase()}] ${message}`;\n}\n\nexport const logger = {\n debug: (message: string, ...args: unknown[]): void => {\n if (!debugEnabled) return;\n console.log(formatMessage(\"debug\", message), ...args);\n },\n\n info: (message: string, ...args: unknown[]): void => {\n if (!debugEnabled) return;\n console.info(formatMessage(\"info\", message), ...args);\n },\n\n warn: (message: string, ...args: unknown[]): void => {\n if (!debugEnabled) return;\n console.warn(formatMessage(\"warn\", message), ...args);\n },\n\n error: (message: string, ...args: unknown[]): void => {\n // Always show errors\n console.error(formatMessage(\"error\", message), ...args);\n },\n\n group: (label: string): void => {\n if (!debugEnabled) return;\n console.group(`[tchao.app] ${label}`);\n },\n\n groupEnd: (): void => {\n if (!debugEnabled) return;\n console.groupEnd();\n },\n\n table: (data: unknown): void => {\n if (!debugEnabled) return;\n console.table(data);\n },\n};\n","import { logger, setDebugEnabled } from \"../widget-preact/logger\";\n\nexport 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 debug?: boolean;\n /** When true, disables identify/setMetadata to prevent data pollution during impersonation */\n impersonate?: boolean;\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 setMetadata: (metadata: Record<string, unknown>) => 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 setMetadata: (metadata: Record<string, unknown>) => 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;\nlet impersonateMode = false;\n\ntype QueuedCall =\n | { type: \"show\" }\n | { type: \"hide\" }\n | { type: \"toggle\" }\n | { type: \"open\"; message?: string }\n | { type: \"identify\"; info: VisitorInfo }\n | { type: \"setMetadata\"; metadata: Record<string, unknown> }\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 \"setMetadata\":\n window.Tchao.setMetadata(call.metadata);\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.debug) {\n setDebugEnabled(true);\n logger.debug(\"Debug mode enabled\");\n }\n\n if (config.impersonate) {\n impersonateMode = true;\n logger.debug(\"Impersonate mode enabled - identify/setMetadata will be disabled\");\n }\n\n logger.debug(\"init() called\", { websiteId: config.websiteId, host: config.host });\n\n if (!config.websiteId) {\n throw new Error(\"websiteId is required\");\n }\n\n if (initialized && window.Tchao && currentInstance) {\n logger.debug(\"Already initialized, returning existing instance\");\n return currentInstance;\n }\n\n logger.debug(\"Loading widget script...\");\n await loadScript(config);\n logger.debug(\"Widget script loaded, waiting for Tchao...\");\n await waitForTchao();\n logger.debug(\"Tchao ready\");\n\n if (!window.Tchao) {\n throw new Error(\"Tchao widget failed to initialize\");\n }\n\n initialized = true;\n currentInstance = createInstance();\n logger.debug(\"Flushing queued calls...\", { queueLength: callQueue.length });\n flushQueue();\n logger.debug(\"Init complete\");\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 setMetadata: (metadata: Record<string, unknown>) => {\n try {\n window.Tchao?.setMetadata(metadata);\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 * Disabled when impersonate mode is enabled.\n */\n identify: (info: VisitorInfo): void => {\n if (impersonateMode) {\n logger.debug(\"identify() blocked - impersonate mode is enabled\");\n return;\n }\n logger.debug(\"identify() called\", info);\n logger.debug(\"window.Tchao exists:\", !!window.Tchao);\n if (window.Tchao) {\n logger.debug(\"calling window.Tchao.identify()\");\n safeCall(() => window.Tchao?.identify(info), undefined);\n } else {\n logger.debug(\"window.Tchao not ready, queuing call\");\n callQueue.push({ type: \"identify\", info });\n }\n },\n\n /**\n * Set custom metadata for the visitor. Safe to call before init.\n * Disabled when impersonate mode is enabled.\n */\n setMetadata: (metadata: Record<string, unknown>): void => {\n if (impersonateMode) {\n logger.debug(\"setMetadata() blocked - impersonate mode is enabled\");\n return;\n }\n logger.debug(\"setMetadata() called\", metadata);\n if (window.Tchao) {\n safeCall(() => window.Tchao?.setMetadata(metadata), undefined);\n } else {\n callQueue.push({ type: \"setMetadata\", metadata });\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","useMemo","debugEnabled","setDebugEnabled","enabled","formatMessage","level","message","logger","args","debugEnabled","label","data","WIDGET_SCRIPT_URL","scriptLoaded","scriptPromise","initialized","currentInstance","impersonateMode","callQueue","flushQueue","call","loadScript","config","resolve","reject","script","waitForTchao","attempts","check","init","setDebugEnabled","logger","createInstance","message","info","metadata","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","setMetadata","metadata","config","on","event","callback","off","TchaoProvider","visitorEmail","visitorName","visitorAvatar","visitorId","visitorRole","visitorPhone","visitorCompany","visitorMetadata","onReady","onError","visitorInfo","useMemo"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tchao",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "JavaScript SDK for Tchao chat widget",
|
|
5
5
|
"main": "./dist/npm.js",
|
|
6
6
|
"module": "./dist/npm.mjs",
|
|
@@ -40,8 +40,10 @@
|
|
|
40
40
|
}
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
+
"@release-it/conventional-changelog": "^10.0.1",
|
|
43
44
|
"@types/react": "^19.1.8",
|
|
44
45
|
"react": "^19.1.0",
|
|
46
|
+
"release-it": "^19.0.4",
|
|
45
47
|
"tsup": "^8.5.0",
|
|
46
48
|
"typescript": "^5.9.3"
|
|
47
49
|
},
|
|
@@ -53,8 +55,6 @@
|
|
|
53
55
|
"build": "tsup",
|
|
54
56
|
"dev": "tsup --watch",
|
|
55
57
|
"typecheck": "tsc --noEmit",
|
|
56
|
-
"release
|
|
57
|
-
"release:minor": "npm version minor && pnpm publish --access public",
|
|
58
|
-
"release:major": "npm version major && pnpm publish --access public"
|
|
58
|
+
"release": "release-it"
|
|
59
59
|
}
|
|
60
60
|
}
|