@opencx/widget-react-headless 4.0.25 → 4.0.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("react"),v=require("@opencx/widget-core"),M=require("uuid"),F="4.0.25";class R{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 U({options:e,children:t,components:n,storage:o,loadingComponent:u}){const a=i.useRef(null),l=i.useRef(!1),[g,f]=i.useState(null),c=i.useMemo(()=>new R({components:n}),[n]);return i.useEffect(()=>{l.current||(l.current=!0,v.WidgetCtx.initialize({config:e,storage:o}).then(f).catch(console.error))},[]),g?i.createElement(y.Provider,{value:{widgetCtx:g,config:e,components:n,componentStore:c,version:F,contentIframeRef:a}},t):u||null}function p(){const e=i.useContext(y);if(!e)throw new Error("useWidget must be used within a WidgetProvider");return e}function w(){const{config:e}=p();return e}function m(e){return i.useSyncExternalStore(e.subscribe,e.get,e.get)}function W(){const{widgetCtx:e}=p();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 h(){const{widgetCtx:e}=p();return{messagesState:m(e.messageCtx.state),sendMessage:e.messageCtx.sendMessage}}function x(){const{widgetCtx:e}=p(),{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 P(){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}=p();return{routerState:m(e.routerCtx.state),toSessionsScreen:e.routerCtx.toSessionsScreen,toChatScreen:e.routerCtx.toChatScreen}}const S=new Map;function k(){const[e,t]=i.useState([]),{widgetCtx:{api:n}}=p();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)},f=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:f,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 E=i.createContext(null);function O({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(E.Provider,{value:{isOpen:n,setIsOpen:o}},e)}function q(){const e=i.useContext(E);if(!e)throw new Error("useWidgetTrigger must be used within a WidgetTriggerProvider");return e}function N(){var g,f;const{widgetCtx:e}=p(),{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=(f=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:f.component;return{modes:o,modesComponents:t,activeModeId:u,activeMode:a,Component:l}}function B(){const{widgetCtx:e}=p(),{messagesState:{messages:t}}=h(),{csatRequestedMessage:n,isCsatRequested:o,csatSubmittedMessage:u,isCsatSubmitted:a,submittedScore:l,submittedFeedback:g}=i.useMemo(()=>{const f=t.find(s=>s.type==="SYSTEM"&&s.subtype==="csat_requested"),c=t.findLast(s=>s.type==="SYSTEM"&&s.subtype==="csat_submitted");return{csatRequestedMessage:f,isCsatRequested:!!f&&!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=U;exports.WidgetTriggerProvider=O;exports.useConfig=w;exports.useContact=W;exports.useCsat=B;exports.useDocumentDir=A;exports.useIsAwaitingBotReply=P;exports.useMessages=h;exports.useModes=N;exports.usePrimitiveState=m;exports.useSessions=x;exports.useUploadFiles=k;exports.useWidget=p;exports.useWidgetRouter=T;exports.useWidgetTrigger=q;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("react"),v=require("@opencx/widget-core"),M=require("uuid"),F="4.0.28";class R{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=u.createContext(null);function U({options:e,children:t,components:n,storage:o,loadingComponent:a}){const i=u.useRef(null),g=u.useRef(!1),[d,f]=u.useState(null),c=u.useMemo(()=>new R({components:n}),[n]);return u.useEffect(()=>{g.current||(g.current=!0,v.WidgetCtx.initialize({config:e,storage:o}).then(f).catch(console.error))},[]),d?u.createElement(y.Provider,{value:{widgetCtx:d,config:e,components:n,componentStore:c,version:F,contentIframeRef:i}},t):a||null}function p(){const e=u.useContext(y);if(!e)throw new Error("useWidget must be used within a WidgetProvider");return e}function w(){const{config:e}=p();return e}function m(e){return u.useSyncExternalStore(e.subscribe,e.get,e.get)}function W(){const{widgetCtx:e}=p();return{contactState:m(e.contactCtx.state),createUnverifiedContact:e.contactCtx.createUnverifiedContact}}function A(){const[e,t]=u.useState("ltr");return u.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}=p();return{messagesState:m(e.messageCtx.state),sendMessage:e.messageCtx.sendMessage}}function x(){const{widgetCtx:e}=p(),{oneOpenSessionAllowed:t}=w(),n=m(e.sessionCtx.sessionState),o=m(e.sessionCtx.sessionsState),{openSessions:a,closedSessions:i}=u.useMemo(()=>({openSessions:o.data.filter(d=>d.isOpened===!0),closedSessions:o.data.filter(d=>d.isOpened===!1)}),[o.data]),g=u.useMemo(()=>t?a.length===0:!0,[t,a.length]);return{sessionState:n,sessionsState:o,loadMoreSessions:e.sessionCtx.loadMoreSessions,resolveSession:e.sessionCtx.resolveSession,createStateCheckpoint:e.sessionCtx.createStateCheckpoint,openSessions:a,closedSessions:i,canCreateNewSession:g}}function T(){var i,g,d;const{sessionState:e}=x(),{messagesState:t}=h(),n=((i=e.session)==null?void 0:i.assignee.kind)==="ai",o=((d=(g=t.messages)==null?void 0:g.at(-1))==null?void 0:d.type)==="USER";return{isAwaitingBotReply:!!(t.isSendingMessageToAI||(n||e.isCreatingSession)&&(t.isSendingMessage||o))}}function P(){const{widgetCtx:e}=p();return{routerState:m(e.routerCtx.state),toSessionsScreen:e.routerCtx.toSessionsScreen,toChatScreen:e.routerCtx.toChatScreen}}const S=new Map;function k(){const[e,t]=u.useState([]),{widgetCtx:{api:n}}=p();function o(s){const r=s.map(l=>({file:l,id:M.v4(),status:"pending",progress:0}));t(l=>[...l,...r]),r.forEach(g)}function a(s,r){t(l=>l.map(C=>C.id===s?{...C,...r}:C))}function i(s){t(r=>r.filter(l=>l.id!==s))}const g=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 l=await n.uploadFile({file:s.file,abortSignal:r.signal,onProgress:C=>{a(s.id,{progress:C})}});a(s.id,{status:"success",fileUrl:l.fileUrl,progress:100})}catch(l){r.signal.aborted||a(s.id,{status:"error",error:l instanceof Error?l.message:"Upload failed",progress:0})}finally{S.delete(s.id)}},d=s=>{const r=S.get(s);r&&(r.abort(),S.delete(s)),i(s)},f=u.useMemo(()=>e.filter(s=>s.status==="success"&&s.fileUrl),[e]);function c(){S.forEach(s=>s.abort()),S.clear(),t([])}return u.useEffect(()=>()=>{S.forEach(s=>s.abort()),S.clear()},[]),{allFiles:e,appendFiles:o,handleCancelUpload:d,successFiles:f,emptyTheFiles:c,getFileById:s=>e.find(r=>r.id===s),getUploadProgress:s=>{var r;return((r=e.find(l=>l.id===s))==null?void 0:r.progress)??0},getUploadStatus:s=>{var r;return(r=e.find(l=>l.id===s))==null?void 0:r.status},hasErrors:e.some(s=>s.status==="error"),isUploading:e.some(s=>s.status==="uploading")}}const E=u.createContext(null);function O({children:e}){const t=w(),[n,o]=u.useState(()=>t.inline?!0:t.isOpen??!1);return u.useEffect(()=>{o(a=>t.isOpen??a)},[t.isOpen]),u.useEffect(()=>{const a=t.openAfterNSeconds;if(typeof a!="number"||isNaN(a))return;const i=setTimeout(()=>o(!0),a*1e3);return()=>clearTimeout(i)},[t.openAfterNSeconds]),u.createElement(E.Provider,{value:{isOpen:n,setIsOpen:o}},e)}function q(){const e=u.useContext(E);if(!e)throw new Error("useWidgetTrigger must be used within a WidgetTriggerProvider");return e}function N(){var d,f;const{widgetCtx:e}=p(),{modesComponents:t}=w(),{sessionState:n}=x(),o=e.modes,a=(d=n.session)==null?void 0:d.modeId,i=o.find(c=>c.id===a),g=(f=t==null?void 0:t.find(c=>{var s,r;return[(i==null?void 0:i.id)||"",((s=i==null?void 0:i.name)==null?void 0:s.toLowerCase())||"",((r=i==null?void 0:i.slug)==null?void 0:r.toLowerCase())||""].includes(c.key.toLowerCase())}))==null?void 0:f.component;return{modes:o,modesComponents:t,activeModeId:a,activeMode:i,Component:g}}function B(){const{widgetCtx:e}=p(),{messagesState:{messages:t}}=h(),{csatRequestedMessage:n,isCsatRequested:o,csatSubmittedMessage:a,isCsatSubmitted:i,submittedScore:g,submittedFeedback:d}=u.useMemo(()=>{const f=t.find(s=>s.type==="SYSTEM"&&s.subtype==="csat_requested"),c=t.findLast(s=>s.type==="SYSTEM"&&s.subtype==="csat_submitted");return{csatRequestedMessage:f,isCsatRequested:!!f&&!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:a,isCsatSubmitted:i,submittedScore:g,submittedFeedback:d}}exports.WidgetProvider=U;exports.WidgetTriggerProvider=O;exports.useConfig=w;exports.useContact=W;exports.useCsat=B;exports.useDocumentDir=A;exports.useIsAwaitingBotReply=T;exports.useMessages=h;exports.useModes=N;exports.usePrimitiveState=m;exports.useSessions=x;exports.useUploadFiles=k;exports.useWidget=p;exports.useWidgetRouter=P;exports.useWidgetTrigger=q;
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/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 {\n type ExternalStorage,\n type WidgetConfig,\n WidgetCtx,\n} 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 })\n .then(setWidgetCtx)\n .catch(console.error);\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 { 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","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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"}
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/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 {\n type ExternalStorage,\n type WidgetConfig,\n WidgetCtx,\n} 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 })\n .then(setWidgetCtx)\n .catch(console.error);\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 { useMemo } from 'react';\nimport { 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 isLastMessageAUserMessage =\n messagesState.messages?.at(-1)?.type === 'USER';\n\n const isAwaitingBotReply = (() => {\n if (messagesState.isSendingMessageToAI) return true;\n if (\n (isSessionAssignedToAI || sessionState.isCreatingSession) &&\n (messagesState.isSendingMessage || isLastMessageAUserMessage)\n ) {\n return true;\n }\n return false;\n })();\n\n return { isAwaitingBotReply };\n}\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","isLastMessageAUserMessage","_c","_b","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","modeComponent","useCsat","messages","csatRequestedMessage","isCsatRequested","csatSubmittedMessage","isCsatSubmitted","submittedScore","submittedFeedback","message"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import E, { createContext as v, useRef as y, useState as h, useMemo as S, useEffect as C, useContext as F, useSyncExternalStore as M } from "react";
2
- import { WidgetCtx as W } from "@opencx/widget-core";
3
- import { v4 as T } from "uuid";
4
- const O = "4.0.25";
1
+ import E, { createContext as v, useRef as y, useState as b, useMemo as m, useEffect as C, useContext as F, useSyncExternalStore as k } from "react";
2
+ import { WidgetCtx as T } from "@opencx/widget-core";
3
+ import { v4 as W } from "uuid";
4
+ const O = "4.0.28";
5
5
  class P {
6
6
  constructor(t) {
7
7
  this.components = [];
@@ -33,30 +33,30 @@ function B({
33
33
  children: t,
34
34
  components: n,
35
35
  storage: o,
36
- loadingComponent: i
36
+ loadingComponent: a
37
37
  }) {
38
- const a = y(null), d = y(!1), [l, g] = h(null), c = S(
38
+ const i = y(null), l = y(!1), [u, g] = b(null), c = m(
39
39
  () => new P({
40
40
  components: n
41
41
  }),
42
42
  [n]
43
43
  );
44
44
  return C(() => {
45
- d.current || (d.current = !0, W.initialize({ config: e, storage: o }).then(g).catch(console.error));
46
- }, []), l ? /* @__PURE__ */ E.createElement(
45
+ l.current || (l.current = !0, T.initialize({ config: e, storage: o }).then(g).catch(console.error));
46
+ }, []), u ? /* @__PURE__ */ E.createElement(
47
47
  U.Provider,
48
48
  {
49
49
  value: {
50
- widgetCtx: l,
50
+ widgetCtx: u,
51
51
  config: e,
52
52
  components: n,
53
53
  componentStore: c,
54
54
  version: O,
55
- contentIframeRef: a
55
+ contentIframeRef: i
56
56
  }
57
57
  },
58
58
  t
59
- ) : i || null;
59
+ ) : a || null;
60
60
  }
61
61
  function f() {
62
62
  const e = F(U);
@@ -69,7 +69,7 @@ function x() {
69
69
  return e;
70
70
  }
71
71
  function w(e) {
72
- return M(e.subscribe, e.get, e.get);
72
+ return k(e.subscribe, e.get, e.get);
73
73
  }
74
74
  function D() {
75
75
  const { widgetCtx: e } = f();
@@ -79,7 +79,7 @@ function D() {
79
79
  };
80
80
  }
81
81
  function I() {
82
- const [e, t] = h("ltr");
82
+ const [e, t] = b("ltr");
83
83
  return C(() => {
84
84
  const n = () => {
85
85
  typeof document > "u" || t(
@@ -103,26 +103,26 @@ function R() {
103
103
  const { widgetCtx: e } = f();
104
104
  return { messagesState: w(e.messageCtx.state), sendMessage: e.messageCtx.sendMessage };
105
105
  }
106
- function k() {
107
- const { widgetCtx: e } = f(), { oneOpenSessionAllowed: t } = x(), n = w(e.sessionCtx.sessionState), o = w(e.sessionCtx.sessionsState), { openSessions: i, closedSessions: a } = S(() => ({
108
- openSessions: o.data.filter((l) => l.isOpened === !0),
109
- closedSessions: o.data.filter((l) => l.isOpened === !1)
110
- }), [o.data]), d = S(() => t ? i.length === 0 : !0, [t, i.length]);
106
+ function A() {
107
+ const { widgetCtx: e } = f(), { oneOpenSessionAllowed: t } = x(), n = w(e.sessionCtx.sessionState), o = w(e.sessionCtx.sessionsState), { openSessions: a, closedSessions: i } = m(() => ({
108
+ openSessions: o.data.filter((u) => u.isOpened === !0),
109
+ closedSessions: o.data.filter((u) => u.isOpened === !1)
110
+ }), [o.data]), l = m(() => t ? a.length === 0 : !0, [t, a.length]);
111
111
  return {
112
112
  sessionState: n,
113
113
  sessionsState: o,
114
114
  loadMoreSessions: e.sessionCtx.loadMoreSessions,
115
115
  resolveSession: e.sessionCtx.resolveSession,
116
116
  createStateCheckpoint: e.sessionCtx.createStateCheckpoint,
117
- openSessions: i,
118
- closedSessions: a,
119
- canCreateNewSession: d
117
+ openSessions: a,
118
+ closedSessions: i,
119
+ canCreateNewSession: l
120
120
  };
121
121
  }
122
122
  function z() {
123
- var d;
124
- const { sessionState: e } = k(), { messagesState: t } = R(), 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";
125
- return { isAwaitingBotReply: (n || e.isCreatingSession) && (t.isSendingMessage || i) };
123
+ var i, l, u;
124
+ const { sessionState: e } = A(), { messagesState: t } = R(), n = ((i = e.session) == null ? void 0 : i.assignee.kind) === "ai", o = ((u = (l = t.messages) == null ? void 0 : l.at(-1)) == null ? void 0 : u.type) === "USER";
125
+ return { isAwaitingBotReply: !!(t.isSendingMessageToAI || (n || e.isCreatingSession) && (t.isSendingMessage || o)) };
126
126
  }
127
127
  function Y() {
128
128
  const { widgetCtx: e } = f();
@@ -134,60 +134,60 @@ function Y() {
134
134
  }
135
135
  const p = /* @__PURE__ */ new Map();
136
136
  function _() {
137
- const [e, t] = h([]), {
137
+ const [e, t] = b([]), {
138
138
  widgetCtx: { api: n }
139
139
  } = f();
140
140
  function o(s) {
141
- const r = s.map((u) => ({
142
- file: u,
143
- id: T(),
141
+ const r = s.map((d) => ({
142
+ file: d,
143
+ id: W(),
144
144
  status: "pending",
145
145
  progress: 0
146
146
  }));
147
- t((u) => [...u, ...r]), r.forEach(d);
147
+ t((d) => [...d, ...r]), r.forEach(l);
148
148
  }
149
- function i(s, r) {
149
+ function a(s, r) {
150
150
  t(
151
- (u) => u.map((m) => m.id === s ? { ...m, ...r } : m)
151
+ (d) => d.map((S) => S.id === s ? { ...S, ...r } : S)
152
152
  );
153
153
  }
154
- function a(s) {
155
- t((r) => r.filter((u) => u.id !== s));
154
+ function i(s) {
155
+ t((r) => r.filter((d) => d.id !== s));
156
156
  }
157
- const d = async (s) => {
157
+ const l = async (s) => {
158
158
  const r = new AbortController();
159
159
  p.set(s.id, r);
160
160
  try {
161
161
  t(
162
- (m) => m.map(
163
- (b) => b.id === s.id ? { ...b, status: "uploading", progress: 0 } : b
162
+ (S) => S.map(
163
+ (h) => h.id === s.id ? { ...h, status: "uploading", progress: 0 } : h
164
164
  )
165
165
  );
166
- const u = await n.uploadFile({
166
+ const d = await n.uploadFile({
167
167
  file: s.file,
168
168
  abortSignal: r.signal,
169
- onProgress: (m) => {
170
- i(s.id, { progress: m });
169
+ onProgress: (S) => {
170
+ a(s.id, { progress: S });
171
171
  }
172
172
  });
173
- i(s.id, {
173
+ a(s.id, {
174
174
  status: "success",
175
- fileUrl: u.fileUrl,
175
+ fileUrl: d.fileUrl,
176
176
  progress: 100
177
177
  });
178
- } catch (u) {
179
- r.signal.aborted || i(s.id, {
178
+ } catch (d) {
179
+ r.signal.aborted || a(s.id, {
180
180
  status: "error",
181
- error: u instanceof Error ? u.message : "Upload failed",
181
+ error: d instanceof Error ? d.message : "Upload failed",
182
182
  progress: 0
183
183
  });
184
184
  } finally {
185
185
  p.delete(s.id);
186
186
  }
187
- }, l = (s) => {
187
+ }, u = (s) => {
188
188
  const r = p.get(s);
189
- r && (r.abort(), p.delete(s)), a(s);
190
- }, g = S(() => e.filter((s) => s.status === "success" && s.fileUrl), [e]);
189
+ r && (r.abort(), p.delete(s)), i(s);
190
+ }, g = m(() => e.filter((s) => s.status === "success" && s.fileUrl), [e]);
191
191
  function c() {
192
192
  p.forEach((s) => s.abort()), p.clear(), t([]);
193
193
  }
@@ -196,37 +196,37 @@ function _() {
196
196
  }, []), {
197
197
  allFiles: e,
198
198
  appendFiles: o,
199
- handleCancelUpload: l,
199
+ handleCancelUpload: u,
200
200
  successFiles: g,
201
201
  emptyTheFiles: c,
202
202
  getFileById: (s) => e.find((r) => r.id === s),
203
203
  getUploadProgress: (s) => {
204
204
  var r;
205
- return ((r = e.find((u) => u.id === s)) == null ? void 0 : r.progress) ?? 0;
205
+ return ((r = e.find((d) => d.id === s)) == null ? void 0 : r.progress) ?? 0;
206
206
  },
207
207
  getUploadStatus: (s) => {
208
208
  var r;
209
- return (r = e.find((u) => u.id === s)) == null ? void 0 : r.status;
209
+ return (r = e.find((d) => d.id === s)) == null ? void 0 : r.status;
210
210
  },
211
211
  hasErrors: e.some((s) => s.status === "error"),
212
212
  isUploading: e.some((s) => s.status === "uploading")
213
213
  };
214
214
  }
215
- const A = v(null);
215
+ const M = v(null);
216
216
  function $({ children: e }) {
217
- const t = x(), [n, o] = h(() => t.inline ? !0 : t.isOpen ?? !1);
217
+ const t = x(), [n, o] = b(() => t.inline ? !0 : t.isOpen ?? !1);
218
218
  return C(() => {
219
- o((i) => t.isOpen ?? i);
219
+ o((a) => t.isOpen ?? a);
220
220
  }, [t.isOpen]), C(() => {
221
- const i = t.openAfterNSeconds;
222
- if (typeof i != "number" || isNaN(i))
221
+ const a = t.openAfterNSeconds;
222
+ if (typeof a != "number" || isNaN(a))
223
223
  return;
224
- const a = setTimeout(() => o(!0), i * 1e3);
225
- return () => clearTimeout(a);
226
- }, [t.openAfterNSeconds]), /* @__PURE__ */ E.createElement(A.Provider, { value: { isOpen: n, setIsOpen: o } }, e);
224
+ const i = setTimeout(() => o(!0), a * 1e3);
225
+ return () => clearTimeout(i);
226
+ }, [t.openAfterNSeconds]), /* @__PURE__ */ E.createElement(M.Provider, { value: { isOpen: n, setIsOpen: o } }, e);
227
227
  }
228
228
  function j() {
229
- const e = F(A);
229
+ const e = F(M);
230
230
  if (!e)
231
231
  throw new Error(
232
232
  "useWidgetTrigger must be used within a WidgetTriggerProvider"
@@ -234,23 +234,23 @@ function j() {
234
234
  return e;
235
235
  }
236
236
  function G() {
237
- var l, g;
238
- const { widgetCtx: e } = f(), { 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(
237
+ var u, g;
238
+ const { widgetCtx: e } = f(), { modesComponents: t } = x(), { sessionState: n } = A(), o = e.modes, a = (u = n.session) == null ? void 0 : u.modeId, i = o.find((c) => c.id === a), l = (g = t == null ? void 0 : t.find(
239
239
  (c) => {
240
240
  var s, r;
241
241
  return [
242
- (a == null ? void 0 : a.id) || "",
243
- ((s = a == null ? void 0 : a.name) == null ? void 0 : s.toLowerCase()) || "",
244
- ((r = a == null ? void 0 : a.slug) == null ? void 0 : r.toLowerCase()) || ""
242
+ (i == null ? void 0 : i.id) || "",
243
+ ((s = i == null ? void 0 : i.name) == null ? void 0 : s.toLowerCase()) || "",
244
+ ((r = i == null ? void 0 : i.slug) == null ? void 0 : r.toLowerCase()) || ""
245
245
  ].includes(c.key.toLowerCase());
246
246
  }
247
247
  )) == null ? void 0 : g.component;
248
248
  return {
249
249
  modes: o,
250
250
  modesComponents: t,
251
- activeModeId: i,
252
- activeMode: a,
253
- Component: d
251
+ activeModeId: a,
252
+ activeMode: i,
253
+ Component: l
254
254
  };
255
255
  }
256
256
  function H() {
@@ -259,11 +259,11 @@ function H() {
259
259
  } = R(), {
260
260
  csatRequestedMessage: n,
261
261
  isCsatRequested: o,
262
- csatSubmittedMessage: i,
263
- isCsatSubmitted: a,
264
- submittedScore: d,
265
- submittedFeedback: l
266
- } = S(() => {
262
+ csatSubmittedMessage: a,
263
+ isCsatSubmitted: i,
264
+ submittedScore: l,
265
+ submittedFeedback: u
266
+ } = m(() => {
267
267
  const g = t.find(
268
268
  (s) => s.type === "SYSTEM" && s.subtype === "csat_requested"
269
269
  ), c = t.findLast(
@@ -282,10 +282,10 @@ function H() {
282
282
  submitCsat: e.csatCtx.submitCsat,
283
283
  csatRequestedMessage: n,
284
284
  isCsatRequested: o,
285
- csatSubmittedMessage: i,
286
- isCsatSubmitted: a,
287
- submittedScore: d,
288
- submittedFeedback: l
285
+ csatSubmittedMessage: a,
286
+ isCsatSubmitted: i,
287
+ submittedScore: l,
288
+ submittedFeedback: u
289
289
  };
290
290
  }
291
291
  export {
@@ -299,7 +299,7 @@ export {
299
299
  R as useMessages,
300
300
  G as useModes,
301
301
  w as usePrimitiveState,
302
- k as useSessions,
302
+ A as useSessions,
303
303
  _ as useUploadFiles,
304
304
  f as useWidget,
305
305
  Y as useWidgetRouter,
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/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 {\n type ExternalStorage,\n type WidgetConfig,\n WidgetCtx,\n} 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 })\n .then(setWidgetCtx)\n .catch(console.error);\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 { 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","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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"}
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/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 {\n type ExternalStorage,\n type WidgetConfig,\n WidgetCtx,\n} 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 })\n .then(setWidgetCtx)\n .catch(console.error);\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 { useMemo } from 'react';\nimport { 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 isLastMessageAUserMessage =\n messagesState.messages?.at(-1)?.type === 'USER';\n\n const isAwaitingBotReply = (() => {\n if (messagesState.isSendingMessageToAI) return true;\n if (\n (isSessionAssignedToAI || sessionState.isCreatingSession) &&\n (messagesState.isSendingMessage || isLastMessageAUserMessage)\n ) {\n return true;\n }\n return false;\n })();\n\n return { isAwaitingBotReply };\n}\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","isLastMessageAUserMessage","_c","_b","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","modeComponent","useCsat","messages","csatRequestedMessage","isCsatRequested","csatSubmittedMessage","isCsatSubmitted","submittedScore","submittedFeedback","message"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useIsAwaitingBotReply.d.ts","sourceRoot":"","sources":["../../../src/hooks/useIsAwaitingBotReply.ts"],"names":[],"mappings":"AAGA,wBAAgB,qBAAqB;;EAiBpC"}
1
+ {"version":3,"file":"useIsAwaitingBotReply.d.ts","sourceRoot":"","sources":["../../../src/hooks/useIsAwaitingBotReply.ts"],"names":[],"mappings":"AAIA,wBAAgB,qBAAqB;;EAqBpC"}
@@ -2,6 +2,7 @@ export declare function useMessages(): {
2
2
  messagesState: {
3
3
  messages: import('@opencx/widget-core').WidgetMessageU[];
4
4
  isSendingMessage: boolean;
5
+ isSendingMessageToAI: boolean;
5
6
  lastAIResMightSolveUserIssue: boolean;
6
7
  isInitialFetchLoading: boolean;
7
8
  };
@@ -1 +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"}
1
+ {"version":3,"file":"useMessages.d.ts","sourceRoot":"","sources":["../../../src/hooks/useMessages.ts"],"names":[],"mappings":"AAGA,wBAAgB,WAAW;;;;;;;;;;mBAMmuB,CAAC;kBAAmD,CAAC;sBAAuD,CAAC;;EAD12B"}
@@ -1 +1 @@
1
- {"version":3,"file":"useSessions.d.ts","sourceRoot":"","sources":["../../../src/hooks/useSessions.ts"],"names":[],"mappings":"AAKA,wBAAgB,WAAW;;;;;;;;;;;;;;;;;qBA+BwtC,CAAC;;;;;;;;;;;;;;;;;;;;;;;sBAA4uB,CAAC;;;;sBAAwG,CAAC;mBAA6B,CAAC;iBAA2B,CAAC;;qBAA0C,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAD9qE"}
1
+ {"version":3,"file":"useSessions.d.ts","sourceRoot":"","sources":["../../../src/hooks/useSessions.ts"],"names":[],"mappings":"AAKA,wBAAgB,WAAW;;;;;;;;;;;;;;;;;qBA+ByvC,CAAC;;;;;;;;;;;;;;;;;;;;;;;sBAA4uB,CAAC;;;;sBAAwG,CAAC;mBAA6B,CAAC;iBAA2B,CAAC;;qBAA0C,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAD/sE"}
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.25",
4
+ "version": "4.0.28",
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.25"
23
+ "@opencx/widget-core": "4.0.28"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "@types/react": ">=18 <20",