@opencx/widget-react-headless 4.0.10 → 4.0.12

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.
Files changed (39) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +154 -118
  4. package/dist/index.js.map +1 -1
  5. package/dist/src/ComponentRegistry.d.ts +1 -0
  6. package/dist/src/ComponentRegistry.d.ts.map +1 -0
  7. package/dist/src/WidgetProvider.d.ts +1 -0
  8. package/dist/src/WidgetProvider.d.ts.map +1 -0
  9. package/dist/src/hooks/useConfig.d.ts +1 -0
  10. package/dist/src/hooks/useConfig.d.ts.map +1 -0
  11. package/dist/src/hooks/useContact.d.ts +1 -0
  12. package/dist/src/hooks/useContact.d.ts.map +1 -0
  13. package/dist/src/hooks/useCsat.d.ts +28 -0
  14. package/dist/src/hooks/useCsat.d.ts.map +1 -0
  15. package/dist/src/hooks/useDocumentDir.d.ts +1 -0
  16. package/dist/src/hooks/useDocumentDir.d.ts.map +1 -0
  17. package/dist/src/hooks/useIsAwaitingBotReply.d.ts +1 -0
  18. package/dist/src/hooks/useIsAwaitingBotReply.d.ts.map +1 -0
  19. package/dist/src/hooks/useMessages.d.ts +2 -1
  20. package/dist/src/hooks/useMessages.d.ts.map +1 -0
  21. package/dist/src/hooks/useModes.d.ts +1 -0
  22. package/dist/src/hooks/useModes.d.ts.map +1 -0
  23. package/dist/src/hooks/usePreludeData.d.ts +1 -0
  24. package/dist/src/hooks/usePreludeData.d.ts.map +1 -0
  25. package/dist/src/hooks/usePrimitiveState.d.ts +1 -0
  26. package/dist/src/hooks/usePrimitiveState.d.ts.map +1 -0
  27. package/dist/src/hooks/useSessions.d.ts +4 -3
  28. package/dist/src/hooks/useSessions.d.ts.map +1 -0
  29. package/dist/src/hooks/useUploadFiles.d.ts +1 -0
  30. package/dist/src/hooks/useUploadFiles.d.ts.map +1 -0
  31. package/dist/src/hooks/useWidgetRouter.d.ts +1 -0
  32. package/dist/src/hooks/useWidgetRouter.d.ts.map +1 -0
  33. package/dist/src/hooks/useWidgetTrigger.d.ts +1 -0
  34. package/dist/src/hooks/useWidgetTrigger.d.ts.map +1 -0
  35. package/dist/src/index.d.ts +2 -0
  36. package/dist/src/index.d.ts.map +1 -0
  37. package/dist/src/types/components.d.ts +3 -2
  38. package/dist/src/types/components.d.ts.map +1 -0
  39. package/package.json +3 -3
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("react"),E=require("@opencx/widget-core"),F=require("swr"),W=require("uuid"),P="4.0.10";class U{constructor(t){this.components=[];const{components:n}=t;if(n&&n.forEach(o=>this.register(o)),this.components.length===0)throw new Error("No components registered");if(!this.get("fallback"))throw new Error("No fallback component registered")}register(t){const n=this.components.findIndex(o=>o.key===t.key);return n!==-1?this.components[n]=t:this.components.push(t),this}get(t){const n=this.components.find(o=>o.key.toUpperCase()===t.toUpperCase());return n||null}getComponent(t){var n;return(n=this.get(t))==null?void 0:n.component}}const b=i.createContext(null);function M({options:e,children:t,components:n,storage:o,loadingComponent:u}){const c=i.useRef(null),d=i.useRef(!1),[l,C]=i.useState(null),p=i.useMemo(()=>new U({components:n}),[n]);return i.useEffect(()=>{d.current||(d.current=!0,E.WidgetCtx.initialize({config:e,storage:o}).then(C))},[]),l?i.createElement(b.Provider,{value:{widgetCtx:l,config:e,components:n,componentStore:p,version:P,contentIframeRef:c}},t):u||null}function g(){const e=i.useContext(b);if(!e)throw new Error("useWidget must be used within a WidgetProvider");return e}function w(){const{config:e}=g();return e}function m(e){return i.useSyncExternalStore(e.subscribe,e.get,e.get)}function R(){const{widgetCtx:e}=g();return{contactState:m(e.contactCtx.state),createUnverifiedContact:e.contactCtx.createUnverifiedContact}}function A(){const[e,t]=i.useState("ltr");return i.useEffect(()=>{const n=()=>{typeof document>"u"||t(window.getComputedStyle((window.top||window).document.body).direction)};n();const o=new MutationObserver(n);return o.observe(document.documentElement,{attributes:!0,attributeFilter:["dir"]}),o.observe(document.body,{attributes:!0,attributeFilter:["dir"]}),window.addEventListener("languagechange",n),()=>{o.disconnect(),window.removeEventListener("languagechange",n)}},[]),{dir:e}}function y(){const{widgetCtx:e}=g();return{messagesState:m(e.messageCtx.state),sendMessage:e.messageCtx.sendMessage}}function x(){const{widgetCtx:e}=g(),{oneOpenSessionAllowed:t}=w(),n=m(e.sessionCtx.sessionState),o=m(e.sessionCtx.sessionsState),{openSessions:u,closedSessions:c}=i.useMemo(()=>({openSessions:o.data.filter(l=>l.isOpened===!0),closedSessions:o.data.filter(l=>l.isOpened===!1)}),[o.data]),d=i.useMemo(()=>t?u.length===0:!0,[t,u.length]);return{sessionState:n,sessionsState:o,loadMoreSessions:e.sessionCtx.loadMoreSessions,resolveSession:e.sessionCtx.resolveSession,createStateCheckpoint:e.sessionCtx.createStateCheckpoint,openSessions:u,closedSessions:c,canCreateNewSession:d}}function O(){var d;const{sessionState:e}=x(),{messagesState:t}=y(),n=((d=e.session)==null?void 0:d.assignee.kind)==="ai",o=t.messages.length>0?t.messages[t.messages.length-1]:null,u=(o==null?void 0:o.type)==="FROM_USER";return{isAwaitingBotReply:(n||e.isCreatingSession)&&(t.isSendingMessage||u)}}function T(){const{widgetCtx:e}=g();return F([e.config.token],e.api.widgetPrelude,{revalidateOnFocus:!1})}function k(){const{widgetCtx:e}=g();return{routerState:m(e.routerCtx.state),toSessionsScreen:e.routerCtx.toSessionsScreen,toChatScreen:e.routerCtx.toChatScreen}}const f=new Map;function D(){const[e,t]=i.useState([]),{widgetCtx:{api:n}}=g();function o(s){const r=s.map(a=>({file:a,id:W.v4(),status:"pending",progress:0}));t(a=>[...a,...r]),r.forEach(d)}function u(s,r){t(a=>a.map(S=>S.id===s?{...S,...r}:S))}function c(s){t(r=>r.filter(a=>a.id!==s))}const d=async s=>{const r=new AbortController;f.set(s.id,r);try{t(S=>S.map(h=>h.id===s.id?{...h,status:"uploading",progress:0}:h));const a=await n.uploadFile({file:s.file,abortSignal:r.signal,onProgress:S=>{u(s.id,{progress:S})}});u(s.id,{status:"success",fileUrl:a.fileUrl,progress:100})}catch(a){r.signal.aborted||u(s.id,{status:"error",error:a instanceof Error?a.message:"Upload failed",progress:0})}finally{f.delete(s.id)}},l=s=>{const r=f.get(s);r&&(r.abort(),f.delete(s)),c(s)},C=i.useMemo(()=>e.filter(s=>s.status==="success"&&s.fileUrl),[e]);function p(){f.forEach(s=>s.abort()),f.clear(),t([])}return i.useEffect(()=>()=>{f.forEach(s=>s.abort()),f.clear()},[]),{allFiles:e,appendFiles:o,handleCancelUpload:l,successFiles:C,emptyTheFiles:p,getFileById:s=>e.find(r=>r.id===s),getUploadProgress:s=>{var r;return((r=e.find(a=>a.id===s))==null?void 0:r.progress)??0},getUploadStatus:s=>{var r;return(r=e.find(a=>a.id===s))==null?void 0:r.status},hasErrors:e.some(s=>s.status==="error"),isUploading:e.some(s=>s.status==="uploading")}}const v=i.createContext(null);function N({children:e}){const t=w(),[n,o]=i.useState(()=>t.inline?!0:t.isOpen??!1);return i.useEffect(()=>{o(u=>t.isOpen??u)},[t.isOpen]),i.useEffect(()=>{const u=t.openAfterNSeconds;if(typeof u!="number"||isNaN(u))return;const c=setTimeout(()=>o(!0),u*1e3);return()=>clearTimeout(c)},[t.openAfterNSeconds]),i.createElement(v.Provider,{value:{isOpen:n,setIsOpen:o}},e)}function B(){const e=i.useContext(v);if(!e)throw new Error("useWidgetTrigger must be used within a WidgetTriggerProvider");return e}function L(){var l,C;const{widgetCtx:e}=g(),{modesComponents:t}=w(),{sessionState:n}=x(),o=e.modes,u=(l=n.session)==null?void 0:l.modeId,c=o.find(p=>p.id===u),d=(C=t==null?void 0:t.find(p=>{var s,r;return[(c==null?void 0:c.id)||"",((s=c==null?void 0:c.name)==null?void 0:s.toLowerCase())||"",((r=c==null?void 0:c.slug)==null?void 0:r.toLowerCase())||""].includes(p.key.toLowerCase())}))==null?void 0:C.component;return{modes:o,modesComponents:t,activeModeId:u,activeMode:c,Component:d}}exports.WidgetProvider=M;exports.WidgetTriggerProvider=N;exports.useConfig=w;exports.useContact=R;exports.useDocumentDir=A;exports.useIsAwaitingBotReply=O;exports.useMessages=y;exports.useModes=L;exports.usePreludeData=T;exports.usePrimitiveState=m;exports.useSessions=x;exports.useUploadFiles=D;exports.useWidget=g;exports.useWidgetRouter=k;exports.useWidgetTrigger=B;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("react"),E=require("@opencx/widget-core"),F=require("swr"),M=require("uuid"),R="4.0.12";class W{constructor(t){this.components=[];const{components:n}=t;if(n&&n.forEach(o=>this.register(o)),this.components.length===0)throw new Error("No components registered");if(!this.get("fallback"))throw new Error("No fallback component registered")}register(t){const n=this.components.findIndex(o=>o.key===t.key);return n!==-1?this.components[n]=t:this.components.push(t),this}get(t){const n=this.components.find(o=>o.key.toUpperCase()===t.toUpperCase());return n||null}getComponent(t){var n;return(n=this.get(t))==null?void 0:n.component}}const y=i.createContext(null);function P({options:e,children:t,components:n,storage:o,loadingComponent:u}){const a=i.useRef(null),l=i.useRef(!1),[g,p]=i.useState(null),c=i.useMemo(()=>new W({components:n}),[n]);return i.useEffect(()=>{l.current||(l.current=!0,E.WidgetCtx.initialize({config:e,storage:o}).then(p))},[]),g?i.createElement(y.Provider,{value:{widgetCtx:g,config:e,components:n,componentStore:c,version:R,contentIframeRef:a}},t):u||null}function f(){const e=i.useContext(y);if(!e)throw new Error("useWidget must be used within a WidgetProvider");return e}function w(){const{config:e}=f();return e}function m(e){return i.useSyncExternalStore(e.subscribe,e.get,e.get)}function U(){const{widgetCtx:e}=f();return{contactState:m(e.contactCtx.state),createUnverifiedContact:e.contactCtx.createUnverifiedContact}}function k(){const[e,t]=i.useState("ltr");return i.useEffect(()=>{const n=()=>{typeof document>"u"||t(window.getComputedStyle((window.top||window).document.body).direction)};n();const o=new MutationObserver(n);return o.observe(document.documentElement,{attributes:!0,attributeFilter:["dir"]}),o.observe(document.body,{attributes:!0,attributeFilter:["dir"]}),window.addEventListener("languagechange",n),()=>{o.disconnect(),window.removeEventListener("languagechange",n)}},[]),{dir:e}}function h(){const{widgetCtx:e}=f();return{messagesState:m(e.messageCtx.state),sendMessage:e.messageCtx.sendMessage}}function x(){const{widgetCtx:e}=f(),{oneOpenSessionAllowed:t}=w(),n=m(e.sessionCtx.sessionState),o=m(e.sessionCtx.sessionsState),{openSessions:u,closedSessions:a}=i.useMemo(()=>({openSessions:o.data.filter(g=>g.isOpened===!0),closedSessions:o.data.filter(g=>g.isOpened===!1)}),[o.data]),l=i.useMemo(()=>t?u.length===0:!0,[t,u.length]);return{sessionState:n,sessionsState:o,loadMoreSessions:e.sessionCtx.loadMoreSessions,resolveSession:e.sessionCtx.resolveSession,createStateCheckpoint:e.sessionCtx.createStateCheckpoint,openSessions:u,closedSessions:a,canCreateNewSession:l}}function A(){var l;const{sessionState:e}=x(),{messagesState:t}=h(),n=((l=e.session)==null?void 0:l.assignee.kind)==="ai",o=t.messages.length>0?t.messages[t.messages.length-1]:null,u=(o==null?void 0:o.type)==="USER";return{isAwaitingBotReply:(n||e.isCreatingSession)&&(t.isSendingMessage||u)}}function T(){const{widgetCtx:e}=f();return F([e.config.token],e.api.widgetPrelude,{revalidateOnFocus:!1})}function O(){const{widgetCtx:e}=f();return{routerState:m(e.routerCtx.state),toSessionsScreen:e.routerCtx.toSessionsScreen,toChatScreen:e.routerCtx.toChatScreen}}const S=new Map;function q(){const[e,t]=i.useState([]),{widgetCtx:{api:n}}=f();function o(s){const r=s.map(d=>({file:d,id:M.v4(),status:"pending",progress:0}));t(d=>[...d,...r]),r.forEach(l)}function u(s,r){t(d=>d.map(C=>C.id===s?{...C,...r}:C))}function a(s){t(r=>r.filter(d=>d.id!==s))}const l=async s=>{const r=new AbortController;S.set(s.id,r);try{t(C=>C.map(b=>b.id===s.id?{...b,status:"uploading",progress:0}:b));const d=await n.uploadFile({file:s.file,abortSignal:r.signal,onProgress:C=>{u(s.id,{progress:C})}});u(s.id,{status:"success",fileUrl:d.fileUrl,progress:100})}catch(d){r.signal.aborted||u(s.id,{status:"error",error:d instanceof Error?d.message:"Upload failed",progress:0})}finally{S.delete(s.id)}},g=s=>{const r=S.get(s);r&&(r.abort(),S.delete(s)),a(s)},p=i.useMemo(()=>e.filter(s=>s.status==="success"&&s.fileUrl),[e]);function c(){S.forEach(s=>s.abort()),S.clear(),t([])}return i.useEffect(()=>()=>{S.forEach(s=>s.abort()),S.clear()},[]),{allFiles:e,appendFiles:o,handleCancelUpload:g,successFiles:p,emptyTheFiles:c,getFileById:s=>e.find(r=>r.id===s),getUploadProgress:s=>{var r;return((r=e.find(d=>d.id===s))==null?void 0:r.progress)??0},getUploadStatus:s=>{var r;return(r=e.find(d=>d.id===s))==null?void 0:r.status},hasErrors:e.some(s=>s.status==="error"),isUploading:e.some(s=>s.status==="uploading")}}const v=i.createContext(null);function D({children:e}){const t=w(),[n,o]=i.useState(()=>t.inline?!0:t.isOpen??!1);return i.useEffect(()=>{o(u=>t.isOpen??u)},[t.isOpen]),i.useEffect(()=>{const u=t.openAfterNSeconds;if(typeof u!="number"||isNaN(u))return;const a=setTimeout(()=>o(!0),u*1e3);return()=>clearTimeout(a)},[t.openAfterNSeconds]),i.createElement(v.Provider,{value:{isOpen:n,setIsOpen:o}},e)}function N(){const e=i.useContext(v);if(!e)throw new Error("useWidgetTrigger must be used within a WidgetTriggerProvider");return e}function B(){var g,p;const{widgetCtx:e}=f(),{modesComponents:t}=w(),{sessionState:n}=x(),o=e.modes,u=(g=n.session)==null?void 0:g.modeId,a=o.find(c=>c.id===u),l=(p=t==null?void 0:t.find(c=>{var s,r;return[(a==null?void 0:a.id)||"",((s=a==null?void 0:a.name)==null?void 0:s.toLowerCase())||"",((r=a==null?void 0:a.slug)==null?void 0:r.toLowerCase())||""].includes(c.key.toLowerCase())}))==null?void 0:p.component;return{modes:o,modesComponents:t,activeModeId:u,activeMode:a,Component:l}}function L(){const{widgetCtx:e}=f(),{messagesState:{messages:t}}=h(),{csatRequestedMessage:n,isCsatRequested:o,csatSubmittedMessage:u,isCsatSubmitted:a,submittedScore:l,submittedFeedback:g}=i.useMemo(()=>{const p=t.find(s=>s.type==="SYSTEM"&&s.subtype==="csat_requested"),c=t.findLast(s=>s.type==="SYSTEM"&&s.subtype==="csat_submitted");return{csatRequestedMessage:p,isCsatRequested:!!p&&!c,csatSubmittedMessage:c,isCsatSubmitted:!!c,submittedScore:c==null?void 0:c.data.payload.score,submittedFeedback:c==null?void 0:c.data.payload.feedback}},[t]);return{submitCsat:e.csatCtx.submitCsat,csatRequestedMessage:n,isCsatRequested:o,csatSubmittedMessage:u,isCsatSubmitted:a,submittedScore:l,submittedFeedback:g}}exports.WidgetProvider=P;exports.WidgetTriggerProvider=D;exports.useConfig=w;exports.useContact=U;exports.useCsat=L;exports.useDocumentDir=k;exports.useIsAwaitingBotReply=A;exports.useMessages=h;exports.useModes=B;exports.usePreludeData=T;exports.usePrimitiveState=m;exports.useSessions=x;exports.useUploadFiles=q;exports.useWidget=f;exports.useWidgetRouter=O;exports.useWidgetTrigger=N;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/ComponentRegistry.ts","../src/WidgetProvider.tsx","../src/hooks/useConfig.ts","../src/hooks/usePrimitiveState.ts","../src/hooks/useContact.ts","../src/hooks/useDocumentDir.ts","../src/hooks/useMessages.ts","../src/hooks/useSessions.ts","../src/hooks/useIsAwaitingBotReply.ts","../src/hooks/usePreludeData.ts","../src/hooks/useWidgetRouter.ts","../src/hooks/useUploadFiles.ts","../src/hooks/useWidgetTrigger.tsx","../src/hooks/useModes.ts"],"sourcesContent":["import type { WidgetComponentKey } from '@opencx/widget-core';\nimport type { WidgetComponentType } from './types/components';\n\nexport class ComponentRegistry {\n components: WidgetComponentType[] = [];\n\n constructor(opts: { components?: WidgetComponentType[] }) {\n const { components } = opts;\n\n if (components) {\n components.forEach((c) => this.register(c));\n }\n\n if (this.components.length === 0) {\n throw new Error('No components registered');\n }\n if (!this.get('fallback')) {\n throw new Error('No fallback component registered');\n }\n }\n\n // TODO test that this registers or replaces the component\n register(component: WidgetComponentType) {\n // Replace the key if it already exists\n const index = this.components.findIndex((c) => c.key === component.key);\n if (index !== -1) {\n this.components[index] = component;\n } else {\n this.components.push(component);\n }\n return this;\n }\n\n private get(key: WidgetComponentKey) {\n const c = this.components.find(\n (c) => c.key.toUpperCase() === key.toUpperCase(),\n );\n if (c) return c;\n return null;\n }\n\n public getComponent(key: string) {\n return this.get(key)?.component;\n }\n}\n","import React, {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { version } from '../package.json';\nimport { type ExternalStorage, type WidgetConfig, WidgetCtx } from '@opencx/widget-core';\nimport { ComponentRegistry } from './ComponentRegistry';\nimport type { WidgetComponentType } from './types/components';\n\ninterface WidgetProviderValue {\n widgetCtx: WidgetCtx;\n config: WidgetConfig;\n components?: WidgetComponentType[];\n componentStore: ComponentRegistry;\n version: string;\n contentIframeRef?: React.MutableRefObject<HTMLIFrameElement | null>;\n}\n\nconst context = createContext<WidgetProviderValue | null>(null);\n\nexport function WidgetProvider({\n options: config,\n children,\n components,\n storage,\n loadingComponent,\n}: {\n options: WidgetConfig;\n children: React.ReactNode;\n components?: WidgetComponentType[];\n storage?: ExternalStorage;\n /**\n * Custom loading component while the widget is initializing\n * Not to be confused with the `loading` custom component which renders when the bot's reply is pending\n */\n loadingComponent?: React.ReactNode;\n}) {\n const contentIframeRef = useRef<HTMLIFrameElement | null>(null);\n\n const didInitialize = useRef(false);\n const [widgetCtx, setWidgetCtx] = useState<WidgetCtx | null>(null);\n\n const componentStore = useMemo(\n () =>\n new ComponentRegistry({\n components: components,\n }),\n [components],\n );\n\n useEffect(() => {\n if (didInitialize.current) return;\n didInitialize.current = true;\n\n WidgetCtx.initialize({ config, storage }).then(setWidgetCtx);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n if (!widgetCtx) {\n return loadingComponent || null;\n }\n\n return (\n <context.Provider\n value={{\n widgetCtx,\n config,\n components,\n componentStore,\n version,\n contentIframeRef,\n }}\n >\n {children}\n </context.Provider>\n );\n}\n\nexport function useWidget() {\n const ctx = useContext(context);\n if (!ctx) {\n throw new Error('useWidget must be used within a WidgetProvider');\n }\n return ctx;\n}\n","import { useWidget } from '../WidgetProvider';\n\nexport function useConfig() {\n const { config } = useWidget();\n\n return config;\n}\n","import { useSyncExternalStore } from 'react';\nimport type { PrimitiveState } from '@opencx/widget-core';\n\nexport function usePrimitiveState<T>(p: PrimitiveState<T>) {\n return useSyncExternalStore(p.subscribe, p.get, p.get);\n}\n","import { useWidget } from '../WidgetProvider';\nimport { usePrimitiveState } from './usePrimitiveState';\n\nexport function useContact() {\n const { widgetCtx } = useWidget();\n const contactState = usePrimitiveState(widgetCtx.contactCtx.state);\n\n return {\n contactState,\n createUnverifiedContact: widgetCtx.contactCtx.createUnverifiedContact,\n };\n}\n","import { useEffect, useState } from 'react';\nimport type { StringOrLiteral } from '@opencx/widget-core';\n\nexport function useDocumentDir() {\n const [dir, setDir] = useState<StringOrLiteral<'ltr' | 'rtl'>>('ltr');\n\n useEffect(() => {\n const updateDir = () => {\n if (typeof document === 'undefined') return;\n setDir(\n window.getComputedStyle((window.top || window).document.body).direction,\n );\n };\n\n // Set initial direction\n updateDir();\n\n // Watch for direction changes on both document and documentElement\n const observer = new MutationObserver(updateDir);\n\n // Observe both document and documentElement\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['dir'],\n });\n\n observer.observe(document.body, {\n attributes: true,\n attributeFilter: ['dir'],\n });\n\n // Add event listener for dynamic changes\n window.addEventListener('languagechange', updateDir);\n\n return () => {\n observer.disconnect();\n window.removeEventListener('languagechange', updateDir);\n };\n }, []);\n\n return { dir };\n}\n","import { usePrimitiveState } from './usePrimitiveState';\nimport { useWidget } from '../WidgetProvider';\n\nexport function useMessages() {\n const { widgetCtx } = useWidget();\n const messagesState = usePrimitiveState(widgetCtx.messageCtx.state);\n\n return { messagesState, sendMessage: widgetCtx.messageCtx.sendMessage };\n}\n","import { useMemo } from 'react';\nimport { useWidget } from '../WidgetProvider';\nimport { usePrimitiveState } from './usePrimitiveState';\nimport { useConfig } from './useConfig';\n\nexport function useSessions() {\n const { widgetCtx } = useWidget();\n const { oneOpenSessionAllowed } = useConfig();\n const sessionState = usePrimitiveState(widgetCtx.sessionCtx.sessionState);\n const sessionsState = usePrimitiveState(widgetCtx.sessionCtx.sessionsState);\n\n const { openSessions, closedSessions } = useMemo(() => {\n return {\n openSessions: sessionsState.data.filter((s) => s.isOpened === true),\n closedSessions: sessionsState.data.filter((s) => s.isOpened === false),\n };\n }, [sessionsState.data]);\n\n const canCreateNewSession = useMemo(() => {\n if (oneOpenSessionAllowed) {\n return openSessions.length === 0;\n }\n return true;\n }, [oneOpenSessionAllowed, openSessions.length]);\n\n return {\n sessionState,\n sessionsState,\n loadMoreSessions: widgetCtx.sessionCtx.loadMoreSessions,\n resolveSession: widgetCtx.sessionCtx.resolveSession,\n createStateCheckpoint: widgetCtx.sessionCtx.createStateCheckpoint,\n openSessions,\n closedSessions,\n canCreateNewSession,\n };\n}\n","import { useMessages } from './useMessages';\nimport { useSessions } from './useSessions';\n\nexport function useIsAwaitingBotReply() {\n const { sessionState } = useSessions();\n const { messagesState } = useMessages();\n\n const isSessionAssignedToAI = sessionState.session?.assignee.kind === 'ai';\n // This check is useful in cases where the user might navigate in and out of a chat, and `isSendingMessage` is reset back to its default value\n const lastMessage =\n messagesState.messages.length > 0\n ? messagesState.messages[messagesState.messages.length - 1]\n : null;\n const isLastMessageAUserMessage = lastMessage?.type === 'FROM_USER';\n\n const isAwaitingBotReply =\n (isSessionAssignedToAI || sessionState.isCreatingSession) &&\n (messagesState.isSendingMessage || isLastMessageAUserMessage);\n\n return { isAwaitingBotReply };\n}\n","import useSWR from 'swr';\nimport { useWidget } from '../WidgetProvider';\n\nfunction usePreludeData() {\n const { widgetCtx } = useWidget();\n\n // TODO remove swr dependency\n return useSWR([widgetCtx.config.token], widgetCtx.api.widgetPrelude, {\n revalidateOnFocus: false,\n });\n}\n\nexport { usePreludeData };\n","import { useWidget } from '../WidgetProvider';\nimport { usePrimitiveState } from './usePrimitiveState';\n\nexport function useWidgetRouter() {\n const { widgetCtx } = useWidget();\n\n const routerState = usePrimitiveState(widgetCtx.routerCtx.state);\n\n return {\n routerState,\n toSessionsScreen: widgetCtx.routerCtx.toSessionsScreen,\n toChatScreen: widgetCtx.routerCtx.toChatScreen,\n };\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport { useWidget } from '../WidgetProvider';\nimport { v4 } from 'uuid';\n\nconst uploadAbortControllers: Map<string, AbortController> = new Map();\n\ninterface FileWithProgress {\n status: 'pending' | 'uploading' | 'success' | 'error';\n id: string;\n file: File;\n fileUrl?: string;\n progress: number;\n error?: string;\n}\n\nfunction useUploadFiles() {\n const [files, setFiles] = useState<FileWithProgress[]>([]);\n const {\n widgetCtx: { api },\n } = useWidget();\n function appendFiles(files: File[]) {\n const newFiles = files.map((file) => ({\n file,\n id: v4(),\n status: 'pending' as const,\n progress: 0,\n }));\n\n setFiles((prev) => [...prev, ...newFiles]);\n newFiles.forEach(uploadFile);\n }\n\n function updateFileById(id: string, update: Partial<FileWithProgress>) {\n setFiles((prev) =>\n prev.map((f) => (f.id === id ? { ...f, ...update } : f)),\n );\n }\n\n function removeFileById(id: string) {\n setFiles((prev) => prev.filter((f) => f.id !== id));\n }\n\n const uploadFile = async (fileItem: FileWithProgress) => {\n const controller = new AbortController();\n uploadAbortControllers.set(fileItem.id, controller);\n\n try {\n setFiles((prev) =>\n prev.map((f) =>\n f.id === fileItem.id ? { ...f, status: 'uploading', progress: 0 } : f,\n ),\n );\n\n const response = await api.uploadFile({\n file: fileItem.file,\n abortSignal: controller.signal,\n onProgress: (percentage) => {\n updateFileById(fileItem.id, { progress: percentage });\n },\n });\n\n updateFileById(fileItem.id, {\n status: 'success',\n fileUrl: response.fileUrl,\n progress: 100,\n });\n } catch (error) {\n if (!controller.signal.aborted) {\n updateFileById(fileItem.id, {\n status: 'error',\n error: error instanceof Error ? error.message : 'Upload failed',\n progress: 0,\n });\n }\n } finally {\n uploadAbortControllers.delete(fileItem.id);\n }\n };\n\n const handleCancelUpload = (fileId: string) => {\n const controller = uploadAbortControllers.get(fileId);\n if (controller) {\n controller.abort();\n uploadAbortControllers.delete(fileId);\n }\n removeFileById(fileId);\n };\n\n const successFiles = useMemo(() => {\n return files.filter((f) => f.status === 'success' && f.fileUrl);\n }, [files]);\n\n function emptyTheFiles() {\n uploadAbortControllers.forEach((controller) => controller.abort());\n uploadAbortControllers.clear();\n setFiles([]);\n }\n\n useEffect(() => {\n return () => {\n uploadAbortControllers.forEach((controller) => controller.abort());\n uploadAbortControllers.clear();\n };\n }, []);\n\n return {\n allFiles: files,\n appendFiles,\n handleCancelUpload,\n successFiles,\n emptyTheFiles,\n getFileById: (id: string) => files.find((f) => f.id === id),\n getUploadProgress: (id: string) =>\n files.find((f) => f.id === id)?.progress ?? 0,\n getUploadStatus: (id: string) => files.find((f) => f.id === id)?.status,\n hasErrors: files.some((f) => f.status === 'error'),\n isUploading: files.some((f) => f.status === 'uploading'),\n };\n}\n\nexport { useUploadFiles, type FileWithProgress };\n","import React, {\n createContext,\n useContext,\n useEffect,\n useState,\n type Dispatch,\n type ReactNode,\n type SetStateAction,\n} from 'react';\nimport { useConfig } from './useConfig';\n\ntype WidgetTriggerCtx = {\n isOpen: boolean;\n setIsOpen: Dispatch<SetStateAction<boolean>>;\n};\n\nconst context = createContext<WidgetTriggerCtx | null>(null);\n\nexport function WidgetTriggerProvider({ children }: { children: ReactNode }) {\n const config = useConfig();\n const [isOpen, setIsOpen] = useState(() => {\n if (config.inline) return true;\n return config.isOpen ?? false;\n });\n\n useEffect(() => {\n setIsOpen((prev) => config.isOpen ?? prev);\n }, [config.isOpen]);\n\n useEffect(() => {\n const openAfterNSeconds = config.openAfterNSeconds;\n if (typeof openAfterNSeconds !== 'number' || isNaN(openAfterNSeconds))\n return;\n\n const timeout = setTimeout(() => setIsOpen(true), openAfterNSeconds * 1000);\n\n return () => clearTimeout(timeout);\n }, [config.openAfterNSeconds]);\n\n return (\n <context.Provider value={{ isOpen, setIsOpen }}>\n {children}\n </context.Provider>\n );\n}\n\nexport function useWidgetTrigger() {\n const ctx = useContext(context);\n if (!ctx) {\n throw new Error(\n 'useWidgetTrigger must be used within a WidgetTriggerProvider',\n );\n }\n return ctx;\n}\n","import { useWidget } from '../WidgetProvider';\nimport { useConfig } from './useConfig';\nimport { useSessions } from './useSessions';\n\nexport function useModes() {\n const { widgetCtx } = useWidget();\n const { modesComponents } = useConfig();\n const { sessionState } = useSessions();\n\n const modes = widgetCtx.modes;\n const activeModeId = sessionState.session?.modeId;\n const activeMode = modes.find((mode) => mode.id === activeModeId);\n\n const Component = modesComponents?.find((modeComponent) =>\n [\n activeMode?.id || '',\n activeMode?.name?.toLowerCase() || '',\n activeMode?.slug?.toLowerCase() || '',\n ].includes(modeComponent.key.toLowerCase()),\n )?.component;\n\n return {\n modes,\n modesComponents,\n activeModeId,\n activeMode,\n Component,\n };\n}\n"],"names":["ComponentRegistry","opts","components","c","component","index","key","_a","context","createContext","WidgetProvider","config","children","storage","loadingComponent","contentIframeRef","useRef","didInitialize","widgetCtx","setWidgetCtx","useState","componentStore","useMemo","useEffect","WidgetCtx","React","version","useWidget","ctx","useContext","useConfig","usePrimitiveState","p","useSyncExternalStore","useContact","useDocumentDir","dir","setDir","updateDir","observer","useMessages","useSessions","oneOpenSessionAllowed","sessionState","sessionsState","openSessions","closedSessions","s","canCreateNewSession","useIsAwaitingBotReply","messagesState","isSessionAssignedToAI","lastMessage","isLastMessageAUserMessage","usePreludeData","useSWR","useWidgetRouter","uploadAbortControllers","useUploadFiles","files","setFiles","api","appendFiles","newFiles","file","v4","prev","uploadFile","updateFileById","id","update","f","removeFileById","fileItem","controller","response","percentage","error","handleCancelUpload","fileId","successFiles","emptyTheFiles","WidgetTriggerProvider","isOpen","setIsOpen","openAfterNSeconds","timeout","useWidgetTrigger","useModes","modesComponents","modes","activeModeId","activeMode","mode","Component","_b","modeComponent"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/ComponentRegistry.ts","../src/WidgetProvider.tsx","../src/hooks/useConfig.ts","../src/hooks/usePrimitiveState.ts","../src/hooks/useContact.ts","../src/hooks/useDocumentDir.ts","../src/hooks/useMessages.ts","../src/hooks/useSessions.ts","../src/hooks/useIsAwaitingBotReply.ts","../src/hooks/usePreludeData.ts","../src/hooks/useWidgetRouter.ts","../src/hooks/useUploadFiles.ts","../src/hooks/useWidgetTrigger.tsx","../src/hooks/useModes.ts","../src/hooks/useCsat.ts"],"sourcesContent":["import type { WidgetComponentKey } from '@opencx/widget-core';\nimport type { WidgetComponentType } from './types/components';\n\nexport class ComponentRegistry {\n components: WidgetComponentType[] = [];\n\n constructor(opts: { components?: WidgetComponentType[] }) {\n const { components } = opts;\n\n if (components) {\n components.forEach((c) => this.register(c));\n }\n\n if (this.components.length === 0) {\n throw new Error('No components registered');\n }\n if (!this.get('fallback')) {\n throw new Error('No fallback component registered');\n }\n }\n\n // TODO test that this registers or replaces the component\n register(component: WidgetComponentType) {\n // Replace the key if it already exists\n const index = this.components.findIndex((c) => c.key === component.key);\n if (index !== -1) {\n this.components[index] = component;\n } else {\n this.components.push(component);\n }\n return this;\n }\n\n private get(key: WidgetComponentKey) {\n const c = this.components.find(\n (c) => c.key.toUpperCase() === key.toUpperCase(),\n );\n if (c) return c;\n return null;\n }\n\n public getComponent(key: string) {\n return this.get(key)?.component;\n }\n}\n","import React, {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { version } from '../package.json';\nimport { type ExternalStorage, type WidgetConfig, WidgetCtx } from '@opencx/widget-core';\nimport { ComponentRegistry } from './ComponentRegistry';\nimport type { WidgetComponentType } from './types/components';\n\ninterface WidgetProviderValue {\n widgetCtx: WidgetCtx;\n config: WidgetConfig;\n components?: WidgetComponentType[];\n componentStore: ComponentRegistry;\n version: string;\n contentIframeRef?: React.MutableRefObject<HTMLIFrameElement | null>;\n}\n\nconst context = createContext<WidgetProviderValue | null>(null);\n\nexport function WidgetProvider({\n options: config,\n children,\n components,\n storage,\n loadingComponent,\n}: {\n options: WidgetConfig;\n children: React.ReactNode;\n components?: WidgetComponentType[];\n storage?: ExternalStorage;\n /**\n * Custom loading component while the widget is initializing\n * Not to be confused with the `loading` custom component which renders when the bot's reply is pending\n */\n loadingComponent?: React.ReactNode;\n}) {\n const contentIframeRef = useRef<HTMLIFrameElement | null>(null);\n\n const didInitialize = useRef(false);\n const [widgetCtx, setWidgetCtx] = useState<WidgetCtx | null>(null);\n\n const componentStore = useMemo(\n () =>\n new ComponentRegistry({\n components: components,\n }),\n [components],\n );\n\n useEffect(() => {\n if (didInitialize.current) return;\n didInitialize.current = true;\n\n WidgetCtx.initialize({ config, storage }).then(setWidgetCtx);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n if (!widgetCtx) {\n return loadingComponent || null;\n }\n\n return (\n <context.Provider\n value={{\n widgetCtx,\n config,\n components,\n componentStore,\n version,\n contentIframeRef,\n }}\n >\n {children}\n </context.Provider>\n );\n}\n\nexport function useWidget() {\n const ctx = useContext(context);\n if (!ctx) {\n throw new Error('useWidget must be used within a WidgetProvider');\n }\n return ctx;\n}\n","import { useWidget } from '../WidgetProvider';\n\nexport function useConfig() {\n const { config } = useWidget();\n\n return config;\n}\n","import { useSyncExternalStore } from 'react';\nimport type { PrimitiveState } from '@opencx/widget-core';\n\nexport function usePrimitiveState<T>(p: PrimitiveState<T>) {\n return useSyncExternalStore(p.subscribe, p.get, p.get);\n}\n","import { useWidget } from '../WidgetProvider';\nimport { usePrimitiveState } from './usePrimitiveState';\n\nexport function useContact() {\n const { widgetCtx } = useWidget();\n const contactState = usePrimitiveState(widgetCtx.contactCtx.state);\n\n return {\n contactState,\n createUnverifiedContact: widgetCtx.contactCtx.createUnverifiedContact,\n };\n}\n","import { useEffect, useState } from 'react';\nimport type { StringOrLiteral } from '@opencx/widget-core';\n\nexport function useDocumentDir() {\n const [dir, setDir] = useState<StringOrLiteral<'ltr' | 'rtl'>>('ltr');\n\n useEffect(() => {\n const updateDir = () => {\n if (typeof document === 'undefined') return;\n setDir(\n window.getComputedStyle((window.top || window).document.body).direction,\n );\n };\n\n // Set initial direction\n updateDir();\n\n // Watch for direction changes on both document and documentElement\n const observer = new MutationObserver(updateDir);\n\n // Observe both document and documentElement\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['dir'],\n });\n\n observer.observe(document.body, {\n attributes: true,\n attributeFilter: ['dir'],\n });\n\n // Add event listener for dynamic changes\n window.addEventListener('languagechange', updateDir);\n\n return () => {\n observer.disconnect();\n window.removeEventListener('languagechange', updateDir);\n };\n }, []);\n\n return { dir };\n}\n","import { usePrimitiveState } from './usePrimitiveState';\nimport { useWidget } from '../WidgetProvider';\n\nexport function useMessages() {\n const { widgetCtx } = useWidget();\n const messagesState = usePrimitiveState(widgetCtx.messageCtx.state);\n\n return { messagesState, sendMessage: widgetCtx.messageCtx.sendMessage };\n}\n","import { useMemo } from 'react';\nimport { useWidget } from '../WidgetProvider';\nimport { usePrimitiveState } from './usePrimitiveState';\nimport { useConfig } from './useConfig';\n\nexport function useSessions() {\n const { widgetCtx } = useWidget();\n const { oneOpenSessionAllowed } = useConfig();\n const sessionState = usePrimitiveState(widgetCtx.sessionCtx.sessionState);\n const sessionsState = usePrimitiveState(widgetCtx.sessionCtx.sessionsState);\n\n const { openSessions, closedSessions } = useMemo(() => {\n return {\n openSessions: sessionsState.data.filter((s) => s.isOpened === true),\n closedSessions: sessionsState.data.filter((s) => s.isOpened === false),\n };\n }, [sessionsState.data]);\n\n const canCreateNewSession = useMemo(() => {\n if (oneOpenSessionAllowed) {\n return openSessions.length === 0;\n }\n return true;\n }, [oneOpenSessionAllowed, openSessions.length]);\n\n return {\n sessionState,\n sessionsState,\n loadMoreSessions: widgetCtx.sessionCtx.loadMoreSessions,\n resolveSession: widgetCtx.sessionCtx.resolveSession,\n createStateCheckpoint: widgetCtx.sessionCtx.createStateCheckpoint,\n openSessions,\n closedSessions,\n canCreateNewSession,\n };\n}\n","import { useMessages } from './useMessages';\nimport { useSessions } from './useSessions';\n\nexport function useIsAwaitingBotReply() {\n const { sessionState } = useSessions();\n const { messagesState } = useMessages();\n\n const isSessionAssignedToAI = sessionState.session?.assignee.kind === 'ai';\n // This check is useful in cases where the user might navigate in and out of a chat, and `isSendingMessage` is reset back to its default value\n const lastMessage =\n messagesState.messages.length > 0\n ? messagesState.messages[messagesState.messages.length - 1]\n : null;\n const isLastMessageAUserMessage = lastMessage?.type === 'USER';\n\n const isAwaitingBotReply =\n (isSessionAssignedToAI || sessionState.isCreatingSession) &&\n (messagesState.isSendingMessage || isLastMessageAUserMessage);\n\n return { isAwaitingBotReply };\n}\n","import useSWR from 'swr';\nimport { useWidget } from '../WidgetProvider';\n\nfunction usePreludeData() {\n const { widgetCtx } = useWidget();\n\n // TODO remove swr dependency\n return useSWR([widgetCtx.config.token], widgetCtx.api.widgetPrelude, {\n revalidateOnFocus: false,\n });\n}\n\nexport { usePreludeData };\n","import { useWidget } from '../WidgetProvider';\nimport { usePrimitiveState } from './usePrimitiveState';\n\nexport function useWidgetRouter() {\n const { widgetCtx } = useWidget();\n\n const routerState = usePrimitiveState(widgetCtx.routerCtx.state);\n\n return {\n routerState,\n toSessionsScreen: widgetCtx.routerCtx.toSessionsScreen,\n toChatScreen: widgetCtx.routerCtx.toChatScreen,\n };\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport { useWidget } from '../WidgetProvider';\nimport { v4 } from 'uuid';\n\nconst uploadAbortControllers: Map<string, AbortController> = new Map();\n\ninterface FileWithProgress {\n status: 'pending' | 'uploading' | 'success' | 'error';\n id: string;\n file: File;\n fileUrl?: string;\n progress: number;\n error?: string;\n}\n\nfunction useUploadFiles() {\n const [files, setFiles] = useState<FileWithProgress[]>([]);\n const {\n widgetCtx: { api },\n } = useWidget();\n function appendFiles(files: File[]) {\n const newFiles = files.map((file) => ({\n file,\n id: v4(),\n status: 'pending' as const,\n progress: 0,\n }));\n\n setFiles((prev) => [...prev, ...newFiles]);\n newFiles.forEach(uploadFile);\n }\n\n function updateFileById(id: string, update: Partial<FileWithProgress>) {\n setFiles((prev) =>\n prev.map((f) => (f.id === id ? { ...f, ...update } : f)),\n );\n }\n\n function removeFileById(id: string) {\n setFiles((prev) => prev.filter((f) => f.id !== id));\n }\n\n const uploadFile = async (fileItem: FileWithProgress) => {\n const controller = new AbortController();\n uploadAbortControllers.set(fileItem.id, controller);\n\n try {\n setFiles((prev) =>\n prev.map((f) =>\n f.id === fileItem.id ? { ...f, status: 'uploading', progress: 0 } : f,\n ),\n );\n\n const response = await api.uploadFile({\n file: fileItem.file,\n abortSignal: controller.signal,\n onProgress: (percentage) => {\n updateFileById(fileItem.id, { progress: percentage });\n },\n });\n\n updateFileById(fileItem.id, {\n status: 'success',\n fileUrl: response.fileUrl,\n progress: 100,\n });\n } catch (error) {\n if (!controller.signal.aborted) {\n updateFileById(fileItem.id, {\n status: 'error',\n error: error instanceof Error ? error.message : 'Upload failed',\n progress: 0,\n });\n }\n } finally {\n uploadAbortControllers.delete(fileItem.id);\n }\n };\n\n const handleCancelUpload = (fileId: string) => {\n const controller = uploadAbortControllers.get(fileId);\n if (controller) {\n controller.abort();\n uploadAbortControllers.delete(fileId);\n }\n removeFileById(fileId);\n };\n\n const successFiles = useMemo(() => {\n return files.filter((f) => f.status === 'success' && f.fileUrl);\n }, [files]);\n\n function emptyTheFiles() {\n uploadAbortControllers.forEach((controller) => controller.abort());\n uploadAbortControllers.clear();\n setFiles([]);\n }\n\n useEffect(() => {\n return () => {\n uploadAbortControllers.forEach((controller) => controller.abort());\n uploadAbortControllers.clear();\n };\n }, []);\n\n return {\n allFiles: files,\n appendFiles,\n handleCancelUpload,\n successFiles,\n emptyTheFiles,\n getFileById: (id: string) => files.find((f) => f.id === id),\n getUploadProgress: (id: string) =>\n files.find((f) => f.id === id)?.progress ?? 0,\n getUploadStatus: (id: string) => files.find((f) => f.id === id)?.status,\n hasErrors: files.some((f) => f.status === 'error'),\n isUploading: files.some((f) => f.status === 'uploading'),\n };\n}\n\nexport { useUploadFiles, type FileWithProgress };\n","import React, {\n createContext,\n useContext,\n useEffect,\n useState,\n type Dispatch,\n type ReactNode,\n type SetStateAction,\n} from 'react';\nimport { useConfig } from './useConfig';\n\ntype WidgetTriggerCtx = {\n isOpen: boolean;\n setIsOpen: Dispatch<SetStateAction<boolean>>;\n};\n\nconst context = createContext<WidgetTriggerCtx | null>(null);\n\nexport function WidgetTriggerProvider({ children }: { children: ReactNode }) {\n const config = useConfig();\n const [isOpen, setIsOpen] = useState(() => {\n if (config.inline) return true;\n return config.isOpen ?? false;\n });\n\n useEffect(() => {\n setIsOpen((prev) => config.isOpen ?? prev);\n }, [config.isOpen]);\n\n useEffect(() => {\n const openAfterNSeconds = config.openAfterNSeconds;\n if (typeof openAfterNSeconds !== 'number' || isNaN(openAfterNSeconds))\n return;\n\n const timeout = setTimeout(() => setIsOpen(true), openAfterNSeconds * 1000);\n\n return () => clearTimeout(timeout);\n }, [config.openAfterNSeconds]);\n\n return (\n <context.Provider value={{ isOpen, setIsOpen }}>\n {children}\n </context.Provider>\n );\n}\n\nexport function useWidgetTrigger() {\n const ctx = useContext(context);\n if (!ctx) {\n throw new Error(\n 'useWidgetTrigger must be used within a WidgetTriggerProvider',\n );\n }\n return ctx;\n}\n","import { useWidget } from '../WidgetProvider';\nimport { useConfig } from './useConfig';\nimport { useSessions } from './useSessions';\n\nexport function useModes() {\n const { widgetCtx } = useWidget();\n const { modesComponents } = useConfig();\n const { sessionState } = useSessions();\n\n const modes = widgetCtx.modes;\n const activeModeId = sessionState.session?.modeId;\n const activeMode = modes.find((mode) => mode.id === activeModeId);\n\n const Component = modesComponents?.find((modeComponent) =>\n [\n activeMode?.id || '',\n activeMode?.name?.toLowerCase() || '',\n activeMode?.slug?.toLowerCase() || '',\n ].includes(modeComponent.key.toLowerCase()),\n )?.component;\n\n return {\n modes,\n modesComponents,\n activeModeId,\n activeMode,\n Component,\n };\n}\n","import type {\n WidgetSystemMessage__CsatRequested,\n WidgetSystemMessage__CsatSubmitted,\n} from '@opencx/widget-core';\nimport { useMemo } from 'react';\nimport { useMessages } from './useMessages';\nimport { useWidget } from '../WidgetProvider';\n\nexport function useCsat() {\n const { widgetCtx } = useWidget();\n const {\n messagesState: { messages },\n } = useMessages();\n\n const {\n csatRequestedMessage,\n isCsatRequested,\n csatSubmittedMessage,\n isCsatSubmitted,\n submittedScore,\n submittedFeedback,\n } = useMemo(() => {\n const csatRequestedMessage = messages.find(\n (message): message is WidgetSystemMessage__CsatRequested =>\n message.type === 'SYSTEM' && message.subtype === 'csat_requested',\n );\n const csatSubmittedMessage = messages.findLast(\n (message): message is WidgetSystemMessage__CsatSubmitted =>\n message.type === 'SYSTEM' && message.subtype === 'csat_submitted',\n );\n\n return {\n csatRequestedMessage,\n isCsatRequested: !!csatRequestedMessage && !csatSubmittedMessage,\n csatSubmittedMessage,\n isCsatSubmitted: !!csatSubmittedMessage,\n submittedScore: csatSubmittedMessage?.data.payload.score,\n submittedFeedback: csatSubmittedMessage?.data.payload.feedback,\n };\n }, [messages]);\n\n return {\n submitCsat: widgetCtx.csatCtx.submitCsat,\n csatRequestedMessage,\n isCsatRequested,\n csatSubmittedMessage,\n isCsatSubmitted,\n submittedScore,\n submittedFeedback,\n };\n}\n"],"names":["ComponentRegistry","opts","components","c","component","index","key","_a","context","createContext","WidgetProvider","config","children","storage","loadingComponent","contentIframeRef","useRef","didInitialize","widgetCtx","setWidgetCtx","useState","componentStore","useMemo","useEffect","WidgetCtx","React","version","useWidget","ctx","useContext","useConfig","usePrimitiveState","p","useSyncExternalStore","useContact","useDocumentDir","dir","setDir","updateDir","observer","useMessages","useSessions","oneOpenSessionAllowed","sessionState","sessionsState","openSessions","closedSessions","s","canCreateNewSession","useIsAwaitingBotReply","messagesState","isSessionAssignedToAI","lastMessage","isLastMessageAUserMessage","usePreludeData","useSWR","useWidgetRouter","uploadAbortControllers","useUploadFiles","files","setFiles","api","appendFiles","newFiles","file","v4","prev","uploadFile","updateFileById","id","update","f","removeFileById","fileItem","controller","response","percentage","error","handleCancelUpload","fileId","successFiles","emptyTheFiles","WidgetTriggerProvider","isOpen","setIsOpen","openAfterNSeconds","timeout","useWidgetTrigger","useModes","modesComponents","modes","activeModeId","activeMode","mode","Component","_b","modeComponent","useCsat","messages","csatRequestedMessage","isCsatRequested","csatSubmittedMessage","isCsatSubmitted","submittedScore","submittedFeedback","message"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
- import v, { createContext as E, useRef as y, useState as h, useMemo as w, useEffect as S, useContext as F, useSyncExternalStore as O } from "react";
2
- import { WidgetCtx as P } from "@opencx/widget-core";
3
- import R from "swr";
4
- import { v4 as k } from "uuid";
5
- const M = "4.0.10";
1
+ import v, { createContext as E, useRef as y, useState as b, useMemo as S, useEffect as C, useContext as F, useSyncExternalStore as W } from "react";
2
+ import { WidgetCtx as M } from "@opencx/widget-core";
3
+ import P from "swr";
4
+ import { v4 as O } from "uuid";
5
+ const T = "4.0.12";
6
6
  class N {
7
7
  constructor(t) {
8
8
  this.components = [];
@@ -28,60 +28,60 @@ class N {
28
28
  return (n = this.get(t)) == null ? void 0 : n.component;
29
29
  }
30
30
  }
31
- const U = E(null);
32
- function z({
31
+ const R = E(null);
32
+ function I({
33
33
  options: e,
34
34
  children: t,
35
35
  components: n,
36
36
  storage: o,
37
37
  loadingComponent: i
38
38
  }) {
39
- const c = y(null), u = y(!1), [d, m] = h(null), p = w(
39
+ const a = y(null), d = y(!1), [l, g] = b(null), c = S(
40
40
  () => new N({
41
41
  components: n
42
42
  }),
43
43
  [n]
44
44
  );
45
- return S(() => {
46
- u.current || (u.current = !0, P.initialize({ config: e, storage: o }).then(m));
47
- }, []), d ? /* @__PURE__ */ v.createElement(
48
- U.Provider,
45
+ return C(() => {
46
+ d.current || (d.current = !0, M.initialize({ config: e, storage: o }).then(g));
47
+ }, []), l ? /* @__PURE__ */ v.createElement(
48
+ R.Provider,
49
49
  {
50
50
  value: {
51
- widgetCtx: d,
51
+ widgetCtx: l,
52
52
  config: e,
53
53
  components: n,
54
- componentStore: p,
55
- version: M,
56
- contentIframeRef: c
54
+ componentStore: c,
55
+ version: T,
56
+ contentIframeRef: a
57
57
  }
58
58
  },
59
59
  t
60
60
  ) : i || null;
61
61
  }
62
- function g() {
63
- const e = F(U);
62
+ function p() {
63
+ const e = F(R);
64
64
  if (!e)
65
65
  throw new Error("useWidget must be used within a WidgetProvider");
66
66
  return e;
67
67
  }
68
- function b() {
69
- const { config: e } = g();
68
+ function x() {
69
+ const { config: e } = p();
70
70
  return e;
71
71
  }
72
- function C(e) {
73
- return O(e.subscribe, e.get, e.get);
72
+ function w(e) {
73
+ return W(e.subscribe, e.get, e.get);
74
74
  }
75
- function _() {
76
- const { widgetCtx: e } = g();
75
+ function z() {
76
+ const { widgetCtx: e } = p();
77
77
  return {
78
- contactState: C(e.contactCtx.state),
78
+ contactState: w(e.contactCtx.state),
79
79
  createUnverifiedContact: e.contactCtx.createUnverifiedContact
80
80
  };
81
81
  }
82
- function $() {
83
- const [e, t] = h("ltr");
84
- return S(() => {
82
+ function Y() {
83
+ const [e, t] = b("ltr");
84
+ return C(() => {
85
85
  const n = () => {
86
86
  typeof document > "u" || t(
87
87
  window.getComputedStyle((window.top || window).document.body).direction
@@ -100,15 +100,15 @@ function $() {
100
100
  };
101
101
  }, []), { dir: e };
102
102
  }
103
- function T() {
104
- const { widgetCtx: e } = g();
105
- return { messagesState: C(e.messageCtx.state), sendMessage: e.messageCtx.sendMessage };
103
+ function U() {
104
+ const { widgetCtx: e } = p();
105
+ return { messagesState: w(e.messageCtx.state), sendMessage: e.messageCtx.sendMessage };
106
106
  }
107
- function A() {
108
- const { widgetCtx: e } = g(), { oneOpenSessionAllowed: t } = b(), n = C(e.sessionCtx.sessionState), o = C(e.sessionCtx.sessionsState), { openSessions: i, closedSessions: c } = w(() => ({
109
- openSessions: o.data.filter((d) => d.isOpened === !0),
110
- closedSessions: o.data.filter((d) => d.isOpened === !1)
111
- }), [o.data]), u = w(() => t ? i.length === 0 : !0, [t, i.length]);
107
+ function k() {
108
+ const { widgetCtx: e } = p(), { oneOpenSessionAllowed: t } = x(), n = w(e.sessionCtx.sessionState), o = w(e.sessionCtx.sessionsState), { openSessions: i, closedSessions: a } = S(() => ({
109
+ openSessions: o.data.filter((l) => l.isOpened === !0),
110
+ closedSessions: o.data.filter((l) => l.isOpened === !1)
111
+ }), [o.data]), d = S(() => t ? i.length === 0 : !0, [t, i.length]);
112
112
  return {
113
113
  sessionState: n,
114
114
  sessionsState: o,
@@ -116,165 +116,201 @@ function A() {
116
116
  resolveSession: e.sessionCtx.resolveSession,
117
117
  createStateCheckpoint: e.sessionCtx.createStateCheckpoint,
118
118
  openSessions: i,
119
- closedSessions: c,
120
- canCreateNewSession: u
119
+ closedSessions: a,
120
+ canCreateNewSession: d
121
121
  };
122
122
  }
123
- function j() {
124
- var u;
125
- const { sessionState: e } = A(), { messagesState: t } = T(), n = ((u = e.session) == null ? void 0 : u.assignee.kind) === "ai", o = t.messages.length > 0 ? t.messages[t.messages.length - 1] : null, i = (o == null ? void 0 : o.type) === "FROM_USER";
123
+ function _() {
124
+ var d;
125
+ const { sessionState: e } = k(), { messagesState: t } = U(), n = ((d = e.session) == null ? void 0 : d.assignee.kind) === "ai", o = t.messages.length > 0 ? t.messages[t.messages.length - 1] : null, i = (o == null ? void 0 : o.type) === "USER";
126
126
  return { isAwaitingBotReply: (n || e.isCreatingSession) && (t.isSendingMessage || i) };
127
127
  }
128
- function q() {
129
- const { widgetCtx: e } = g();
130
- return R([e.config.token], e.api.widgetPrelude, {
128
+ function $() {
129
+ const { widgetCtx: e } = p();
130
+ return P([e.config.token], e.api.widgetPrelude, {
131
131
  revalidateOnFocus: !1
132
132
  });
133
133
  }
134
- function G() {
135
- const { widgetCtx: e } = g();
134
+ function j() {
135
+ const { widgetCtx: e } = p();
136
136
  return {
137
- routerState: C(e.routerCtx.state),
137
+ routerState: w(e.routerCtx.state),
138
138
  toSessionsScreen: e.routerCtx.toSessionsScreen,
139
139
  toChatScreen: e.routerCtx.toChatScreen
140
140
  };
141
141
  }
142
- const l = /* @__PURE__ */ new Map();
143
- function H() {
144
- const [e, t] = h([]), {
142
+ const f = /* @__PURE__ */ new Map();
143
+ function G() {
144
+ const [e, t] = b([]), {
145
145
  widgetCtx: { api: n }
146
- } = g();
146
+ } = p();
147
147
  function o(s) {
148
- const r = s.map((a) => ({
149
- file: a,
150
- id: k(),
148
+ const r = s.map((u) => ({
149
+ file: u,
150
+ id: O(),
151
151
  status: "pending",
152
152
  progress: 0
153
153
  }));
154
- t((a) => [...a, ...r]), r.forEach(u);
154
+ t((u) => [...u, ...r]), r.forEach(d);
155
155
  }
156
156
  function i(s, r) {
157
157
  t(
158
- (a) => a.map((f) => f.id === s ? { ...f, ...r } : f)
158
+ (u) => u.map((m) => m.id === s ? { ...m, ...r } : m)
159
159
  );
160
160
  }
161
- function c(s) {
162
- t((r) => r.filter((a) => a.id !== s));
161
+ function a(s) {
162
+ t((r) => r.filter((u) => u.id !== s));
163
163
  }
164
- const u = async (s) => {
164
+ const d = async (s) => {
165
165
  const r = new AbortController();
166
- l.set(s.id, r);
166
+ f.set(s.id, r);
167
167
  try {
168
168
  t(
169
- (f) => f.map(
170
- (x) => x.id === s.id ? { ...x, status: "uploading", progress: 0 } : x
169
+ (m) => m.map(
170
+ (h) => h.id === s.id ? { ...h, status: "uploading", progress: 0 } : h
171
171
  )
172
172
  );
173
- const a = await n.uploadFile({
173
+ const u = await n.uploadFile({
174
174
  file: s.file,
175
175
  abortSignal: r.signal,
176
- onProgress: (f) => {
177
- i(s.id, { progress: f });
176
+ onProgress: (m) => {
177
+ i(s.id, { progress: m });
178
178
  }
179
179
  });
180
180
  i(s.id, {
181
181
  status: "success",
182
- fileUrl: a.fileUrl,
182
+ fileUrl: u.fileUrl,
183
183
  progress: 100
184
184
  });
185
- } catch (a) {
185
+ } catch (u) {
186
186
  r.signal.aborted || i(s.id, {
187
187
  status: "error",
188
- error: a instanceof Error ? a.message : "Upload failed",
188
+ error: u instanceof Error ? u.message : "Upload failed",
189
189
  progress: 0
190
190
  });
191
191
  } finally {
192
- l.delete(s.id);
192
+ f.delete(s.id);
193
193
  }
194
- }, d = (s) => {
195
- const r = l.get(s);
196
- r && (r.abort(), l.delete(s)), c(s);
197
- }, m = w(() => e.filter((s) => s.status === "success" && s.fileUrl), [e]);
198
- function p() {
199
- l.forEach((s) => s.abort()), l.clear(), t([]);
194
+ }, l = (s) => {
195
+ const r = f.get(s);
196
+ r && (r.abort(), f.delete(s)), a(s);
197
+ }, g = S(() => e.filter((s) => s.status === "success" && s.fileUrl), [e]);
198
+ function c() {
199
+ f.forEach((s) => s.abort()), f.clear(), t([]);
200
200
  }
201
- return S(() => () => {
202
- l.forEach((s) => s.abort()), l.clear();
201
+ return C(() => () => {
202
+ f.forEach((s) => s.abort()), f.clear();
203
203
  }, []), {
204
204
  allFiles: e,
205
205
  appendFiles: o,
206
- handleCancelUpload: d,
207
- successFiles: m,
208
- emptyTheFiles: p,
206
+ handleCancelUpload: l,
207
+ successFiles: g,
208
+ emptyTheFiles: c,
209
209
  getFileById: (s) => e.find((r) => r.id === s),
210
210
  getUploadProgress: (s) => {
211
211
  var r;
212
- return ((r = e.find((a) => a.id === s)) == null ? void 0 : r.progress) ?? 0;
212
+ return ((r = e.find((u) => u.id === s)) == null ? void 0 : r.progress) ?? 0;
213
213
  },
214
214
  getUploadStatus: (s) => {
215
215
  var r;
216
- return (r = e.find((a) => a.id === s)) == null ? void 0 : r.status;
216
+ return (r = e.find((u) => u.id === s)) == null ? void 0 : r.status;
217
217
  },
218
218
  hasErrors: e.some((s) => s.status === "error"),
219
219
  isUploading: e.some((s) => s.status === "uploading")
220
220
  };
221
221
  }
222
- const W = E(null);
223
- function J({ children: e }) {
224
- const t = b(), [n, o] = h(() => t.inline ? !0 : t.isOpen ?? !1);
225
- return S(() => {
222
+ const A = E(null);
223
+ function H({ children: e }) {
224
+ const t = x(), [n, o] = b(() => t.inline ? !0 : t.isOpen ?? !1);
225
+ return C(() => {
226
226
  o((i) => t.isOpen ?? i);
227
- }, [t.isOpen]), S(() => {
227
+ }, [t.isOpen]), C(() => {
228
228
  const i = t.openAfterNSeconds;
229
229
  if (typeof i != "number" || isNaN(i))
230
230
  return;
231
- const c = setTimeout(() => o(!0), i * 1e3);
232
- return () => clearTimeout(c);
233
- }, [t.openAfterNSeconds]), /* @__PURE__ */ v.createElement(W.Provider, { value: { isOpen: n, setIsOpen: o } }, e);
231
+ const a = setTimeout(() => o(!0), i * 1e3);
232
+ return () => clearTimeout(a);
233
+ }, [t.openAfterNSeconds]), /* @__PURE__ */ v.createElement(A.Provider, { value: { isOpen: n, setIsOpen: o } }, e);
234
234
  }
235
- function K() {
236
- const e = F(W);
235
+ function J() {
236
+ const e = F(A);
237
237
  if (!e)
238
238
  throw new Error(
239
239
  "useWidgetTrigger must be used within a WidgetTriggerProvider"
240
240
  );
241
241
  return e;
242
242
  }
243
- function Q() {
244
- var d, m;
245
- const { widgetCtx: e } = g(), { modesComponents: t } = b(), { sessionState: n } = A(), o = e.modes, i = (d = n.session) == null ? void 0 : d.modeId, c = o.find((p) => p.id === i), u = (m = t == null ? void 0 : t.find(
246
- (p) => {
243
+ function K() {
244
+ var l, g;
245
+ const { widgetCtx: e } = p(), { modesComponents: t } = x(), { sessionState: n } = k(), o = e.modes, i = (l = n.session) == null ? void 0 : l.modeId, a = o.find((c) => c.id === i), d = (g = t == null ? void 0 : t.find(
246
+ (c) => {
247
247
  var s, r;
248
248
  return [
249
- (c == null ? void 0 : c.id) || "",
250
- ((s = c == null ? void 0 : c.name) == null ? void 0 : s.toLowerCase()) || "",
251
- ((r = c == null ? void 0 : c.slug) == null ? void 0 : r.toLowerCase()) || ""
252
- ].includes(p.key.toLowerCase());
249
+ (a == null ? void 0 : a.id) || "",
250
+ ((s = a == null ? void 0 : a.name) == null ? void 0 : s.toLowerCase()) || "",
251
+ ((r = a == null ? void 0 : a.slug) == null ? void 0 : r.toLowerCase()) || ""
252
+ ].includes(c.key.toLowerCase());
253
253
  }
254
- )) == null ? void 0 : m.component;
254
+ )) == null ? void 0 : g.component;
255
255
  return {
256
256
  modes: o,
257
257
  modesComponents: t,
258
258
  activeModeId: i,
259
- activeMode: c,
260
- Component: u
259
+ activeMode: a,
260
+ Component: d
261
+ };
262
+ }
263
+ function Q() {
264
+ const { widgetCtx: e } = p(), {
265
+ messagesState: { messages: t }
266
+ } = U(), {
267
+ csatRequestedMessage: n,
268
+ isCsatRequested: o,
269
+ csatSubmittedMessage: i,
270
+ isCsatSubmitted: a,
271
+ submittedScore: d,
272
+ submittedFeedback: l
273
+ } = S(() => {
274
+ const g = t.find(
275
+ (s) => s.type === "SYSTEM" && s.subtype === "csat_requested"
276
+ ), c = t.findLast(
277
+ (s) => s.type === "SYSTEM" && s.subtype === "csat_submitted"
278
+ );
279
+ return {
280
+ csatRequestedMessage: g,
281
+ isCsatRequested: !!g && !c,
282
+ csatSubmittedMessage: c,
283
+ isCsatSubmitted: !!c,
284
+ submittedScore: c == null ? void 0 : c.data.payload.score,
285
+ submittedFeedback: c == null ? void 0 : c.data.payload.feedback
286
+ };
287
+ }, [t]);
288
+ return {
289
+ submitCsat: e.csatCtx.submitCsat,
290
+ csatRequestedMessage: n,
291
+ isCsatRequested: o,
292
+ csatSubmittedMessage: i,
293
+ isCsatSubmitted: a,
294
+ submittedScore: d,
295
+ submittedFeedback: l
261
296
  };
262
297
  }
263
298
  export {
264
- z as WidgetProvider,
265
- J as WidgetTriggerProvider,
266
- b as useConfig,
267
- _ as useContact,
268
- $ as useDocumentDir,
269
- j as useIsAwaitingBotReply,
270
- T as useMessages,
271
- Q as useModes,
272
- q as usePreludeData,
273
- C as usePrimitiveState,
274
- A as useSessions,
275
- H as useUploadFiles,
276
- g as useWidget,
277
- G as useWidgetRouter,
278
- K as useWidgetTrigger
299
+ I as WidgetProvider,
300
+ H as WidgetTriggerProvider,
301
+ x as useConfig,
302
+ z as useContact,
303
+ Q as useCsat,
304
+ Y as useDocumentDir,
305
+ _ as useIsAwaitingBotReply,
306
+ U as useMessages,
307
+ K as useModes,
308
+ $ as usePreludeData,
309
+ w as usePrimitiveState,
310
+ k as useSessions,
311
+ G as useUploadFiles,
312
+ p as useWidget,
313
+ j as useWidgetRouter,
314
+ J as useWidgetTrigger
279
315
  };
280
316
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/ComponentRegistry.ts","../src/WidgetProvider.tsx","../src/hooks/useConfig.ts","../src/hooks/usePrimitiveState.ts","../src/hooks/useContact.ts","../src/hooks/useDocumentDir.ts","../src/hooks/useMessages.ts","../src/hooks/useSessions.ts","../src/hooks/useIsAwaitingBotReply.ts","../src/hooks/usePreludeData.ts","../src/hooks/useWidgetRouter.ts","../src/hooks/useUploadFiles.ts","../src/hooks/useWidgetTrigger.tsx","../src/hooks/useModes.ts"],"sourcesContent":["import type { WidgetComponentKey } from '@opencx/widget-core';\nimport type { WidgetComponentType } from './types/components';\n\nexport class ComponentRegistry {\n components: WidgetComponentType[] = [];\n\n constructor(opts: { components?: WidgetComponentType[] }) {\n const { components } = opts;\n\n if (components) {\n components.forEach((c) => this.register(c));\n }\n\n if (this.components.length === 0) {\n throw new Error('No components registered');\n }\n if (!this.get('fallback')) {\n throw new Error('No fallback component registered');\n }\n }\n\n // TODO test that this registers or replaces the component\n register(component: WidgetComponentType) {\n // Replace the key if it already exists\n const index = this.components.findIndex((c) => c.key === component.key);\n if (index !== -1) {\n this.components[index] = component;\n } else {\n this.components.push(component);\n }\n return this;\n }\n\n private get(key: WidgetComponentKey) {\n const c = this.components.find(\n (c) => c.key.toUpperCase() === key.toUpperCase(),\n );\n if (c) return c;\n return null;\n }\n\n public getComponent(key: string) {\n return this.get(key)?.component;\n }\n}\n","import React, {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { version } from '../package.json';\nimport { type ExternalStorage, type WidgetConfig, WidgetCtx } from '@opencx/widget-core';\nimport { ComponentRegistry } from './ComponentRegistry';\nimport type { WidgetComponentType } from './types/components';\n\ninterface WidgetProviderValue {\n widgetCtx: WidgetCtx;\n config: WidgetConfig;\n components?: WidgetComponentType[];\n componentStore: ComponentRegistry;\n version: string;\n contentIframeRef?: React.MutableRefObject<HTMLIFrameElement | null>;\n}\n\nconst context = createContext<WidgetProviderValue | null>(null);\n\nexport function WidgetProvider({\n options: config,\n children,\n components,\n storage,\n loadingComponent,\n}: {\n options: WidgetConfig;\n children: React.ReactNode;\n components?: WidgetComponentType[];\n storage?: ExternalStorage;\n /**\n * Custom loading component while the widget is initializing\n * Not to be confused with the `loading` custom component which renders when the bot's reply is pending\n */\n loadingComponent?: React.ReactNode;\n}) {\n const contentIframeRef = useRef<HTMLIFrameElement | null>(null);\n\n const didInitialize = useRef(false);\n const [widgetCtx, setWidgetCtx] = useState<WidgetCtx | null>(null);\n\n const componentStore = useMemo(\n () =>\n new ComponentRegistry({\n components: components,\n }),\n [components],\n );\n\n useEffect(() => {\n if (didInitialize.current) return;\n didInitialize.current = true;\n\n WidgetCtx.initialize({ config, storage }).then(setWidgetCtx);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n if (!widgetCtx) {\n return loadingComponent || null;\n }\n\n return (\n <context.Provider\n value={{\n widgetCtx,\n config,\n components,\n componentStore,\n version,\n contentIframeRef,\n }}\n >\n {children}\n </context.Provider>\n );\n}\n\nexport function useWidget() {\n const ctx = useContext(context);\n if (!ctx) {\n throw new Error('useWidget must be used within a WidgetProvider');\n }\n return ctx;\n}\n","import { useWidget } from '../WidgetProvider';\n\nexport function useConfig() {\n const { config } = useWidget();\n\n return config;\n}\n","import { useSyncExternalStore } from 'react';\nimport type { PrimitiveState } from '@opencx/widget-core';\n\nexport function usePrimitiveState<T>(p: PrimitiveState<T>) {\n return useSyncExternalStore(p.subscribe, p.get, p.get);\n}\n","import { useWidget } from '../WidgetProvider';\nimport { usePrimitiveState } from './usePrimitiveState';\n\nexport function useContact() {\n const { widgetCtx } = useWidget();\n const contactState = usePrimitiveState(widgetCtx.contactCtx.state);\n\n return {\n contactState,\n createUnverifiedContact: widgetCtx.contactCtx.createUnverifiedContact,\n };\n}\n","import { useEffect, useState } from 'react';\nimport type { StringOrLiteral } from '@opencx/widget-core';\n\nexport function useDocumentDir() {\n const [dir, setDir] = useState<StringOrLiteral<'ltr' | 'rtl'>>('ltr');\n\n useEffect(() => {\n const updateDir = () => {\n if (typeof document === 'undefined') return;\n setDir(\n window.getComputedStyle((window.top || window).document.body).direction,\n );\n };\n\n // Set initial direction\n updateDir();\n\n // Watch for direction changes on both document and documentElement\n const observer = new MutationObserver(updateDir);\n\n // Observe both document and documentElement\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['dir'],\n });\n\n observer.observe(document.body, {\n attributes: true,\n attributeFilter: ['dir'],\n });\n\n // Add event listener for dynamic changes\n window.addEventListener('languagechange', updateDir);\n\n return () => {\n observer.disconnect();\n window.removeEventListener('languagechange', updateDir);\n };\n }, []);\n\n return { dir };\n}\n","import { usePrimitiveState } from './usePrimitiveState';\nimport { useWidget } from '../WidgetProvider';\n\nexport function useMessages() {\n const { widgetCtx } = useWidget();\n const messagesState = usePrimitiveState(widgetCtx.messageCtx.state);\n\n return { messagesState, sendMessage: widgetCtx.messageCtx.sendMessage };\n}\n","import { useMemo } from 'react';\nimport { useWidget } from '../WidgetProvider';\nimport { usePrimitiveState } from './usePrimitiveState';\nimport { useConfig } from './useConfig';\n\nexport function useSessions() {\n const { widgetCtx } = useWidget();\n const { oneOpenSessionAllowed } = useConfig();\n const sessionState = usePrimitiveState(widgetCtx.sessionCtx.sessionState);\n const sessionsState = usePrimitiveState(widgetCtx.sessionCtx.sessionsState);\n\n const { openSessions, closedSessions } = useMemo(() => {\n return {\n openSessions: sessionsState.data.filter((s) => s.isOpened === true),\n closedSessions: sessionsState.data.filter((s) => s.isOpened === false),\n };\n }, [sessionsState.data]);\n\n const canCreateNewSession = useMemo(() => {\n if (oneOpenSessionAllowed) {\n return openSessions.length === 0;\n }\n return true;\n }, [oneOpenSessionAllowed, openSessions.length]);\n\n return {\n sessionState,\n sessionsState,\n loadMoreSessions: widgetCtx.sessionCtx.loadMoreSessions,\n resolveSession: widgetCtx.sessionCtx.resolveSession,\n createStateCheckpoint: widgetCtx.sessionCtx.createStateCheckpoint,\n openSessions,\n closedSessions,\n canCreateNewSession,\n };\n}\n","import { useMessages } from './useMessages';\nimport { useSessions } from './useSessions';\n\nexport function useIsAwaitingBotReply() {\n const { sessionState } = useSessions();\n const { messagesState } = useMessages();\n\n const isSessionAssignedToAI = sessionState.session?.assignee.kind === 'ai';\n // This check is useful in cases where the user might navigate in and out of a chat, and `isSendingMessage` is reset back to its default value\n const lastMessage =\n messagesState.messages.length > 0\n ? messagesState.messages[messagesState.messages.length - 1]\n : null;\n const isLastMessageAUserMessage = lastMessage?.type === 'FROM_USER';\n\n const isAwaitingBotReply =\n (isSessionAssignedToAI || sessionState.isCreatingSession) &&\n (messagesState.isSendingMessage || isLastMessageAUserMessage);\n\n return { isAwaitingBotReply };\n}\n","import useSWR from 'swr';\nimport { useWidget } from '../WidgetProvider';\n\nfunction usePreludeData() {\n const { widgetCtx } = useWidget();\n\n // TODO remove swr dependency\n return useSWR([widgetCtx.config.token], widgetCtx.api.widgetPrelude, {\n revalidateOnFocus: false,\n });\n}\n\nexport { usePreludeData };\n","import { useWidget } from '../WidgetProvider';\nimport { usePrimitiveState } from './usePrimitiveState';\n\nexport function useWidgetRouter() {\n const { widgetCtx } = useWidget();\n\n const routerState = usePrimitiveState(widgetCtx.routerCtx.state);\n\n return {\n routerState,\n toSessionsScreen: widgetCtx.routerCtx.toSessionsScreen,\n toChatScreen: widgetCtx.routerCtx.toChatScreen,\n };\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport { useWidget } from '../WidgetProvider';\nimport { v4 } from 'uuid';\n\nconst uploadAbortControllers: Map<string, AbortController> = new Map();\n\ninterface FileWithProgress {\n status: 'pending' | 'uploading' | 'success' | 'error';\n id: string;\n file: File;\n fileUrl?: string;\n progress: number;\n error?: string;\n}\n\nfunction useUploadFiles() {\n const [files, setFiles] = useState<FileWithProgress[]>([]);\n const {\n widgetCtx: { api },\n } = useWidget();\n function appendFiles(files: File[]) {\n const newFiles = files.map((file) => ({\n file,\n id: v4(),\n status: 'pending' as const,\n progress: 0,\n }));\n\n setFiles((prev) => [...prev, ...newFiles]);\n newFiles.forEach(uploadFile);\n }\n\n function updateFileById(id: string, update: Partial<FileWithProgress>) {\n setFiles((prev) =>\n prev.map((f) => (f.id === id ? { ...f, ...update } : f)),\n );\n }\n\n function removeFileById(id: string) {\n setFiles((prev) => prev.filter((f) => f.id !== id));\n }\n\n const uploadFile = async (fileItem: FileWithProgress) => {\n const controller = new AbortController();\n uploadAbortControllers.set(fileItem.id, controller);\n\n try {\n setFiles((prev) =>\n prev.map((f) =>\n f.id === fileItem.id ? { ...f, status: 'uploading', progress: 0 } : f,\n ),\n );\n\n const response = await api.uploadFile({\n file: fileItem.file,\n abortSignal: controller.signal,\n onProgress: (percentage) => {\n updateFileById(fileItem.id, { progress: percentage });\n },\n });\n\n updateFileById(fileItem.id, {\n status: 'success',\n fileUrl: response.fileUrl,\n progress: 100,\n });\n } catch (error) {\n if (!controller.signal.aborted) {\n updateFileById(fileItem.id, {\n status: 'error',\n error: error instanceof Error ? error.message : 'Upload failed',\n progress: 0,\n });\n }\n } finally {\n uploadAbortControllers.delete(fileItem.id);\n }\n };\n\n const handleCancelUpload = (fileId: string) => {\n const controller = uploadAbortControllers.get(fileId);\n if (controller) {\n controller.abort();\n uploadAbortControllers.delete(fileId);\n }\n removeFileById(fileId);\n };\n\n const successFiles = useMemo(() => {\n return files.filter((f) => f.status === 'success' && f.fileUrl);\n }, [files]);\n\n function emptyTheFiles() {\n uploadAbortControllers.forEach((controller) => controller.abort());\n uploadAbortControllers.clear();\n setFiles([]);\n }\n\n useEffect(() => {\n return () => {\n uploadAbortControllers.forEach((controller) => controller.abort());\n uploadAbortControllers.clear();\n };\n }, []);\n\n return {\n allFiles: files,\n appendFiles,\n handleCancelUpload,\n successFiles,\n emptyTheFiles,\n getFileById: (id: string) => files.find((f) => f.id === id),\n getUploadProgress: (id: string) =>\n files.find((f) => f.id === id)?.progress ?? 0,\n getUploadStatus: (id: string) => files.find((f) => f.id === id)?.status,\n hasErrors: files.some((f) => f.status === 'error'),\n isUploading: files.some((f) => f.status === 'uploading'),\n };\n}\n\nexport { useUploadFiles, type FileWithProgress };\n","import React, {\n createContext,\n useContext,\n useEffect,\n useState,\n type Dispatch,\n type ReactNode,\n type SetStateAction,\n} from 'react';\nimport { useConfig } from './useConfig';\n\ntype WidgetTriggerCtx = {\n isOpen: boolean;\n setIsOpen: Dispatch<SetStateAction<boolean>>;\n};\n\nconst context = createContext<WidgetTriggerCtx | null>(null);\n\nexport function WidgetTriggerProvider({ children }: { children: ReactNode }) {\n const config = useConfig();\n const [isOpen, setIsOpen] = useState(() => {\n if (config.inline) return true;\n return config.isOpen ?? false;\n });\n\n useEffect(() => {\n setIsOpen((prev) => config.isOpen ?? prev);\n }, [config.isOpen]);\n\n useEffect(() => {\n const openAfterNSeconds = config.openAfterNSeconds;\n if (typeof openAfterNSeconds !== 'number' || isNaN(openAfterNSeconds))\n return;\n\n const timeout = setTimeout(() => setIsOpen(true), openAfterNSeconds * 1000);\n\n return () => clearTimeout(timeout);\n }, [config.openAfterNSeconds]);\n\n return (\n <context.Provider value={{ isOpen, setIsOpen }}>\n {children}\n </context.Provider>\n );\n}\n\nexport function useWidgetTrigger() {\n const ctx = useContext(context);\n if (!ctx) {\n throw new Error(\n 'useWidgetTrigger must be used within a WidgetTriggerProvider',\n );\n }\n return ctx;\n}\n","import { useWidget } from '../WidgetProvider';\nimport { useConfig } from './useConfig';\nimport { useSessions } from './useSessions';\n\nexport function useModes() {\n const { widgetCtx } = useWidget();\n const { modesComponents } = useConfig();\n const { sessionState } = useSessions();\n\n const modes = widgetCtx.modes;\n const activeModeId = sessionState.session?.modeId;\n const activeMode = modes.find((mode) => mode.id === activeModeId);\n\n const Component = modesComponents?.find((modeComponent) =>\n [\n activeMode?.id || '',\n activeMode?.name?.toLowerCase() || '',\n activeMode?.slug?.toLowerCase() || '',\n ].includes(modeComponent.key.toLowerCase()),\n )?.component;\n\n return {\n modes,\n modesComponents,\n activeModeId,\n activeMode,\n Component,\n };\n}\n"],"names":["ComponentRegistry","opts","components","c","component","index","key","_a","context","createContext","WidgetProvider","config","children","storage","loadingComponent","contentIframeRef","useRef","didInitialize","widgetCtx","setWidgetCtx","useState","componentStore","useMemo","useEffect","WidgetCtx","React","version","useWidget","ctx","useContext","useConfig","usePrimitiveState","p","useSyncExternalStore","useContact","useDocumentDir","dir","setDir","updateDir","observer","useMessages","useSessions","oneOpenSessionAllowed","sessionState","sessionsState","openSessions","closedSessions","s","canCreateNewSession","useIsAwaitingBotReply","messagesState","isSessionAssignedToAI","lastMessage","isLastMessageAUserMessage","usePreludeData","useSWR","useWidgetRouter","uploadAbortControllers","useUploadFiles","files","setFiles","api","appendFiles","newFiles","file","v4","prev","uploadFile","updateFileById","id","update","removeFileById","f","fileItem","controller","response","percentage","error","handleCancelUpload","fileId","successFiles","emptyTheFiles","WidgetTriggerProvider","isOpen","setIsOpen","openAfterNSeconds","timeout","useWidgetTrigger","useModes","modesComponents","modes","activeModeId","activeMode","mode","Component","_b","modeComponent"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/ComponentRegistry.ts","../src/WidgetProvider.tsx","../src/hooks/useConfig.ts","../src/hooks/usePrimitiveState.ts","../src/hooks/useContact.ts","../src/hooks/useDocumentDir.ts","../src/hooks/useMessages.ts","../src/hooks/useSessions.ts","../src/hooks/useIsAwaitingBotReply.ts","../src/hooks/usePreludeData.ts","../src/hooks/useWidgetRouter.ts","../src/hooks/useUploadFiles.ts","../src/hooks/useWidgetTrigger.tsx","../src/hooks/useModes.ts","../src/hooks/useCsat.ts"],"sourcesContent":["import type { WidgetComponentKey } from '@opencx/widget-core';\nimport type { WidgetComponentType } from './types/components';\n\nexport class ComponentRegistry {\n components: WidgetComponentType[] = [];\n\n constructor(opts: { components?: WidgetComponentType[] }) {\n const { components } = opts;\n\n if (components) {\n components.forEach((c) => this.register(c));\n }\n\n if (this.components.length === 0) {\n throw new Error('No components registered');\n }\n if (!this.get('fallback')) {\n throw new Error('No fallback component registered');\n }\n }\n\n // TODO test that this registers or replaces the component\n register(component: WidgetComponentType) {\n // Replace the key if it already exists\n const index = this.components.findIndex((c) => c.key === component.key);\n if (index !== -1) {\n this.components[index] = component;\n } else {\n this.components.push(component);\n }\n return this;\n }\n\n private get(key: WidgetComponentKey) {\n const c = this.components.find(\n (c) => c.key.toUpperCase() === key.toUpperCase(),\n );\n if (c) return c;\n return null;\n }\n\n public getComponent(key: string) {\n return this.get(key)?.component;\n }\n}\n","import React, {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { version } from '../package.json';\nimport { type ExternalStorage, type WidgetConfig, WidgetCtx } from '@opencx/widget-core';\nimport { ComponentRegistry } from './ComponentRegistry';\nimport type { WidgetComponentType } from './types/components';\n\ninterface WidgetProviderValue {\n widgetCtx: WidgetCtx;\n config: WidgetConfig;\n components?: WidgetComponentType[];\n componentStore: ComponentRegistry;\n version: string;\n contentIframeRef?: React.MutableRefObject<HTMLIFrameElement | null>;\n}\n\nconst context = createContext<WidgetProviderValue | null>(null);\n\nexport function WidgetProvider({\n options: config,\n children,\n components,\n storage,\n loadingComponent,\n}: {\n options: WidgetConfig;\n children: React.ReactNode;\n components?: WidgetComponentType[];\n storage?: ExternalStorage;\n /**\n * Custom loading component while the widget is initializing\n * Not to be confused with the `loading` custom component which renders when the bot's reply is pending\n */\n loadingComponent?: React.ReactNode;\n}) {\n const contentIframeRef = useRef<HTMLIFrameElement | null>(null);\n\n const didInitialize = useRef(false);\n const [widgetCtx, setWidgetCtx] = useState<WidgetCtx | null>(null);\n\n const componentStore = useMemo(\n () =>\n new ComponentRegistry({\n components: components,\n }),\n [components],\n );\n\n useEffect(() => {\n if (didInitialize.current) return;\n didInitialize.current = true;\n\n WidgetCtx.initialize({ config, storage }).then(setWidgetCtx);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n if (!widgetCtx) {\n return loadingComponent || null;\n }\n\n return (\n <context.Provider\n value={{\n widgetCtx,\n config,\n components,\n componentStore,\n version,\n contentIframeRef,\n }}\n >\n {children}\n </context.Provider>\n );\n}\n\nexport function useWidget() {\n const ctx = useContext(context);\n if (!ctx) {\n throw new Error('useWidget must be used within a WidgetProvider');\n }\n return ctx;\n}\n","import { useWidget } from '../WidgetProvider';\n\nexport function useConfig() {\n const { config } = useWidget();\n\n return config;\n}\n","import { useSyncExternalStore } from 'react';\nimport type { PrimitiveState } from '@opencx/widget-core';\n\nexport function usePrimitiveState<T>(p: PrimitiveState<T>) {\n return useSyncExternalStore(p.subscribe, p.get, p.get);\n}\n","import { useWidget } from '../WidgetProvider';\nimport { usePrimitiveState } from './usePrimitiveState';\n\nexport function useContact() {\n const { widgetCtx } = useWidget();\n const contactState = usePrimitiveState(widgetCtx.contactCtx.state);\n\n return {\n contactState,\n createUnverifiedContact: widgetCtx.contactCtx.createUnverifiedContact,\n };\n}\n","import { useEffect, useState } from 'react';\nimport type { StringOrLiteral } from '@opencx/widget-core';\n\nexport function useDocumentDir() {\n const [dir, setDir] = useState<StringOrLiteral<'ltr' | 'rtl'>>('ltr');\n\n useEffect(() => {\n const updateDir = () => {\n if (typeof document === 'undefined') return;\n setDir(\n window.getComputedStyle((window.top || window).document.body).direction,\n );\n };\n\n // Set initial direction\n updateDir();\n\n // Watch for direction changes on both document and documentElement\n const observer = new MutationObserver(updateDir);\n\n // Observe both document and documentElement\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['dir'],\n });\n\n observer.observe(document.body, {\n attributes: true,\n attributeFilter: ['dir'],\n });\n\n // Add event listener for dynamic changes\n window.addEventListener('languagechange', updateDir);\n\n return () => {\n observer.disconnect();\n window.removeEventListener('languagechange', updateDir);\n };\n }, []);\n\n return { dir };\n}\n","import { usePrimitiveState } from './usePrimitiveState';\nimport { useWidget } from '../WidgetProvider';\n\nexport function useMessages() {\n const { widgetCtx } = useWidget();\n const messagesState = usePrimitiveState(widgetCtx.messageCtx.state);\n\n return { messagesState, sendMessage: widgetCtx.messageCtx.sendMessage };\n}\n","import { useMemo } from 'react';\nimport { useWidget } from '../WidgetProvider';\nimport { usePrimitiveState } from './usePrimitiveState';\nimport { useConfig } from './useConfig';\n\nexport function useSessions() {\n const { widgetCtx } = useWidget();\n const { oneOpenSessionAllowed } = useConfig();\n const sessionState = usePrimitiveState(widgetCtx.sessionCtx.sessionState);\n const sessionsState = usePrimitiveState(widgetCtx.sessionCtx.sessionsState);\n\n const { openSessions, closedSessions } = useMemo(() => {\n return {\n openSessions: sessionsState.data.filter((s) => s.isOpened === true),\n closedSessions: sessionsState.data.filter((s) => s.isOpened === false),\n };\n }, [sessionsState.data]);\n\n const canCreateNewSession = useMemo(() => {\n if (oneOpenSessionAllowed) {\n return openSessions.length === 0;\n }\n return true;\n }, [oneOpenSessionAllowed, openSessions.length]);\n\n return {\n sessionState,\n sessionsState,\n loadMoreSessions: widgetCtx.sessionCtx.loadMoreSessions,\n resolveSession: widgetCtx.sessionCtx.resolveSession,\n createStateCheckpoint: widgetCtx.sessionCtx.createStateCheckpoint,\n openSessions,\n closedSessions,\n canCreateNewSession,\n };\n}\n","import { useMessages } from './useMessages';\nimport { useSessions } from './useSessions';\n\nexport function useIsAwaitingBotReply() {\n const { sessionState } = useSessions();\n const { messagesState } = useMessages();\n\n const isSessionAssignedToAI = sessionState.session?.assignee.kind === 'ai';\n // This check is useful in cases where the user might navigate in and out of a chat, and `isSendingMessage` is reset back to its default value\n const lastMessage =\n messagesState.messages.length > 0\n ? messagesState.messages[messagesState.messages.length - 1]\n : null;\n const isLastMessageAUserMessage = lastMessage?.type === 'USER';\n\n const isAwaitingBotReply =\n (isSessionAssignedToAI || sessionState.isCreatingSession) &&\n (messagesState.isSendingMessage || isLastMessageAUserMessage);\n\n return { isAwaitingBotReply };\n}\n","import useSWR from 'swr';\nimport { useWidget } from '../WidgetProvider';\n\nfunction usePreludeData() {\n const { widgetCtx } = useWidget();\n\n // TODO remove swr dependency\n return useSWR([widgetCtx.config.token], widgetCtx.api.widgetPrelude, {\n revalidateOnFocus: false,\n });\n}\n\nexport { usePreludeData };\n","import { useWidget } from '../WidgetProvider';\nimport { usePrimitiveState } from './usePrimitiveState';\n\nexport function useWidgetRouter() {\n const { widgetCtx } = useWidget();\n\n const routerState = usePrimitiveState(widgetCtx.routerCtx.state);\n\n return {\n routerState,\n toSessionsScreen: widgetCtx.routerCtx.toSessionsScreen,\n toChatScreen: widgetCtx.routerCtx.toChatScreen,\n };\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport { useWidget } from '../WidgetProvider';\nimport { v4 } from 'uuid';\n\nconst uploadAbortControllers: Map<string, AbortController> = new Map();\n\ninterface FileWithProgress {\n status: 'pending' | 'uploading' | 'success' | 'error';\n id: string;\n file: File;\n fileUrl?: string;\n progress: number;\n error?: string;\n}\n\nfunction useUploadFiles() {\n const [files, setFiles] = useState<FileWithProgress[]>([]);\n const {\n widgetCtx: { api },\n } = useWidget();\n function appendFiles(files: File[]) {\n const newFiles = files.map((file) => ({\n file,\n id: v4(),\n status: 'pending' as const,\n progress: 0,\n }));\n\n setFiles((prev) => [...prev, ...newFiles]);\n newFiles.forEach(uploadFile);\n }\n\n function updateFileById(id: string, update: Partial<FileWithProgress>) {\n setFiles((prev) =>\n prev.map((f) => (f.id === id ? { ...f, ...update } : f)),\n );\n }\n\n function removeFileById(id: string) {\n setFiles((prev) => prev.filter((f) => f.id !== id));\n }\n\n const uploadFile = async (fileItem: FileWithProgress) => {\n const controller = new AbortController();\n uploadAbortControllers.set(fileItem.id, controller);\n\n try {\n setFiles((prev) =>\n prev.map((f) =>\n f.id === fileItem.id ? { ...f, status: 'uploading', progress: 0 } : f,\n ),\n );\n\n const response = await api.uploadFile({\n file: fileItem.file,\n abortSignal: controller.signal,\n onProgress: (percentage) => {\n updateFileById(fileItem.id, { progress: percentage });\n },\n });\n\n updateFileById(fileItem.id, {\n status: 'success',\n fileUrl: response.fileUrl,\n progress: 100,\n });\n } catch (error) {\n if (!controller.signal.aborted) {\n updateFileById(fileItem.id, {\n status: 'error',\n error: error instanceof Error ? error.message : 'Upload failed',\n progress: 0,\n });\n }\n } finally {\n uploadAbortControllers.delete(fileItem.id);\n }\n };\n\n const handleCancelUpload = (fileId: string) => {\n const controller = uploadAbortControllers.get(fileId);\n if (controller) {\n controller.abort();\n uploadAbortControllers.delete(fileId);\n }\n removeFileById(fileId);\n };\n\n const successFiles = useMemo(() => {\n return files.filter((f) => f.status === 'success' && f.fileUrl);\n }, [files]);\n\n function emptyTheFiles() {\n uploadAbortControllers.forEach((controller) => controller.abort());\n uploadAbortControllers.clear();\n setFiles([]);\n }\n\n useEffect(() => {\n return () => {\n uploadAbortControllers.forEach((controller) => controller.abort());\n uploadAbortControllers.clear();\n };\n }, []);\n\n return {\n allFiles: files,\n appendFiles,\n handleCancelUpload,\n successFiles,\n emptyTheFiles,\n getFileById: (id: string) => files.find((f) => f.id === id),\n getUploadProgress: (id: string) =>\n files.find((f) => f.id === id)?.progress ?? 0,\n getUploadStatus: (id: string) => files.find((f) => f.id === id)?.status,\n hasErrors: files.some((f) => f.status === 'error'),\n isUploading: files.some((f) => f.status === 'uploading'),\n };\n}\n\nexport { useUploadFiles, type FileWithProgress };\n","import React, {\n createContext,\n useContext,\n useEffect,\n useState,\n type Dispatch,\n type ReactNode,\n type SetStateAction,\n} from 'react';\nimport { useConfig } from './useConfig';\n\ntype WidgetTriggerCtx = {\n isOpen: boolean;\n setIsOpen: Dispatch<SetStateAction<boolean>>;\n};\n\nconst context = createContext<WidgetTriggerCtx | null>(null);\n\nexport function WidgetTriggerProvider({ children }: { children: ReactNode }) {\n const config = useConfig();\n const [isOpen, setIsOpen] = useState(() => {\n if (config.inline) return true;\n return config.isOpen ?? false;\n });\n\n useEffect(() => {\n setIsOpen((prev) => config.isOpen ?? prev);\n }, [config.isOpen]);\n\n useEffect(() => {\n const openAfterNSeconds = config.openAfterNSeconds;\n if (typeof openAfterNSeconds !== 'number' || isNaN(openAfterNSeconds))\n return;\n\n const timeout = setTimeout(() => setIsOpen(true), openAfterNSeconds * 1000);\n\n return () => clearTimeout(timeout);\n }, [config.openAfterNSeconds]);\n\n return (\n <context.Provider value={{ isOpen, setIsOpen }}>\n {children}\n </context.Provider>\n );\n}\n\nexport function useWidgetTrigger() {\n const ctx = useContext(context);\n if (!ctx) {\n throw new Error(\n 'useWidgetTrigger must be used within a WidgetTriggerProvider',\n );\n }\n return ctx;\n}\n","import { useWidget } from '../WidgetProvider';\nimport { useConfig } from './useConfig';\nimport { useSessions } from './useSessions';\n\nexport function useModes() {\n const { widgetCtx } = useWidget();\n const { modesComponents } = useConfig();\n const { sessionState } = useSessions();\n\n const modes = widgetCtx.modes;\n const activeModeId = sessionState.session?.modeId;\n const activeMode = modes.find((mode) => mode.id === activeModeId);\n\n const Component = modesComponents?.find((modeComponent) =>\n [\n activeMode?.id || '',\n activeMode?.name?.toLowerCase() || '',\n activeMode?.slug?.toLowerCase() || '',\n ].includes(modeComponent.key.toLowerCase()),\n )?.component;\n\n return {\n modes,\n modesComponents,\n activeModeId,\n activeMode,\n Component,\n };\n}\n","import type {\n WidgetSystemMessage__CsatRequested,\n WidgetSystemMessage__CsatSubmitted,\n} from '@opencx/widget-core';\nimport { useMemo } from 'react';\nimport { useMessages } from './useMessages';\nimport { useWidget } from '../WidgetProvider';\n\nexport function useCsat() {\n const { widgetCtx } = useWidget();\n const {\n messagesState: { messages },\n } = useMessages();\n\n const {\n csatRequestedMessage,\n isCsatRequested,\n csatSubmittedMessage,\n isCsatSubmitted,\n submittedScore,\n submittedFeedback,\n } = useMemo(() => {\n const csatRequestedMessage = messages.find(\n (message): message is WidgetSystemMessage__CsatRequested =>\n message.type === 'SYSTEM' && message.subtype === 'csat_requested',\n );\n const csatSubmittedMessage = messages.findLast(\n (message): message is WidgetSystemMessage__CsatSubmitted =>\n message.type === 'SYSTEM' && message.subtype === 'csat_submitted',\n );\n\n return {\n csatRequestedMessage,\n isCsatRequested: !!csatRequestedMessage && !csatSubmittedMessage,\n csatSubmittedMessage,\n isCsatSubmitted: !!csatSubmittedMessage,\n submittedScore: csatSubmittedMessage?.data.payload.score,\n submittedFeedback: csatSubmittedMessage?.data.payload.feedback,\n };\n }, [messages]);\n\n return {\n submitCsat: widgetCtx.csatCtx.submitCsat,\n csatRequestedMessage,\n isCsatRequested,\n csatSubmittedMessage,\n isCsatSubmitted,\n submittedScore,\n submittedFeedback,\n };\n}\n"],"names":["ComponentRegistry","opts","components","c","component","index","key","_a","context","createContext","WidgetProvider","config","children","storage","loadingComponent","contentIframeRef","useRef","didInitialize","widgetCtx","setWidgetCtx","useState","componentStore","useMemo","useEffect","WidgetCtx","React","version","useWidget","ctx","useContext","useConfig","usePrimitiveState","p","useSyncExternalStore","useContact","useDocumentDir","dir","setDir","updateDir","observer","useMessages","useSessions","oneOpenSessionAllowed","sessionState","sessionsState","openSessions","closedSessions","s","canCreateNewSession","useIsAwaitingBotReply","messagesState","isSessionAssignedToAI","lastMessage","isLastMessageAUserMessage","usePreludeData","useSWR","useWidgetRouter","uploadAbortControllers","useUploadFiles","files","setFiles","api","appendFiles","newFiles","file","v4","prev","uploadFile","updateFileById","id","update","f","removeFileById","fileItem","controller","response","percentage","error","handleCancelUpload","fileId","successFiles","emptyTheFiles","WidgetTriggerProvider","isOpen","setIsOpen","openAfterNSeconds","timeout","useWidgetTrigger","useModes","modesComponents","modes","activeModeId","activeMode","mode","Component","_b","modeComponent","useCsat","messages","csatRequestedMessage","isCsatRequested","csatSubmittedMessage","isCsatSubmitted","submittedScore","submittedFeedback","message"],"mappings":"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"}
@@ -8,3 +8,4 @@ export declare class ComponentRegistry {
8
8
  private get;
9
9
  getComponent(key: string): import('react').ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
10
10
  }
11
+ //# sourceMappingURL=ComponentRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ComponentRegistry.d.ts","sourceRoot":"","sources":["../../src/ComponentRegistry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,qBAAa,iBAAiB;IAC5B,UAAU,EAAE,mBAAmB,EAAE,CAAM;gBAE3B,IAAI,EAAE;QAAE,UAAU,CAAC,EAAE,mBAAmB,EAAE,CAAA;KAAE;IAgBxD,QAAQ,CAAC,SAAS,EAAE,mBAAmB;IAWvC,OAAO,CAAC,GAAG;IAQJ,YAAY,CAAC,GAAG,EAAE,MAAM;CAGhC"}
@@ -23,3 +23,4 @@ export declare function WidgetProvider({ options: config, children, components,
23
23
  }): string | number | bigint | true | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | React.JSX.Element | null;
24
24
  export declare function useWidget(): WidgetProviderValue;
25
25
  export {};
26
+ //# sourceMappingURL=WidgetProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WidgetProvider.d.ts","sourceRoot":"","sources":["../../src/WidgetProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAON,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,UAAU,mBAAmB;IAC3B,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACnC,cAAc,EAAE,iBAAiB,CAAC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;CACrE;AAID,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EAAE,MAAM,EACf,QAAQ,EACR,UAAU,EACV,OAAO,EACP,gBAAgB,GACjB,EAAE;IACD,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACnC,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACpC,oRAwCA;AAED,wBAAgB,SAAS,wBAMxB"}
@@ -1 +1,2 @@
1
1
  export declare function useConfig(): import('@opencx/widget-core').WidgetConfig;
2
+ //# sourceMappingURL=useConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useConfig.d.ts","sourceRoot":"","sources":["../../../src/hooks/useConfig.ts"],"names":[],"mappings":"AAEA,wBAAgB,SAAS,+CAIxB"}
@@ -16,3 +16,4 @@ export declare function useContact(): {
16
16
  };
17
17
  }, extraCollectedData?: Record<string, string>) => Promise<void>;
18
18
  };
19
+ //# sourceMappingURL=useContact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useContact.d.ts","sourceRoot":"","sources":["../../../src/hooks/useContact.ts"],"names":[],"mappings":"AAGA,wBAAgB,UAAU;;;;;;;;;;;;;;;;;EAQzB"}
@@ -0,0 +1,28 @@
1
+ import { WidgetSystemMessage__CsatRequested, WidgetSystemMessage__CsatSubmitted } from '@opencx/widget-core';
2
+ export declare function useCsat(): {
3
+ submitCsat: (body: Pick<{
4
+ session_id: string;
5
+ score: number;
6
+ feedback?: string;
7
+ system_message_uuid?: string;
8
+ }, "score" | "feedback">) => Promise<{
9
+ data: null;
10
+ error: string;
11
+ } | {
12
+ data: {
13
+ success: boolean;
14
+ } | undefined;
15
+ error: {
16
+ statusCode?: number;
17
+ message?: string;
18
+ error?: string;
19
+ } | undefined;
20
+ }>;
21
+ csatRequestedMessage: WidgetSystemMessage__CsatRequested | undefined;
22
+ isCsatRequested: boolean;
23
+ csatSubmittedMessage: WidgetSystemMessage__CsatSubmitted | undefined;
24
+ isCsatSubmitted: boolean;
25
+ submittedScore: number | null | undefined;
26
+ submittedFeedback: string | null | undefined;
27
+ };
28
+ //# sourceMappingURL=useCsat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCsat.d.ts","sourceRoot":"","sources":["../../../src/hooks/useCsat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kCAAkC,EAClC,kCAAkC,EACnC,MAAM,qBAAqB,CAAC;AAK7B,wBAAgB,OAAO;;;;;;;;;;;;;;sBAkBuB,CAAC;mBACtB,CAAA;iBAA2B,CAAC;;;;;;;;;EAuBpD"}
@@ -2,3 +2,4 @@ import { StringOrLiteral } from '@opencx/widget-core';
2
2
  export declare function useDocumentDir(): {
3
3
  dir: StringOrLiteral<"ltr" | "rtl">;
4
4
  };
5
+ //# sourceMappingURL=useDocumentDir.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDocumentDir.d.ts","sourceRoot":"","sources":["../../../src/hooks/useDocumentDir.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,wBAAgB,cAAc;;EAsC7B"}
@@ -1,3 +1,4 @@
1
1
  export declare function useIsAwaitingBotReply(): {
2
2
  isAwaitingBotReply: boolean;
3
3
  };
4
+ //# sourceMappingURL=useIsAwaitingBotReply.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useIsAwaitingBotReply.d.ts","sourceRoot":"","sources":["../../../src/hooks/useIsAwaitingBotReply.ts"],"names":[],"mappings":"AAGA,wBAAgB,qBAAqB;;EAiBpC"}
@@ -1,6 +1,6 @@
1
1
  export declare function useMessages(): {
2
2
  messagesState: {
3
- messages: import('@opencx/widget-core').MessageType[];
3
+ messages: import('@opencx/widget-core').WidgetMessageU[];
4
4
  isSendingMessage: boolean;
5
5
  lastAIResMightSolveUserIssue: boolean;
6
6
  isInitialFetchLoading: boolean;
@@ -12,3 +12,4 @@ export declare function useMessages(): {
12
12
  exitModePrompt?: string;
13
13
  }) => Promise<void>;
14
14
  };
15
+ //# sourceMappingURL=useMessages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMessages.d.ts","sourceRoot":"","sources":["../../../src/hooks/useMessages.ts"],"names":[],"mappings":"AAGA,wBAAgB,WAAW;;;;;;;;;mBAM8pB,CAAC;kBAAmD,CAAC;sBAAuD,CAAC;;EADryB"}
@@ -13,3 +13,4 @@ export declare function useModes(): {
13
13
  } | undefined;
14
14
  Component: ((props: import('@opencx/widget-core').ModeComponentProps) => ReturnType<typeof React.createElement>) | undefined;
15
15
  };
16
+ //# sourceMappingURL=useModes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useModes.d.ts","sourceRoot":"","sources":["../../../src/hooks/useModes.ts"],"names":[],"mappings":"AAIA,wBAAgB,QAAQ;;;;;;;;;;;;;;EAwBvB"}
@@ -83,3 +83,4 @@ declare function usePreludeData(): import('swr').SWRResponse<import('openapi-fet
83
83
  revalidateOnFocus: false;
84
84
  }>;
85
85
  export { usePreludeData };
86
+ //# sourceMappingURL=usePreludeData.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePreludeData.d.ts","sourceRoot":"","sources":["../../../src/hooks/usePreludeData.ts"],"names":[],"mappings":"AAGA,iBAAS,cAAc;;aAUutC,CAAC;;;;YAAqG,CAAC;cAA2B,CAAC;;;;;;;;;;;;;8BAA62T,CAAC;;;;+BAAgH,CAAC;;;;iCAAkH,CAAC;;;;gCAAiH,CAAC;;;;8BAA+G,CAAC;;;;gCAAiH,CAAC;;;;8BAA+G,CAAC;;;;gCAAiH,CAAC;;;;gCAAiH,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAH1mY;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -1,2 +1,3 @@
1
1
  import { PrimitiveState } from '@opencx/widget-core';
2
2
  export declare function usePrimitiveState<T>(p: PrimitiveState<T>): T;
3
+ //# sourceMappingURL=usePrimitiveState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePrimitiveState.d.ts","sourceRoot":"","sources":["../../../src/hooks/usePrimitiveState.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,KAExD"}
@@ -25,7 +25,7 @@ export declare function useSessions(): {
25
25
  isHandedOff: boolean;
26
26
  isOpened: boolean;
27
27
  assignee: {
28
- kind: "human" | "ai" | "none" | "unknown";
28
+ kind: "human" | "ai" | "none";
29
29
  name: string | null;
30
30
  avatarUrl: string | null;
31
31
  };
@@ -71,7 +71,7 @@ export declare function useSessions(): {
71
71
  isHandedOff: boolean;
72
72
  isOpened: boolean;
73
73
  assignee: {
74
- kind: "human" | "ai" | "none" | "unknown";
74
+ kind: "human" | "ai" | "none";
75
75
  name: string | null;
76
76
  avatarUrl: string | null;
77
77
  };
@@ -90,7 +90,7 @@ export declare function useSessions(): {
90
90
  isHandedOff: boolean;
91
91
  isOpened: boolean;
92
92
  assignee: {
93
- kind: "human" | "ai" | "none" | "unknown";
93
+ kind: "human" | "ai" | "none";
94
94
  name: string | null;
95
95
  avatarUrl: string | null;
96
96
  };
@@ -104,3 +104,4 @@ export declare function useSessions(): {
104
104
  }[];
105
105
  canCreateNewSession: boolean;
106
106
  };
107
+ //# sourceMappingURL=useSessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSessions.d.ts","sourceRoot":"","sources":["../../../src/hooks/useSessions.ts"],"names":[],"mappings":"AAKA,wBAAgB,WAAW;;;;;;;;;;;;;;;;;qBA+B0rC,CAAC;;;;;;;;;;;;;;;;;;;;;;sBAA0sB,CAAC;;;;sBAAwG,CAAC;mBAA6B,CAAC;iBAA2B,CAAC;;qBAA0C,CAAC;;;;;;;;wBAAwN,CAAC;sBAAmC,CAAC;;;;sBAAwG,CAAC;mBAA6B,CAAC;iBAA2B,CAAC;;qBAA0C,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EADzjF"}
@@ -19,3 +19,4 @@ declare function useUploadFiles(): {
19
19
  isUploading: boolean;
20
20
  };
21
21
  export { useUploadFiles, type FileWithProgress };
22
+ //# sourceMappingURL=useUploadFiles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useUploadFiles.d.ts","sourceRoot":"","sources":["../../../src/hooks/useUploadFiles.ts"],"names":[],"mappings":"AAMA,UAAU,gBAAgB;IACxB,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;IACtD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,iBAAS,cAAc;;yBAKO,IAAI,EAAE;iCA2DE,MAAM;;;sBAgCtB,MAAM;4BACA,MAAM;0BAER,MAAM;;;EAI/B;AAED,OAAO,EAAE,cAAc,EAAE,KAAK,gBAAgB,EAAE,CAAC"}
@@ -5,3 +5,4 @@ export declare function useWidgetRouter(): {
5
5
  toSessionsScreen: () => void;
6
6
  toChatScreen: (sessionId?: string) => void;
7
7
  };
8
+ //# sourceMappingURL=useWidgetRouter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWidgetRouter.d.ts","sourceRoot":"","sources":["../../../src/hooks/useWidgetRouter.ts"],"names":[],"mappings":"AAGA,wBAAgB,eAAe;;;;;;EAU9B"}
@@ -8,3 +8,4 @@ export declare function WidgetTriggerProvider({ children }: {
8
8
  }): React.JSX.Element;
9
9
  export declare function useWidgetTrigger(): WidgetTriggerCtx;
10
10
  export {};
11
+ //# sourceMappingURL=useWidgetTrigger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWidgetTrigger.d.ts","sourceRoot":"","sources":["../../../src/hooks/useWidgetTrigger.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAKZ,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,cAAc,EACpB,MAAM,OAAO,CAAC;AAGf,KAAK,gBAAgB,GAAG;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;CAC9C,CAAC;AAIF,wBAAgB,qBAAqB,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,qBA0B1E;AAED,wBAAgB,gBAAgB,qBAQ/B"}
@@ -12,3 +12,5 @@ export { useWidgetRouter } from './hooks/useWidgetRouter';
12
12
  export { type FileWithProgress, useUploadFiles } from './hooks/useUploadFiles';
13
13
  export { useWidgetTrigger, WidgetTriggerProvider, } from './hooks/useWidgetTrigger';
14
14
  export { useModes } from './hooks/useModes';
15
+ export { useCsat } from './hooks/useCsat';
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7D,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,KAAK,gBAAgB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EACL,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1,7 +1,8 @@
1
1
  import { default as React } from 'react';
2
- import { AgentMessageType, BotMessageType, WidgetComponentKey } from '@opencx/widget-core';
3
- export type WidgetComponentProps<TData = unknown> = BotMessageType<TData> | AgentMessageType;
2
+ import { WidgetAgentMessage, WidgetAiMessage, WidgetComponentKey, WidgetSystemMessageU } from '@opencx/widget-core';
3
+ export type WidgetComponentProps<TData = unknown> = WidgetAiMessage<TData> | WidgetAgentMessage | WidgetSystemMessageU;
4
4
  export type WidgetComponentType = {
5
5
  key: WidgetComponentKey;
6
6
  component: React.ElementType;
7
7
  };
8
+ //# sourceMappingURL=components.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../../src/types/components.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EACV,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,oBAAoB,EACrB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,MAAM,oBAAoB,CAAC,KAAK,GAAG,OAAO,IAC5C,eAAe,CAAC,KAAK,CAAC,GACtB,kBAAkB,GAClB,oBAAoB,CAAC;AAEzB,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,EAAE,kBAAkB,CAAC;IACxB,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC;CAC9B,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@opencx/widget-react-headless",
3
3
  "private": false,
4
- "version": "4.0.10",
4
+ "version": "4.0.12",
5
5
  "type": "module",
6
6
  "repository": {
7
7
  "type": "git",
@@ -20,7 +20,7 @@
20
20
  "dependencies": {
21
21
  "swr": "^2.2.5",
22
22
  "uuid": "^11.0.4",
23
- "@opencx/widget-core": "4.0.10"
23
+ "@opencx/widget-core": "4.0.12"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "@types/react": ">=18 <20",
@@ -29,7 +29,7 @@
29
29
  "react-dom": ">=18 <20"
30
30
  },
31
31
  "devDependencies": {
32
- "@opencx/tsconfig": "0.0.0",
32
+ "@opencx/tsconfig": "0.0.1",
33
33
  "@opencx/eslint-config": "0.0.0"
34
34
  },
35
35
  "scripts": {