@characterxyz/react 0.6.0 → 0.7.1
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/dist/index.d.ts +13 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
+
import * as _characterxyz_web from '@characterxyz/web';
|
|
2
3
|
import { CharacterXYZ, CxError, ChatMessage, CallState, Call, InitOptions } from '@characterxyz/web';
|
|
3
4
|
export { Call, CallState, ChatMessage, CxError } from '@characterxyz/web';
|
|
4
5
|
import { MountOptions } from '@characterxyz/widget';
|
|
@@ -20,6 +21,12 @@ interface CharacterXYZWidgetProps extends MountOptions {
|
|
|
20
21
|
interface CharacterXYZWidgetRef {
|
|
21
22
|
open(view?: 'chat' | 'call'): void;
|
|
22
23
|
close(): void;
|
|
24
|
+
track(name: string, data?: Record<string, unknown>, opts?: {
|
|
25
|
+
id?: string;
|
|
26
|
+
}): Promise<_characterxyz_web.TrackResult> | undefined;
|
|
27
|
+
identify(visitor: _characterxyz_web.VisitorIdentity): Promise<void> | undefined;
|
|
28
|
+
setContext(context: Record<string, unknown>): Promise<void> | undefined;
|
|
29
|
+
registerAction(name: string, handler: _characterxyz_web.ClientActionHandler): (() => void) | undefined;
|
|
23
30
|
}
|
|
24
31
|
/**
|
|
25
32
|
* The ready-made widget. Renders nothing in your tree: the widget lives in
|
|
@@ -34,6 +41,12 @@ interface UseCharacterXYZ {
|
|
|
34
41
|
send(text: string): Promise<void>;
|
|
35
42
|
call: CallState | null;
|
|
36
43
|
startCall(): Promise<Call | null>;
|
|
44
|
+
track(name: string, data?: Record<string, unknown>, opts?: {
|
|
45
|
+
id?: string;
|
|
46
|
+
}): Promise<_characterxyz_web.TrackResult | null>;
|
|
47
|
+
identify(visitor: _characterxyz_web.VisitorIdentity): Promise<void>;
|
|
48
|
+
setContext(context: Record<string, unknown>): Promise<void>;
|
|
49
|
+
registerAction(name: string, handler: _characterxyz_web.ClientActionHandler): () => void;
|
|
37
50
|
}
|
|
38
51
|
/** The headless SDK as React state, for brands building their own UI. */
|
|
39
52
|
declare function useCharacterXYZ(options: InitOptions): UseCharacterXYZ;
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import{CharacterXYZ as
|
|
2
|
+
import{CharacterXYZ as w}from"@characterxyz/web";import{mount as E}from"@characterxyz/widget";import{forwardRef as b,useEffect as v,useImperativeHandle as R,useRef as m,useState as h}from"react";var k=b(function(r,g){let o=m(null),i=m(r);return i.current=r,R(g,()=>({open:n=>o.current?.open(n),close:()=>o.current?.close(),track:(n,c,d)=>o.current?.track(n,c,d),identify:n=>o.current?.identify(n),setContext:n=>o.current?.setContext(n),registerAction:(n,c)=>o.current?.registerAction(n,c)})),v(()=>{let{onReady:n,onOpen:c,onClose:d,onError:f,...p}=i.current,u=E(p);o.current=u;let C=u.element,e=(t,a)=>{let y=x=>a(x);return C.addEventListener(t,y),()=>C.removeEventListener(t,y)},s=[e("cx-ready",t=>i.current.onReady?.(t.detail)),e("cx-open",t=>i.current.onOpen?.(t.detail.view)),e("cx-close",()=>i.current.onClose?.()),e("cx-error",t=>i.current.onError?.(t.detail))];return()=>{s.forEach(t=>t()),u.destroy(),o.current=null}},[r.publishableKey,r.agentId,r.apiUrl]),null});function P(l){let[r,g]=h(null),[o,i]=h(null),[n,c]=h([]),[d,f]=h(!1),[p,u]=h(null),C=m(l);return C.current=l,v(()=>{let e=!1,s=null,t=[];return w.init(C.current).then(a=>{if(e)return a.destroy();s=a,g(a),t.push(a.chat.on("messages",c),a.chat.on("busy",f)),t.push(a.on("call",y=>{y&&t.push(y.on("state",u))})),a.chat.load().catch(()=>{})},a=>!e&&i(a)),()=>{e=!0,t.forEach(a=>a()),s?.destroy()}},[l.publishableKey,l.agentId,l.apiUrl]),{client:r,error:o,messages:n,busy:d,call:p,send:async e=>{await r?.chat.send(e)},startCall:async()=>r?r.startCall():null,track:async(e,s,t)=>r?r.track(e,s,t):null,identify:async e=>{await r?.identify(e)},setContext:async e=>{await r?.setContext(e)},registerAction:(e,s)=>r?.registerAction(e,s)??(()=>{})}}export{k as CharacterXYZWidget,P as useCharacterXYZ};
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx"],"sourcesContent":["/**\n * `@characterxyz/react`\n *\n * ```tsx\n * import { CharacterXYZWidget } from '@characterxyz/react';\n *\n * <CharacterXYZWidget publishableKey=\"cxyz_pk_live_…\" accent=\"#e11d48\" onReady={(a) => track(a)} />\n * ```\n *\n * Or build your own UI on the headless SDK:\n *\n * ```tsx\n * const { client, messages, send, startCall, call } = useCharacterXYZ({ publishableKey });\n * ```\n */\nimport { CharacterXYZ, type Call, type CallState, type ChatMessage, type CxError, type InitOptions } from '@characterxyz/web';\nimport { mount, type MountOptions, type WidgetHandle } from '@characterxyz/widget';\nimport { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';\n\nexport interface CharacterXYZWidgetProps extends MountOptions {\n onReady?: (detail: { agent: { id: string; name: string } }) => void;\n onOpen?: (view: 'chat' | 'call') => void;\n onClose?: () => void;\n onError?: (detail: { code: string; message: string }) => void;\n}\n\nexport interface CharacterXYZWidgetRef {\n open(view?: 'chat' | 'call'): void;\n close(): void;\n}\n\n/**\n * The ready-made widget. Renders nothing in your tree: the widget lives in\n * its own element at the end of <body>. Re-mounts when the key or agent changes.\n */\nexport const CharacterXYZWidget = forwardRef<CharacterXYZWidgetRef, CharacterXYZWidgetProps>(function CharacterXYZWidget(props, ref) {\n const handle = useRef<WidgetHandle | null>(null);\n const latest = useRef(props);\n latest.current = props;\n\n useImperativeHandle(ref, () => ({\n open: (v) => handle.current?.open(v),\n close: () => handle.current?.close(),\n }));\n\n useEffect(() => {\n const { onReady, onOpen, onClose, onError, ...opts } = latest.current;\n void onReady;\n void onOpen;\n void onClose;\n void onError;\n const w = mount(opts);\n handle.current = w;\n const el = w.element;\n const on = (name: string, fn: (e: CustomEvent) => void) => {\n const h = (e: Event) => fn(e as CustomEvent);\n el.addEventListener(name, h);\n return () => el.removeEventListener(name, h);\n };\n const offs = [\n on('cx-ready', (e) => latest.current.onReady?.(e.detail)),\n on('cx-open', (e) => latest.current.onOpen?.(e.detail.view)),\n on('cx-close', () => latest.current.onClose?.()),\n on('cx-error', (e) => latest.current.onError?.(e.detail)),\n ];\n return () => {\n offs.forEach((f) => f());\n w.destroy();\n handle.current = null;\n };\n // The widget's look is read at mount; a new key or agent is a new widget.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [props.publishableKey, props.agentId, props.apiUrl]);\n\n return null;\n});\n\nexport interface UseCharacterXYZ {\n client: CharacterXYZ | null;\n error: CxError | null;\n messages: readonly ChatMessage[];\n busy: boolean;\n send(text: string): Promise<void>;\n call: CallState | null;\n startCall(): Promise<Call | null>;\n}\n\n/** The headless SDK as React state, for brands building their own UI. */\nexport function useCharacterXYZ(options: InitOptions): UseCharacterXYZ {\n const [client, setClient] = useState<CharacterXYZ | null>(null);\n const [error, setError] = useState<CxError | null>(null);\n const [messages, setMessages] = useState<readonly ChatMessage[]>([]);\n const [busy, setBusy] = useState(false);\n const [call, setCall] = useState<CallState | null>(null);\n const opts = useRef(options);\n opts.current = options;\n\n useEffect(() => {\n let cancelled = false;\n let c: CharacterXYZ | null = null;\n const offs: Array<() => void> = [];\n CharacterXYZ.init(opts.current).then(\n (cl) => {\n if (cancelled) return cl.destroy();\n c = cl;\n setClient(cl);\n offs.push(cl.chat.on('messages', setMessages), cl.chat.on('busy', setBusy));\n offs.push(\n cl.on('call', (k) => {\n if (k) offs.push(k.on('state', setCall));\n }),\n );\n void cl.chat.load().catch(() => {});\n },\n (e) => !cancelled && setError(e),\n );\n return () => {\n cancelled = true;\n offs.forEach((f) => f());\n c?.destroy();\n };\n }, [options.publishableKey, options.agentId, options.apiUrl]);\n\n return {\n client,\n error,\n messages,\n busy,\n call,\n send: async (text) => {\n await client?.chat.send(text);\n },\n startCall: async () => (client ? client.startCall() : null),\n };\n}\n\nexport type { Call, CallState, ChatMessage, CxError } from '@characterxyz/web';\n"],"mappings":";AAeA,OAAS,gBAAAA,MAAiG,oBAC1G,OAAS,SAAAC,MAAmD,uBAC5D,OAAS,cAAAC,EAAY,aAAAC,EAAW,uBAAAC,EAAqB,UAAAC,EAAQ,YAAAC,MAAgB,
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx"],"sourcesContent":["/**\n * `@characterxyz/react`\n *\n * ```tsx\n * import { CharacterXYZWidget } from '@characterxyz/react';\n *\n * <CharacterXYZWidget publishableKey=\"cxyz_pk_live_…\" accent=\"#e11d48\" onReady={(a) => track(a)} />\n * ```\n *\n * Or build your own UI on the headless SDK:\n *\n * ```tsx\n * const { client, messages, send, startCall, call } = useCharacterXYZ({ publishableKey });\n * ```\n */\nimport { CharacterXYZ, type Call, type CallState, type ChatMessage, type CxError, type InitOptions } from '@characterxyz/web';\nimport { mount, type MountOptions, type WidgetHandle } from '@characterxyz/widget';\nimport { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';\n\nexport interface CharacterXYZWidgetProps extends MountOptions {\n onReady?: (detail: { agent: { id: string; name: string } }) => void;\n onOpen?: (view: 'chat' | 'call') => void;\n onClose?: () => void;\n onError?: (detail: { code: string; message: string }) => void;\n}\n\nexport interface CharacterXYZWidgetRef {\n open(view?: 'chat' | 'call'): void;\n close(): void;\n track(name: string, data?: Record<string, unknown>, opts?: { id?: string }): Promise<import('@characterxyz/web').TrackResult> | undefined;\n identify(visitor: import('@characterxyz/web').VisitorIdentity): Promise<void> | undefined;\n setContext(context: Record<string, unknown>): Promise<void> | undefined;\n registerAction(name: string, handler: import('@characterxyz/web').ClientActionHandler): (() => void) | undefined;\n}\n\n/**\n * The ready-made widget. Renders nothing in your tree: the widget lives in\n * its own element at the end of <body>. Re-mounts when the key or agent changes.\n */\nexport const CharacterXYZWidget = forwardRef<CharacterXYZWidgetRef, CharacterXYZWidgetProps>(function CharacterXYZWidget(props, ref) {\n const handle = useRef<WidgetHandle | null>(null);\n const latest = useRef(props);\n latest.current = props;\n\n useImperativeHandle(ref, () => ({\n open: (v) => handle.current?.open(v),\n close: () => handle.current?.close(),\n track: (n, d, o) => handle.current?.track(n, d, o),\n identify: (v) => handle.current?.identify(v),\n setContext: (c) => handle.current?.setContext(c),\n registerAction: (n, h) => handle.current?.registerAction(n, h),\n }));\n\n useEffect(() => {\n const { onReady, onOpen, onClose, onError, ...opts } = latest.current;\n void onReady;\n void onOpen;\n void onClose;\n void onError;\n const w = mount(opts);\n handle.current = w;\n const el = w.element;\n const on = (name: string, fn: (e: CustomEvent) => void) => {\n const h = (e: Event) => fn(e as CustomEvent);\n el.addEventListener(name, h);\n return () => el.removeEventListener(name, h);\n };\n const offs = [\n on('cx-ready', (e) => latest.current.onReady?.(e.detail)),\n on('cx-open', (e) => latest.current.onOpen?.(e.detail.view)),\n on('cx-close', () => latest.current.onClose?.()),\n on('cx-error', (e) => latest.current.onError?.(e.detail)),\n ];\n return () => {\n offs.forEach((f) => f());\n w.destroy();\n handle.current = null;\n };\n // The widget's look is read at mount; a new key or agent is a new widget.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [props.publishableKey, props.agentId, props.apiUrl]);\n\n return null;\n});\n\nexport interface UseCharacterXYZ {\n client: CharacterXYZ | null;\n error: CxError | null;\n messages: readonly ChatMessage[];\n busy: boolean;\n send(text: string): Promise<void>;\n call: CallState | null;\n startCall(): Promise<Call | null>;\n track(name: string, data?: Record<string, unknown>, opts?: { id?: string }): Promise<import('@characterxyz/web').TrackResult | null>;\n identify(visitor: import('@characterxyz/web').VisitorIdentity): Promise<void>;\n setContext(context: Record<string, unknown>): Promise<void>;\n registerAction(name: string, handler: import('@characterxyz/web').ClientActionHandler): () => void;\n}\n\n/** The headless SDK as React state, for brands building their own UI. */\nexport function useCharacterXYZ(options: InitOptions): UseCharacterXYZ {\n const [client, setClient] = useState<CharacterXYZ | null>(null);\n const [error, setError] = useState<CxError | null>(null);\n const [messages, setMessages] = useState<readonly ChatMessage[]>([]);\n const [busy, setBusy] = useState(false);\n const [call, setCall] = useState<CallState | null>(null);\n const opts = useRef(options);\n opts.current = options;\n\n useEffect(() => {\n let cancelled = false;\n let c: CharacterXYZ | null = null;\n const offs: Array<() => void> = [];\n CharacterXYZ.init(opts.current).then(\n (cl) => {\n if (cancelled) return cl.destroy();\n c = cl;\n setClient(cl);\n offs.push(cl.chat.on('messages', setMessages), cl.chat.on('busy', setBusy));\n offs.push(\n cl.on('call', (k) => {\n if (k) offs.push(k.on('state', setCall));\n }),\n );\n void cl.chat.load().catch(() => {});\n },\n (e) => !cancelled && setError(e),\n );\n return () => {\n cancelled = true;\n offs.forEach((f) => f());\n c?.destroy();\n };\n }, [options.publishableKey, options.agentId, options.apiUrl]);\n\n return {\n client,\n error,\n messages,\n busy,\n call,\n send: async (text) => {\n await client?.chat.send(text);\n },\n startCall: async () => (client ? client.startCall() : null),\n track: async (name, data, opts) => (client ? client.track(name, data, opts) : null),\n identify: async (visitor) => {\n await client?.identify(visitor);\n },\n setContext: async (context) => {\n await client?.setContext(context);\n },\n registerAction: (name, handler) => client?.registerAction(name, handler) ?? (() => {}),\n };\n}\n\nexport type { Call, CallState, ChatMessage, CxError } from '@characterxyz/web';\n"],"mappings":"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","names":["CharacterXYZ","mount","forwardRef","useEffect","useImperativeHandle","useRef","useState","CharacterXYZWidget","props","ref","handle","latest","v","d","o","c","h","onReady","onOpen","onClose","onError","opts","w","el","on","name","fn","e","offs","f","useCharacterXYZ","options","client","setClient","error","setError","messages","setMessages","busy","setBusy","call","setCall","cancelled","cl","k","text","data","visitor","context","handler"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@characterxyz/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "Character XYZ for React: the widget as a component, and hooks over the headless SDK.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"react": ">=17"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@characterxyz/web": "^0.
|
|
28
|
-
"@characterxyz/widget": "^0.
|
|
27
|
+
"@characterxyz/web": "^0.7.1",
|
|
28
|
+
"@characterxyz/widget": "^0.7.1"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/react": "^19.3.0",
|