@xpert-ai/chatkit-react 0.11.1 → 0.12.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 CHANGED
@@ -5,7 +5,7 @@ import { XpertAIChatKit } from '../../chatkit/src/index.ts';
5
5
 
6
6
  export declare const ChatKit: React_2.ForwardRefExoticComponent<ChatKitProps & React_2.RefAttributes<XpertAIChatKit>>;
7
7
 
8
- declare const CHATKIT_METHOD_NAMES: readonly ["focusComposer", "setThreadId", "sendUserMessage", "setComposerValue", "setRuntimeCapabilities", "fetchUpdates", "sendCustomAction"];
8
+ declare const CHATKIT_METHOD_NAMES: readonly ["focusComposer", "setThreadId", "focusMessage", "sendUserMessage", "setComposerValue", "setRuntimeCapabilities", "fetchUpdates", "sendCustomAction"];
9
9
 
10
10
  declare type ChatKitControl = {
11
11
  setInstance: (instance: XpertAIChatKit | null) => void;
package/dist/index.js CHANGED
@@ -93,6 +93,7 @@ function useStableOptions(options) {
93
93
  const CHATKIT_METHOD_NAMES = Object.freeze([
94
94
  "focusComposer",
95
95
  "setThreadId",
96
+ "focusMessage",
96
97
  "sendUserMessage",
97
98
  "setComposerValue",
98
99
  "setRuntimeCapabilities",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/useStableOptions.ts","../src/useChatKit.ts","../src/chatkit.tsx"],"sourcesContent":["import React from 'react';\n\nfunction isPlainObjectOrArray(\n obj: unknown,\n): obj is Record<string, unknown> | unknown[] {\n return (\n (obj !== null &&\n typeof obj === 'object' &&\n [null, Object.prototype].includes(Object.getPrototypeOf(obj))) ||\n Array.isArray(obj)\n );\n}\n\nexport function deepEqualIgnoringFns(\n a: unknown,\n b: unknown,\n seen = new WeakMap<WeakKey, unknown>(),\n): boolean {\n if (Object.is(a, b)) return true;\n\n // Functions: ignore identity/body differences entirely\n if (typeof a === 'function' && typeof b === 'function') {\n return typeof a === typeof b;\n }\n\n if (!isPlainObjectOrArray(a) || !isPlainObjectOrArray(b)) {\n return false;\n }\n\n // Cycles\n const mapped = seen.get(a);\n if (mapped && mapped === b) return true;\n seen.set(a, b);\n\n // Arrays\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length)\n return false;\n for (let i = 0; i < a.length; i++) {\n if (!deepEqualIgnoringFns(a[i], b[i], seen)) return false;\n }\n return true;\n }\n\n // Plain objects (Maps/Sets/Dates: treat as unequal unless same ref)\n const aKeys = Object.keys(a);\n const bKeys = Object.keys(b);\n if (aKeys.length !== bKeys.length) return false;\n\n for (let i = 0; i < aKeys.length; i++) {\n const k = aKeys[i];\n if (!Object.prototype.hasOwnProperty.call(b, k)) return false;\n\n const av = (a as Record<string, unknown>)[k];\n const bv = (b as Record<string, unknown>)[k];\n\n if (!deepEqualIgnoringFns(av, bv, seen)) return false;\n }\n\n return true;\n}\n\nexport function withLatestFunctionWrappers<T extends Record<string, any>>(ref: {\n current: T;\n}): T {\n const path: (string | number)[] = [];\n\n const getByPath = (root: any, p: (string | number)[]) =>\n p.reduce((acc, k) => (acc == null ? acc : acc[k]), root);\n\n const wrap = (parentPath: (string | number)[], key: string | number) => {\n return (...args: any[]) => {\n const latestParent = getByPath(ref.current, parentPath);\n const latestFn: any = latestParent?.[key];\n if (typeof latestFn === 'function') {\n return latestFn.apply(latestParent, args);\n }\n };\n };\n\n const visit = (v: any): any => {\n if (typeof v === 'function') {\n const key = path[path.length - 1];\n const parentPath = path.slice(0, -1);\n return wrap(parentPath, key);\n }\n if (Array.isArray(v)) {\n const base = path.length;\n const out = new Array(v.length);\n for (let i = 0; i < v.length; i++) {\n path[base] = i;\n out[i] = visit(v[i]);\n }\n path.length = base;\n return out as any;\n }\n if (v && typeof v === 'object') {\n const base = path.length;\n const out: Record<string, any> = {};\n for (const k of Object.keys(v)) {\n path[base] = k;\n out[k] = visit(v[k]);\n }\n path.length = base;\n return out as any;\n }\n return v;\n };\n\n return visit(ref.current);\n}\n\nexport function useStableOptions<T extends Record<string, any>>(options: T): T {\n const latestOptions = React.useRef(options);\n latestOptions.current = options;\n const cache = React.useRef<{ snapshot: T; shaped: T } | null>(null);\n\n if (\n !cache.current ||\n !deepEqualIgnoringFns(cache.current.snapshot, options)\n ) {\n cache.current = {\n snapshot: options,\n shaped: withLatestFunctionWrappers(latestOptions),\n };\n }\n\n return cache.current.shaped;\n}\n","import * as React from 'react';\nimport { ChatKitEvents, ChatKitOptions, XpertAIChatKit } from '@xpert-ai/chatkit-types';\nimport { useStableOptions } from './useStableOptions';\n\n\ntype DotToCamelCase<S extends string> = S extends `${infer Head}.${infer Tail}`\n ? `${Head}${Capitalize<DotToCamelCase<Tail>>}`\n : S;\n\nconst CHATKIT_METHOD_NAMES = Object.freeze([\n 'focusComposer',\n 'setThreadId',\n 'sendUserMessage',\n 'setComposerValue',\n 'setRuntimeCapabilities',\n 'fetchUpdates',\n 'sendCustomAction',\n] as const);\n\ntype ChatKitMethod = (typeof CHATKIT_METHOD_NAMES)[number];\n\ntype ChatKitMethods = {\n [K in ChatKitMethod]: XpertAIChatKit[K];\n};\n\nexport type ToEventHandlerKey<K extends keyof ChatKitEvents> =\n DotToCamelCase<K> extends `chatkit${infer EventName}`\n ? `on${Capitalize<EventName>}`\n : never;\nexport type ChatKitEventHandlers = Partial<{\n [K in keyof ChatKitEvents as ToEventHandlerKey<K>]: ChatKitEvents[K] extends CustomEvent<\n infer Detail\n >\n ? Detail extends undefined\n ? () => void\n : (event: Detail) => void\n : never;\n}>;\n\nexport type UseChatKitOptions = ChatKitOptions & ChatKitEventHandlers;\n\nexport type ChatKitControl = {\n setInstance: (instance: XpertAIChatKit | null) => void;\n options: ChatKitOptions;\n handlers: ChatKitEventHandlers;\n};\n\nexport type UseChatKitReturn = ChatKitMethods & {\n control: ChatKitControl;\n ref: React.RefObject<XpertAIChatKit | null>;\n};\n\n\nexport function useChatKit(options: UseChatKitOptions): UseChatKitReturn {\n const ref = React.useRef<XpertAIChatKit | null>(null);\n const stableOptions = useStableOptions(options);\n\n const methods: ChatKitMethods = React.useMemo(() => {\n return CHATKIT_METHOD_NAMES.reduce((acc, key) => {\n acc[key] = (...args: any[]) => {\n if (!ref.current) {\n console.warn('ChatKit element is not mounted');\n return;\n }\n\n return (ref.current as any)[key](...args);\n };\n return acc;\n }, {} as ChatKitMethods);\n }, []);\n\n const setInstance = React.useCallback(\n (instance: XpertAIChatKit | null): void => {\n ref.current = instance;\n },\n [],\n );\n\n const control: ChatKitControl = React.useMemo(() => {\n const options = {} as ChatKitOptions;\n const handlers: ChatKitEventHandlers = {};\n\n for (const [key, value] of Object.entries(stableOptions)) {\n if (/^on[A-Z]/.test(key) && key !== 'onClientTool') {\n // @ts-expect-error - too dynamic for TypeScript\n handlers[key] = value;\n } else {\n // @ts-expect-error - too dynamic for TypeScript\n options[key] = value;\n }\n }\n\n return {\n setInstance,\n options,\n handlers,\n };\n }, [stableOptions, setInstance]);\n\n return React.useMemo(\n () => ({ ...methods, control, ref }),\n [methods, control],\n );\n}\n","import * as React from 'react';\nimport { XpertAIChatKit, ChatKitEvents } from '@xpert-ai/chatkit-types';\n\n// Import web component side effect\nimport '@xpert-ai/chatkit-web-component';\nimport { ChatKitControl, ToEventHandlerKey } from './useChatKit';\n\ndeclare module 'react' {\n namespace JSX {\n interface IntrinsicElements {\n 'xpertai-chatkit': React.DetailedHTMLProps<\n React.HTMLAttributes<XpertAIChatKit>,\n XpertAIChatKit\n >;\n }\n }\n}\n\nexport interface ChatKitProps extends React.HTMLAttributes<XpertAIChatKit> {\n control: ChatKitControl;\n}\n\nconst EVENT_HANDLER_MAP: {\n [K in keyof ChatKitEvents]: ToEventHandlerKey<K>;\n} = {\n 'chatkit.error': 'onError',\n 'chatkit.response.end': 'onResponseEnd',\n 'chatkit.response.start': 'onResponseStart',\n 'chatkit.log': 'onLog',\n 'chatkit.thread.change': 'onThreadChange',\n 'chatkit.project.change': 'onProjectChange',\n 'chatkit.connectors.change': 'onConnectorsChange',\n 'chatkit.thread.load.start': 'onThreadLoadStart',\n 'chatkit.thread.load.end': 'onThreadLoadEnd',\n 'chatkit.ready': 'onReady',\n 'chatkit.effect': 'onEffect',\n};\n\nconst EVENT_NAMES = Object.keys(EVENT_HANDLER_MAP) as (keyof ChatKitEvents)[];\n\nexport const ChatKit = React.forwardRef<XpertAIChatKit, ChatKitProps>(\n function ChatKit({ control, ...htmlProps }, forwardedRef) {\n const ref = React.useRef<XpertAIChatKit | null>(null);\n\n React.useLayoutEffect(() => {\n const el = ref.current;\n if (!el) return;\n\n // Fast path: element is already defined\n if (customElements.get('xpertai-chatkit')) {\n el.setOptions(control.options);\n return;\n }\n // Fallback path: wait for definition\n let active = true;\n customElements.whenDefined('xpertai-chatkit').then(() => {\n if (active) {\n el.setOptions(control.options);\n }\n });\n return () => {\n active = false;\n };\n }, [control.options]);\n\n React.useEffect(() => {\n const el = ref.current;\n if (!el) return;\n\n const controller = new AbortController();\n for (const eventName of EVENT_NAMES) {\n el.addEventListener(\n eventName,\n (e) => {\n const handlerName = EVENT_HANDLER_MAP[eventName];\n const handler = control.handlers[handlerName];\n if (typeof handler === 'function') {\n handler(e.detail as any);\n }\n },\n { signal: controller.signal },\n );\n }\n return () => {\n controller.abort();\n };\n }, [control.handlers]);\n\n return (\n <xpertai-chatkit\n ref={(chatKit) => {\n ref.current = chatKit;\n\n control.setInstance(chatKit);\n\n if (typeof forwardedRef === 'function') {\n forwardedRef(chatKit);\n } else if (forwardedRef) {\n forwardedRef.current = chatKit;\n }\n\n if (!ref.current) {\n return;\n }\n }}\n {...htmlProps}\n />\n );\n },\n);\n"],"names":["React","options","ChatKit"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/useStableOptions.ts","../src/useChatKit.ts","../src/chatkit.tsx"],"sourcesContent":["import React from 'react';\n\nfunction isPlainObjectOrArray(\n obj: unknown,\n): obj is Record<string, unknown> | unknown[] {\n return (\n (obj !== null &&\n typeof obj === 'object' &&\n [null, Object.prototype].includes(Object.getPrototypeOf(obj))) ||\n Array.isArray(obj)\n );\n}\n\nexport function deepEqualIgnoringFns(\n a: unknown,\n b: unknown,\n seen = new WeakMap<WeakKey, unknown>(),\n): boolean {\n if (Object.is(a, b)) return true;\n\n // Functions: ignore identity/body differences entirely\n if (typeof a === 'function' && typeof b === 'function') {\n return typeof a === typeof b;\n }\n\n if (!isPlainObjectOrArray(a) || !isPlainObjectOrArray(b)) {\n return false;\n }\n\n // Cycles\n const mapped = seen.get(a);\n if (mapped && mapped === b) return true;\n seen.set(a, b);\n\n // Arrays\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length)\n return false;\n for (let i = 0; i < a.length; i++) {\n if (!deepEqualIgnoringFns(a[i], b[i], seen)) return false;\n }\n return true;\n }\n\n // Plain objects (Maps/Sets/Dates: treat as unequal unless same ref)\n const aKeys = Object.keys(a);\n const bKeys = Object.keys(b);\n if (aKeys.length !== bKeys.length) return false;\n\n for (let i = 0; i < aKeys.length; i++) {\n const k = aKeys[i];\n if (!Object.prototype.hasOwnProperty.call(b, k)) return false;\n\n const av = (a as Record<string, unknown>)[k];\n const bv = (b as Record<string, unknown>)[k];\n\n if (!deepEqualIgnoringFns(av, bv, seen)) return false;\n }\n\n return true;\n}\n\nexport function withLatestFunctionWrappers<T extends Record<string, any>>(ref: {\n current: T;\n}): T {\n const path: (string | number)[] = [];\n\n const getByPath = (root: any, p: (string | number)[]) =>\n p.reduce((acc, k) => (acc == null ? acc : acc[k]), root);\n\n const wrap = (parentPath: (string | number)[], key: string | number) => {\n return (...args: any[]) => {\n const latestParent = getByPath(ref.current, parentPath);\n const latestFn: any = latestParent?.[key];\n if (typeof latestFn === 'function') {\n return latestFn.apply(latestParent, args);\n }\n };\n };\n\n const visit = (v: any): any => {\n if (typeof v === 'function') {\n const key = path[path.length - 1];\n const parentPath = path.slice(0, -1);\n return wrap(parentPath, key);\n }\n if (Array.isArray(v)) {\n const base = path.length;\n const out = new Array(v.length);\n for (let i = 0; i < v.length; i++) {\n path[base] = i;\n out[i] = visit(v[i]);\n }\n path.length = base;\n return out as any;\n }\n if (v && typeof v === 'object') {\n const base = path.length;\n const out: Record<string, any> = {};\n for (const k of Object.keys(v)) {\n path[base] = k;\n out[k] = visit(v[k]);\n }\n path.length = base;\n return out as any;\n }\n return v;\n };\n\n return visit(ref.current);\n}\n\nexport function useStableOptions<T extends Record<string, any>>(options: T): T {\n const latestOptions = React.useRef(options);\n latestOptions.current = options;\n const cache = React.useRef<{ snapshot: T; shaped: T } | null>(null);\n\n if (\n !cache.current ||\n !deepEqualIgnoringFns(cache.current.snapshot, options)\n ) {\n cache.current = {\n snapshot: options,\n shaped: withLatestFunctionWrappers(latestOptions),\n };\n }\n\n return cache.current.shaped;\n}\n","import * as React from 'react';\nimport {\n ChatKitEvents,\n ChatKitOptions,\n XpertAIChatKit,\n} from '@xpert-ai/chatkit-types';\nimport { useStableOptions } from './useStableOptions';\n\ntype DotToCamelCase<S extends string> = S extends `${infer Head}.${infer Tail}`\n ? `${Head}${Capitalize<DotToCamelCase<Tail>>}`\n : S;\n\nconst CHATKIT_METHOD_NAMES = Object.freeze([\n 'focusComposer',\n 'setThreadId',\n 'focusMessage',\n 'sendUserMessage',\n 'setComposerValue',\n 'setRuntimeCapabilities',\n 'fetchUpdates',\n 'sendCustomAction',\n] as const);\n\ntype ChatKitMethod = (typeof CHATKIT_METHOD_NAMES)[number];\n\ntype ChatKitMethods = {\n [K in ChatKitMethod]: XpertAIChatKit[K];\n};\n\nexport type ToEventHandlerKey<K extends keyof ChatKitEvents> =\n DotToCamelCase<K> extends `chatkit${infer EventName}`\n ? `on${Capitalize<EventName>}`\n : never;\nexport type ChatKitEventHandlers = Partial<{\n [K in keyof ChatKitEvents as ToEventHandlerKey<K>]: ChatKitEvents[K] extends CustomEvent<\n infer Detail\n >\n ? Detail extends undefined\n ? () => void\n : (event: Detail) => void\n : never;\n}>;\n\nexport type UseChatKitOptions = ChatKitOptions & ChatKitEventHandlers;\n\nexport type ChatKitControl = {\n setInstance: (instance: XpertAIChatKit | null) => void;\n options: ChatKitOptions;\n handlers: ChatKitEventHandlers;\n};\n\nexport type UseChatKitReturn = ChatKitMethods & {\n control: ChatKitControl;\n ref: React.RefObject<XpertAIChatKit | null>;\n};\n\nexport function useChatKit(options: UseChatKitOptions): UseChatKitReturn {\n const ref = React.useRef<XpertAIChatKit | null>(null);\n const stableOptions = useStableOptions(options);\n\n const methods: ChatKitMethods = React.useMemo(() => {\n return CHATKIT_METHOD_NAMES.reduce((acc, key) => {\n acc[key] = (...args: any[]) => {\n if (!ref.current) {\n console.warn('ChatKit element is not mounted');\n return;\n }\n\n return (ref.current as any)[key](...args);\n };\n return acc;\n }, {} as ChatKitMethods);\n }, []);\n\n const setInstance = React.useCallback(\n (instance: XpertAIChatKit | null): void => {\n ref.current = instance;\n },\n [],\n );\n\n const control: ChatKitControl = React.useMemo(() => {\n const options = {} as ChatKitOptions;\n const handlers: ChatKitEventHandlers = {};\n\n for (const [key, value] of Object.entries(stableOptions)) {\n if (/^on[A-Z]/.test(key) && key !== 'onClientTool') {\n // @ts-expect-error - too dynamic for TypeScript\n handlers[key] = value;\n } else {\n // @ts-expect-error - too dynamic for TypeScript\n options[key] = value;\n }\n }\n\n return {\n setInstance,\n options,\n handlers,\n };\n }, [stableOptions, setInstance]);\n\n return React.useMemo(\n () => ({ ...methods, control, ref }),\n [methods, control],\n );\n}\n","import * as React from 'react';\nimport { XpertAIChatKit, ChatKitEvents } from '@xpert-ai/chatkit-types';\n\n// Import web component side effect\nimport '@xpert-ai/chatkit-web-component';\nimport { ChatKitControl, ToEventHandlerKey } from './useChatKit';\n\ndeclare module 'react' {\n namespace JSX {\n interface IntrinsicElements {\n 'xpertai-chatkit': React.DetailedHTMLProps<\n React.HTMLAttributes<XpertAIChatKit>,\n XpertAIChatKit\n >;\n }\n }\n}\n\nexport interface ChatKitProps extends React.HTMLAttributes<XpertAIChatKit> {\n control: ChatKitControl;\n}\n\nconst EVENT_HANDLER_MAP: {\n [K in keyof ChatKitEvents]: ToEventHandlerKey<K>;\n} = {\n 'chatkit.error': 'onError',\n 'chatkit.response.end': 'onResponseEnd',\n 'chatkit.response.start': 'onResponseStart',\n 'chatkit.log': 'onLog',\n 'chatkit.thread.change': 'onThreadChange',\n 'chatkit.project.change': 'onProjectChange',\n 'chatkit.connectors.change': 'onConnectorsChange',\n 'chatkit.thread.load.start': 'onThreadLoadStart',\n 'chatkit.thread.load.end': 'onThreadLoadEnd',\n 'chatkit.ready': 'onReady',\n 'chatkit.effect': 'onEffect',\n};\n\nconst EVENT_NAMES = Object.keys(EVENT_HANDLER_MAP) as (keyof ChatKitEvents)[];\n\nexport const ChatKit = React.forwardRef<XpertAIChatKit, ChatKitProps>(\n function ChatKit({ control, ...htmlProps }, forwardedRef) {\n const ref = React.useRef<XpertAIChatKit | null>(null);\n\n React.useLayoutEffect(() => {\n const el = ref.current;\n if (!el) return;\n\n // Fast path: element is already defined\n if (customElements.get('xpertai-chatkit')) {\n el.setOptions(control.options);\n return;\n }\n // Fallback path: wait for definition\n let active = true;\n customElements.whenDefined('xpertai-chatkit').then(() => {\n if (active) {\n el.setOptions(control.options);\n }\n });\n return () => {\n active = false;\n };\n }, [control.options]);\n\n React.useEffect(() => {\n const el = ref.current;\n if (!el) return;\n\n const controller = new AbortController();\n for (const eventName of EVENT_NAMES) {\n el.addEventListener(\n eventName,\n (e) => {\n const handlerName = EVENT_HANDLER_MAP[eventName];\n const handler = control.handlers[handlerName];\n if (typeof handler === 'function') {\n handler(e.detail as any);\n }\n },\n { signal: controller.signal },\n );\n }\n return () => {\n controller.abort();\n };\n }, [control.handlers]);\n\n return (\n <xpertai-chatkit\n ref={(chatKit) => {\n ref.current = chatKit;\n\n control.setInstance(chatKit);\n\n if (typeof forwardedRef === 'function') {\n forwardedRef(chatKit);\n } else if (forwardedRef) {\n forwardedRef.current = chatKit;\n }\n\n if (!ref.current) {\n return;\n }\n }}\n {...htmlProps}\n />\n );\n },\n);\n"],"names":["React","options","ChatKit"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xpert-ai/chatkit-react",
3
- "version": "0.11.1",
3
+ "version": "0.12.1",
4
4
  "description": "React bindings for Xpert Chatkit",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -21,8 +21,8 @@
21
21
  "react-dom": ">=18"
22
22
  },
23
23
  "dependencies": {
24
- "@xpert-ai/chatkit-types": "~0.11.1",
25
- "@xpert-ai/chatkit-web-component": "~0.11.1"
24
+ "@xpert-ai/chatkit-types": "~0.12.1",
25
+ "@xpert-ai/chatkit-web-component": "~0.12.1"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/react": "^18.3.0",