@opencx/widget 3.0.94 → 3.0.96

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/react.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./useModes-BzcZkifa.cjs"),o=require("react-use/lib/useAsyncFn");function g(s,t,i){const{widgetCtx:{api:u}}=e.useWidget();return o(async r=>u.vote({action:r==="up"?"upvote":"downvote",messagePublicId:s,sessionId:t}).then(i),[u,s,t,i])}exports.WidgetProvider=e.WidgetProvider;exports.WidgetTriggerProvider=e.WidgetTriggerProvider;exports.useConfig=e.useConfig;exports.useContact=e.useContact;exports.useIsAwaitingBotReply=e.useIsAwaitingBotReply;exports.useMessages=e.useMessages;exports.useModes=e.useModes;exports.usePreludeData=e.usePreludeData;exports.usePrimitiveState=e.usePrimitiveState;exports.useSessions=e.useSessions;exports.useUploadFiles=e.useUploadFiles;exports.useWidget=e.useWidget;exports.useWidgetRouter=e.useWidgetRouter;exports.useWidgetTrigger=e.useWidgetTrigger;exports.useVote=g;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./useModes-BJqYvlSG.cjs"),o=require("react-use/lib/useAsyncFn");function g(s,t,i){const{widgetCtx:{api:u}}=e.useWidget();return o(async r=>u.vote({action:r==="up"?"upvote":"downvote",messagePublicId:s,sessionId:t}).then(i),[u,s,t,i])}exports.WidgetProvider=e.WidgetProvider;exports.WidgetTriggerProvider=e.WidgetTriggerProvider;exports.useConfig=e.useConfig;exports.useContact=e.useContact;exports.useIsAwaitingBotReply=e.useIsAwaitingBotReply;exports.useMessages=e.useMessages;exports.useModes=e.useModes;exports.usePreludeData=e.usePreludeData;exports.usePrimitiveState=e.usePrimitiveState;exports.useSessions=e.useSessions;exports.useUploadFiles=e.useUploadFiles;exports.useWidget=e.useWidget;exports.useWidgetRouter=e.useWidgetRouter;exports.useWidgetTrigger=e.useWidgetTrigger;exports.useVote=g;
2
2
  //# sourceMappingURL=react.cjs.map
package/dist/react.js CHANGED
@@ -1,5 +1,5 @@
1
- import { u as o } from "./useModes-B5-vdm1q.js";
2
- import { W as m, k as c, a as f, b as l, c as v, d as W, l as P, e as w, f as x, g as y, i as C, h as b, j as h } from "./useModes-B5-vdm1q.js";
1
+ import { u as o } from "./useModes-Dm1CBDor.js";
2
+ import { W as m, k as c, a as f, b as l, c as v, d as W, l as P, e as w, f as x, g as y, i as C, h as b, j as h } from "./useModes-Dm1CBDor.js";
3
3
  import r from "react-use/lib/useAsyncFn";
4
4
  function n(e, s, t) {
5
5
  const {
@@ -1,2 +1,3 @@
1
1
  import { default as React } from 'react';
2
+ export declare function WidgetContent(): React.JSX.Element;
2
3
  export declare function WidgetPopoverContent(): React.JSX.Element;
@@ -113,7 +113,14 @@ export type HeaderButtonU = (HeaderButtonBase & {
113
113
  functionality: 'close-widget';
114
114
  }) | (HeaderButtonBase & {
115
115
  functionality: 'resolve-session';
116
- onResolved?: 'reset-chat' | 'close-widget' | 'reset-chat-and-close-widget';
116
+ /**
117
+ * The side effect after the session is resolved.
118
+ * @default 'stay-in-chat'
119
+ */
120
+ onResolved?: 'stay-in-chat' | 'reset-chat' | 'close-widget' | 'reset-chat-and-close-widget';
121
+ /**
122
+ * Optional confirmation dialog before the session is resolved.
123
+ */
117
124
  confirmation?: {
118
125
  type: 'modal';
119
126
  title?: string;
@@ -121,6 +128,16 @@ export type HeaderButtonU = (HeaderButtonBase & {
121
128
  confirmButtonText?: string;
122
129
  cancelButtonText?: string;
123
130
  };
131
+ /**
132
+ * The button's behavior before the session is created (before the user sends their first message).
133
+ * @default 'disabled'
134
+ */
135
+ behaviorBeforeSessionCreation?: 'disabled' | 'close-widget';
136
+ /**
137
+ * The button's behavior after the session is resolved and the user is still in the same chat session.
138
+ * @default 'disabled'
139
+ */
140
+ behaviorIfSessionIsResolved?: 'disabled' | 'reset-chat' | 'close-widget' | 'reset-chat-and-close-widget';
124
141
  });
125
142
  export type ModeComponentProps = {
126
143
  react: typeof React;
@@ -354,6 +371,17 @@ export interface WidgetConfig {
354
371
  * @default undefined
355
372
  */
356
373
  sessionCustomData?: Record<string, unknown>;
374
+ /**
375
+ * If this is set to `true`:
376
+ * 1. The widget content will fill it's parent element.
377
+ * 2. The content will always be open.
378
+ * 3. The widget trigger will not be visible.
379
+ *
380
+ * This is useful if you want to embed the widget in a parent element and have it always open.
381
+ *
382
+ * @default false
383
+ */
384
+ inline?: boolean;
357
385
  /**
358
386
  * An apiUrl to override production backend.
359
387
  * This is for us to test the widget locally, you don't need to play with this option 😊.
@@ -1,2 +1,2 @@
1
- "use strict";const U=require("swr"),u=require("react"),F=require("uuid"),y=require("react/jsx-runtime"),P=require("./widget.ctx-B-9oCDpY.cjs"),R="3.0.94";class b{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 W=u.createContext(null);function A({options:e,children:t,components:n,storage:o,loadingComponent:i}){const c=u.useRef(null),d=u.useRef(!1),[l,C]=u.useState(null),p=u.useMemo(()=>new b({components:n}),[n]);return u.useEffect(()=>{d.current||(d.current=!0,P.WidgetCtx.initialize({config:e,storage:o}).then(C))},[]),l?y.jsx(W.Provider,{value:{widgetCtx:l,config:e,components:n,componentStore:p,version:R,contentIframeRef:c},children:t}):i||null}function g(){const e=u.useContext(W);if(!e)throw new Error("useWidget must be used within a WidgetProvider");return e}function x(){const{config:e}=g();return e}function m(e){return u.useSyncExternalStore(e.subscribe,e.get,e.get)}function M(){const{widgetCtx:e}=g();return{contactState:m(e.contactCtx.state),createUnverifiedContact:e.contactCtx.createUnverifiedContact}}function v(){const{widgetCtx:e}=g();return{messagesState:m(e.messageCtx.state),sendMessage:e.messageCtx.sendMessage}}function w(){const{widgetCtx:e}=g(),{oneOpenSessionAllowed:t}=x(),n=m(e.sessionCtx.sessionState),o=m(e.sessionCtx.sessionsState),{openSessions:i,closedSessions:c}=u.useMemo(()=>({openSessions:o.data.filter(l=>l.isOpened===!0),closedSessions:o.data.filter(l=>l.isOpened===!1)}),[o.data]),d=u.useMemo(()=>t?i.length===0:!0,[t,i.length]);return{sessionState:n,sessionsState:o,loadMoreSessions:e.sessionCtx.loadMoreSessions,resolveSession:e.sessionCtx.resolveSession,createStateCheckpoint:e.sessionCtx.createStateCheckpoint,openSessions:i,closedSessions:c,canCreateNewSession:d}}function k(){var d;const{sessionState:e}=w(),{messagesState:t}=v(),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)==="FROM_USER";return{isAwaitingBotReply:(n||e.isCreatingSession)&&(t.isSendingMessage||i)}}function O(){const{widgetCtx:e}=g();return U([e.config.token],e.api.widgetPrelude,{revalidateOnFocus:!1})}function T(){const{widgetCtx:e}=g();return{routerState:m(e.routerCtx.state),toSessionsScreen:e.routerCtx.toSessionsScreen,toChatScreen:e.routerCtx.toChatScreen}}const f=new Map;function N(){const[e,t]=u.useState([]),{widgetCtx:{api:n}}=g();function o(s){const r=s.map(a=>({file:a,id:F.v4(),status:"pending",progress:0}));t(a=>[...a,...r]),r.forEach(d)}function i(s,r){t(a=>a.map(S=>S.id===s?{...S,...r}:S))}function c(s){t(r=>r.filter(a=>a.id!==s))}const d=async s=>{const r=new AbortController;f.set(s.id,r);try{t(S=>S.map(h=>h.id===s.id?{...h,status:"uploading",progress:0}:h));const a=await n.uploadFile({file:s.file,abortSignal:r.signal,onProgress:S=>{i(s.id,{progress:S})}});i(s.id,{status:"success",fileUrl:a.fileUrl,progress:100})}catch(a){r.signal.aborted||i(s.id,{status:"error",error:a instanceof Error?a.message:"Upload failed",progress:0})}finally{f.delete(s.id)}},l=s=>{const r=f.get(s);r&&(r.abort(),f.delete(s)),c(s)},C=u.useMemo(()=>e.filter(s=>s.status==="success"&&s.fileUrl),[e]);function p(){f.forEach(s=>s.abort()),f.clear(),t([])}return u.useEffect(()=>()=>{f.forEach(s=>s.abort()),f.clear()},[]),{allFiles:e,appendFiles:o,handleCancelUpload:l,successFiles:C,emptyTheFiles:p,getFileById:s=>e.find(r=>r.id===s),getUploadProgress:s=>{var r;return((r=e.find(a=>a.id===s))==null?void 0:r.progress)??0},getUploadStatus:s=>{var r;return(r=e.find(a=>a.id===s))==null?void 0:r.status},hasErrors:e.some(s=>s.status==="error"),isUploading:e.some(s=>s.status==="uploading")}}const E=u.createContext(null);function B({children:e}){const t=x(),[n,o]=u.useState(t.isOpen??!1);return u.useEffect(()=>{o(i=>t.isOpen??i)},[t.isOpen]),u.useEffect(()=>{const i=t.openAfterNSeconds;if(typeof i!="number"||isNaN(i))return;const c=setTimeout(()=>o(!0),i*1e3);return()=>clearTimeout(c)},[t.openAfterNSeconds]),y.jsx(E.Provider,{value:{isOpen:n,setIsOpen:o},children:e})}function q(){const e=u.useContext(E);if(!e)throw new Error("useWidgetTrigger must be used within a WidgetTriggerProvider");return e}function I(){var l,C;const{widgetCtx:e}=g(),{modesComponents:t}=x(),{sessionState:n}=w(),o=e.modes,i=(l=n.session)==null?void 0:l.modeId,c=o.find(p=>p.id===i),d=(C=t==null?void 0:t.find(p=>{var s,r;return[(c==null?void 0:c.id)||"",((s=c==null?void 0:c.name)==null?void 0:s.toLowerCase())||"",((r=c==null?void 0:c.slug)==null?void 0:r.toLowerCase())||""].includes(p.key.toLowerCase())}))==null?void 0:C.component;return{modes:o,modesComponents:t,activeModeId:i,activeMode:c,Component:d}}exports.WidgetProvider=A;exports.WidgetTriggerProvider=B;exports.useConfig=x;exports.useContact=M;exports.useIsAwaitingBotReply=k;exports.useMessages=v;exports.useModes=I;exports.usePreludeData=O;exports.usePrimitiveState=m;exports.useSessions=w;exports.useUploadFiles=N;exports.useWidget=g;exports.useWidgetRouter=T;exports.useWidgetTrigger=q;
2
- //# sourceMappingURL=useModes-BzcZkifa.cjs.map
1
+ "use strict";const U=require("swr"),c=require("react"),F=require("uuid"),y=require("react/jsx-runtime"),P=require("./widget.ctx-B-9oCDpY.cjs"),R="3.0.96";class b{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 W=c.createContext(null);function A({options:e,children:t,components:n,storage:o,loadingComponent:i}){const u=c.useRef(null),d=c.useRef(!1),[l,C]=c.useState(null),p=c.useMemo(()=>new b({components:n}),[n]);return c.useEffect(()=>{d.current||(d.current=!0,P.WidgetCtx.initialize({config:e,storage:o}).then(C))},[]),l?y.jsx(W.Provider,{value:{widgetCtx:l,config:e,components:n,componentStore:p,version:R,contentIframeRef:u},children:t}):i||null}function g(){const e=c.useContext(W);if(!e)throw new Error("useWidget must be used within a WidgetProvider");return e}function x(){const{config:e}=g();return e}function m(e){return c.useSyncExternalStore(e.subscribe,e.get,e.get)}function M(){const{widgetCtx:e}=g();return{contactState:m(e.contactCtx.state),createUnverifiedContact:e.contactCtx.createUnverifiedContact}}function v(){const{widgetCtx:e}=g();return{messagesState:m(e.messageCtx.state),sendMessage:e.messageCtx.sendMessage}}function w(){const{widgetCtx:e}=g(),{oneOpenSessionAllowed:t}=x(),n=m(e.sessionCtx.sessionState),o=m(e.sessionCtx.sessionsState),{openSessions:i,closedSessions:u}=c.useMemo(()=>({openSessions:o.data.filter(l=>l.isOpened===!0),closedSessions:o.data.filter(l=>l.isOpened===!1)}),[o.data]),d=c.useMemo(()=>t?i.length===0:!0,[t,i.length]);return{sessionState:n,sessionsState:o,loadMoreSessions:e.sessionCtx.loadMoreSessions,resolveSession:e.sessionCtx.resolveSession,createStateCheckpoint:e.sessionCtx.createStateCheckpoint,openSessions:i,closedSessions:u,canCreateNewSession:d}}function k(){var d;const{sessionState:e}=w(),{messagesState:t}=v(),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)==="FROM_USER";return{isAwaitingBotReply:(n||e.isCreatingSession)&&(t.isSendingMessage||i)}}function O(){const{widgetCtx:e}=g();return U([e.config.token],e.api.widgetPrelude,{revalidateOnFocus:!1})}function T(){const{widgetCtx:e}=g();return{routerState:m(e.routerCtx.state),toSessionsScreen:e.routerCtx.toSessionsScreen,toChatScreen:e.routerCtx.toChatScreen}}const f=new Map;function N(){const[e,t]=c.useState([]),{widgetCtx:{api:n}}=g();function o(s){const r=s.map(a=>({file:a,id:F.v4(),status:"pending",progress:0}));t(a=>[...a,...r]),r.forEach(d)}function i(s,r){t(a=>a.map(S=>S.id===s?{...S,...r}:S))}function u(s){t(r=>r.filter(a=>a.id!==s))}const d=async s=>{const r=new AbortController;f.set(s.id,r);try{t(S=>S.map(h=>h.id===s.id?{...h,status:"uploading",progress:0}:h));const a=await n.uploadFile({file:s.file,abortSignal:r.signal,onProgress:S=>{i(s.id,{progress:S})}});i(s.id,{status:"success",fileUrl:a.fileUrl,progress:100})}catch(a){r.signal.aborted||i(s.id,{status:"error",error:a instanceof Error?a.message:"Upload failed",progress:0})}finally{f.delete(s.id)}},l=s=>{const r=f.get(s);r&&(r.abort(),f.delete(s)),u(s)},C=c.useMemo(()=>e.filter(s=>s.status==="success"&&s.fileUrl),[e]);function p(){f.forEach(s=>s.abort()),f.clear(),t([])}return c.useEffect(()=>()=>{f.forEach(s=>s.abort()),f.clear()},[]),{allFiles:e,appendFiles:o,handleCancelUpload:l,successFiles:C,emptyTheFiles:p,getFileById:s=>e.find(r=>r.id===s),getUploadProgress:s=>{var r;return((r=e.find(a=>a.id===s))==null?void 0:r.progress)??0},getUploadStatus:s=>{var r;return(r=e.find(a=>a.id===s))==null?void 0:r.status},hasErrors:e.some(s=>s.status==="error"),isUploading:e.some(s=>s.status==="uploading")}}const E=c.createContext(null);function B({children:e}){const t=x(),[n,o]=c.useState(()=>t.inline?!0:t.isOpen??!1);return c.useEffect(()=>{o(i=>t.isOpen??i)},[t.isOpen]),c.useEffect(()=>{const i=t.openAfterNSeconds;if(typeof i!="number"||isNaN(i))return;const u=setTimeout(()=>o(!0),i*1e3);return()=>clearTimeout(u)},[t.openAfterNSeconds]),y.jsx(E.Provider,{value:{isOpen:n,setIsOpen:o},children:e})}function q(){const e=c.useContext(E);if(!e)throw new Error("useWidgetTrigger must be used within a WidgetTriggerProvider");return e}function I(){var l,C;const{widgetCtx:e}=g(),{modesComponents:t}=x(),{sessionState:n}=w(),o=e.modes,i=(l=n.session)==null?void 0:l.modeId,u=o.find(p=>p.id===i),d=(C=t==null?void 0:t.find(p=>{var s,r;return[(u==null?void 0:u.id)||"",((s=u==null?void 0:u.name)==null?void 0:s.toLowerCase())||"",((r=u==null?void 0:u.slug)==null?void 0:r.toLowerCase())||""].includes(p.key.toLowerCase())}))==null?void 0:C.component;return{modes:o,modesComponents:t,activeModeId:i,activeMode:u,Component:d}}exports.WidgetProvider=A;exports.WidgetTriggerProvider=B;exports.useConfig=x;exports.useContact=M;exports.useIsAwaitingBotReply=k;exports.useMessages=v;exports.useModes=I;exports.usePreludeData=O;exports.usePrimitiveState=m;exports.useSessions=w;exports.useUploadFiles=N;exports.useWidget=g;exports.useWidgetRouter=T;exports.useWidgetTrigger=q;
2
+ //# sourceMappingURL=useModes-BJqYvlSG.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"useModes-BzcZkifa.cjs","sources":["../src/headless/react/ComponentRegistry.ts","../src/headless/react/WidgetProvider.tsx","../src/headless/react/hooks/useConfig.ts","../src/headless/react/hooks/usePrimitiveState.ts","../src/headless/react/hooks/useContact.ts","../src/headless/react/hooks/useMessages.ts","../src/headless/react/hooks/useSessions.ts","../src/headless/react/hooks/useIsAwaitingBotReply.ts","../src/headless/react/hooks/usePreludeData.ts","../src/headless/react/hooks/useWidgetRouter.ts","../src/headless/react/hooks/useUploadFiles.ts","../src/headless/react/hooks/useWidgetTrigger.tsx","../src/headless/react/hooks/useModes.ts"],"sourcesContent":["import type { WidgetComponentKey } from '../core';\nimport type { WidgetComponentType } from './types/components';\n\nexport class ComponentRegistry {\n components: WidgetComponentType[] = [];\n\n constructor(opts: { components?: WidgetComponentType[] }) {\n const { components } = opts;\n\n if (components) {\n components.forEach((c) => this.register(c));\n }\n\n if (this.components.length === 0) {\n throw new Error('No components registered');\n }\n if (!this.get('fallback')) {\n throw new Error('No fallback component registered');\n }\n }\n\n // TODO test that this registers or replaces the component\n register(component: WidgetComponentType) {\n // Replace the key if it already exists\n const index = this.components.findIndex((c) => c.key === component.key);\n if (index !== -1) {\n this.components[index] = component;\n } else {\n this.components.push(component);\n }\n return this;\n }\n\n private get(key: WidgetComponentKey) {\n const c = this.components.find(\n (c) => c.key.toUpperCase() === key.toUpperCase(),\n );\n if (c) return c;\n return null;\n }\n\n public getComponent(key: string) {\n return this.get(key)?.component;\n }\n}\n","import React, {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { version } from '../../../package.json';\nimport { type ExternalStorage, type WidgetConfig, WidgetCtx } from '../core';\nimport { ComponentRegistry } from './ComponentRegistry';\nimport type { WidgetComponentType } from './types/components';\n\ninterface WidgetProviderValue {\n widgetCtx: WidgetCtx;\n config: WidgetConfig;\n components?: WidgetComponentType[];\n componentStore: ComponentRegistry;\n version: string;\n contentIframeRef?: React.MutableRefObject<HTMLIFrameElement | null>;\n}\n\nconst context = createContext<WidgetProviderValue | null>(null);\n\nexport function WidgetProvider({\n options: config,\n children,\n components,\n storage,\n loadingComponent,\n}: {\n options: WidgetConfig;\n children: React.ReactNode;\n components?: WidgetComponentType[];\n storage?: ExternalStorage;\n /**\n * Custom loading component while the widget is initializing\n * Not to be confused with the `loading` custom component which renders when the bot's reply is pending\n */\n loadingComponent?: React.ReactNode;\n}) {\n const contentIframeRef = useRef<HTMLIFrameElement | null>(null);\n\n const didInitialize = useRef(false);\n const [widgetCtx, setWidgetCtx] = useState<WidgetCtx | null>(null);\n\n const componentStore = useMemo(\n () =>\n new ComponentRegistry({\n components: components,\n }),\n [components],\n );\n\n useEffect(() => {\n if (didInitialize.current) return;\n didInitialize.current = true;\n\n WidgetCtx.initialize({ config, storage }).then(setWidgetCtx);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n if (!widgetCtx) {\n return loadingComponent || null;\n }\n\n return (\n <context.Provider\n value={{\n widgetCtx,\n config,\n components,\n componentStore,\n version,\n contentIframeRef,\n }}\n >\n {children}\n </context.Provider>\n );\n}\n\nexport function useWidget() {\n const ctx = useContext(context);\n if (!ctx) {\n throw new Error('useWidget must be used within a WidgetProvider');\n }\n return ctx;\n}\n","import { useWidget } from '../WidgetProvider';\n\nexport function useConfig() {\n const { config } = useWidget();\n\n return config;\n}\n","import { useSyncExternalStore } from 'react';\nimport type { PrimitiveState } from '../../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 { usePrimitiveState } from './usePrimitiveState';\nimport { useWidget } from '../WidgetProvider';\n\nexport function useMessages() {\n const { widgetCtx } = useWidget();\n const messagesState = usePrimitiveState(widgetCtx.messageCtx.state);\n\n return { messagesState, sendMessage: widgetCtx.messageCtx.sendMessage };\n}\n","import { useMemo } from 'react';\nimport { useWidget } from '../WidgetProvider';\nimport { usePrimitiveState } from './usePrimitiveState';\nimport { useConfig } from './useConfig';\n\nexport function useSessions() {\n const { widgetCtx } = useWidget();\n const { oneOpenSessionAllowed } = useConfig();\n const sessionState = usePrimitiveState(widgetCtx.sessionCtx.sessionState);\n const sessionsState = usePrimitiveState(widgetCtx.sessionCtx.sessionsState);\n\n const { openSessions, closedSessions } = useMemo(() => {\n return {\n openSessions: sessionsState.data.filter((s) => s.isOpened === true),\n closedSessions: sessionsState.data.filter((s) => s.isOpened === false),\n };\n }, [sessionsState.data]);\n\n const canCreateNewSession = useMemo(() => {\n if (oneOpenSessionAllowed) {\n return openSessions.length === 0;\n }\n return true;\n }, [oneOpenSessionAllowed, openSessions.length]);\n\n return {\n sessionState,\n sessionsState,\n loadMoreSessions: widgetCtx.sessionCtx.loadMoreSessions,\n resolveSession: widgetCtx.sessionCtx.resolveSession,\n createStateCheckpoint: widgetCtx.sessionCtx.createStateCheckpoint,\n openSessions,\n closedSessions,\n canCreateNewSession,\n };\n}\n","import { useMessages } from './useMessages';\nimport { useSessions } from './useSessions';\n\nexport function useIsAwaitingBotReply() {\n const { sessionState } = useSessions();\n const { messagesState } = useMessages();\n\n const isSessionAssignedToAI = sessionState.session?.assignee.kind === 'ai';\n // This check is useful in cases where the user might navigate in and out of a chat, and `isSendingMessage` is reset back to its default value\n const lastMessage =\n messagesState.messages.length > 0\n ? messagesState.messages[messagesState.messages.length - 1]\n : null;\n const isLastMessageAUserMessage = lastMessage?.type === 'FROM_USER';\n\n const isAwaitingBotReply =\n (isSessionAssignedToAI || sessionState.isCreatingSession) &&\n (messagesState.isSendingMessage || isLastMessageAUserMessage);\n\n return { isAwaitingBotReply };\n}\n","import useSWR from 'swr';\nimport { useWidget } from '../WidgetProvider';\n\nfunction usePreludeData() {\n const { widgetCtx } = useWidget();\n\n // TODO remove swr dependency\n return useSWR([widgetCtx.config.token], widgetCtx.api.widgetPrelude, {\n revalidateOnFocus: false,\n });\n}\n\nexport { usePreludeData };\n","import { useWidget } from '../WidgetProvider';\nimport { usePrimitiveState } from './usePrimitiveState';\n\nexport function useWidgetRouter() {\n const { widgetCtx } = useWidget();\n\n const routerState = usePrimitiveState(widgetCtx.routerCtx.state);\n\n return {\n routerState,\n toSessionsScreen: widgetCtx.routerCtx.toSessionsScreen,\n toChatScreen: widgetCtx.routerCtx.toChatScreen,\n };\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport { useWidget } from '../WidgetProvider';\nimport { v4 } from 'uuid';\n\nconst uploadAbortControllers: Map<string, AbortController> = new Map();\n\ninterface FileWithProgress {\n status: 'pending' | 'uploading' | 'success' | 'error';\n id: string;\n file: File;\n fileUrl?: string;\n progress: number;\n error?: string;\n}\n\nfunction useUploadFiles() {\n const [files, setFiles] = useState<FileWithProgress[]>([]);\n const {\n widgetCtx: { api },\n } = useWidget();\n function appendFiles(files: File[]) {\n const newFiles = files.map((file) => ({\n file,\n id: v4(),\n status: 'pending' as const,\n progress: 0,\n }));\n\n setFiles((prev) => [...prev, ...newFiles]);\n newFiles.forEach(uploadFile);\n }\n\n function updateFileById(id: string, update: Partial<FileWithProgress>) {\n setFiles((prev) =>\n prev.map((f) => (f.id === id ? { ...f, ...update } : f)),\n );\n }\n\n function removeFileById(id: string) {\n setFiles((prev) => prev.filter((f) => f.id !== id));\n }\n\n const uploadFile = async (fileItem: FileWithProgress) => {\n const controller = new AbortController();\n uploadAbortControllers.set(fileItem.id, controller);\n\n try {\n setFiles((prev) =>\n prev.map((f) =>\n f.id === fileItem.id ? { ...f, status: 'uploading', progress: 0 } : f,\n ),\n );\n\n const response = await api.uploadFile({\n file: fileItem.file,\n abortSignal: controller.signal,\n onProgress: (percentage) => {\n updateFileById(fileItem.id, { progress: percentage });\n },\n });\n\n updateFileById(fileItem.id, {\n status: 'success',\n fileUrl: response.fileUrl,\n progress: 100,\n });\n } catch (error) {\n if (!controller.signal.aborted) {\n updateFileById(fileItem.id, {\n status: 'error',\n error: error instanceof Error ? error.message : 'Upload failed',\n progress: 0,\n });\n }\n } finally {\n uploadAbortControllers.delete(fileItem.id);\n }\n };\n\n const handleCancelUpload = (fileId: string) => {\n const controller = uploadAbortControllers.get(fileId);\n if (controller) {\n controller.abort();\n uploadAbortControllers.delete(fileId);\n }\n removeFileById(fileId);\n };\n\n const successFiles = useMemo(() => {\n return files.filter((f) => f.status === 'success' && f.fileUrl);\n }, [files]);\n\n function emptyTheFiles() {\n uploadAbortControllers.forEach((controller) => controller.abort());\n uploadAbortControllers.clear();\n setFiles([]);\n }\n\n useEffect(() => {\n return () => {\n uploadAbortControllers.forEach((controller) => controller.abort());\n uploadAbortControllers.clear();\n };\n }, []);\n\n return {\n allFiles: files,\n appendFiles,\n handleCancelUpload,\n successFiles,\n emptyTheFiles,\n getFileById: (id: string) => files.find((f) => f.id === id),\n getUploadProgress: (id: string) =>\n files.find((f) => f.id === id)?.progress ?? 0,\n getUploadStatus: (id: string) => files.find((f) => f.id === id)?.status,\n hasErrors: files.some((f) => f.status === 'error'),\n isUploading: files.some((f) => f.status === 'uploading'),\n };\n}\n\nexport { useUploadFiles, type FileWithProgress };\n","import React, {\n createContext,\n useContext,\n useEffect,\n useState,\n type Dispatch,\n type ReactNode,\n type SetStateAction,\n} from 'react';\nimport { useConfig } from './useConfig';\n\ntype WidgetTriggerCtx = {\n isOpen: boolean;\n setIsOpen: Dispatch<SetStateAction<boolean>>;\n};\n\nconst context = createContext<WidgetTriggerCtx | null>(null);\n\nexport function WidgetTriggerProvider({ children }: { children: ReactNode }) {\n const config = useConfig();\n const [isOpen, setIsOpen] = useState(config.isOpen ?? false);\n\n useEffect(() => {\n setIsOpen((prev) => config.isOpen ?? prev);\n }, [config.isOpen]);\n\n useEffect(() => {\n const openAfterNSeconds = config.openAfterNSeconds;\n if (typeof openAfterNSeconds !== 'number' || isNaN(openAfterNSeconds))\n return;\n\n const timeout = setTimeout(() => setIsOpen(true), openAfterNSeconds * 1000);\n\n return () => clearTimeout(timeout);\n }, [config.openAfterNSeconds]);\n\n return (\n <context.Provider value={{ isOpen, setIsOpen }}>\n {children}\n </context.Provider>\n );\n}\n\nexport function useWidgetTrigger() {\n const ctx = useContext(context);\n if (!ctx) {\n throw new Error(\n 'useWidgetTrigger must be used within a WidgetTriggerProvider',\n );\n }\n return ctx;\n}\n","import { useWidget } from '../WidgetProvider';\nimport { useConfig } from './useConfig';\nimport { useSessions } from './useSessions';\n\nexport function useModes() {\n const { widgetCtx } = useWidget();\n const { modesComponents } = useConfig();\n const { sessionState } = useSessions();\n\n const modes = widgetCtx.modes;\n const activeModeId = sessionState.session?.modeId;\n const activeMode = modes.find((mode) => mode.id === activeModeId);\n\n const Component = modesComponents?.find((modeComponent) =>\n [\n activeMode?.id || '',\n activeMode?.name?.toLowerCase() || '',\n activeMode?.slug?.toLowerCase() || '',\n ].includes(modeComponent.key.toLowerCase()),\n )?.component;\n\n return {\n modes,\n modesComponents,\n activeModeId,\n activeMode,\n Component,\n };\n}\n"],"names":["ComponentRegistry","opts","components","c","component","index","key","_a","context","createContext","WidgetProvider","config","children","storage","loadingComponent","contentIframeRef","useRef","didInitialize","widgetCtx","setWidgetCtx","useState","componentStore","useMemo","useEffect","WidgetCtx","jsx","version","useWidget","ctx","useContext","useConfig","usePrimitiveState","p","useSyncExternalStore","useContact","useMessages","useSessions","oneOpenSessionAllowed","sessionState","sessionsState","openSessions","closedSessions","s","canCreateNewSession","useIsAwaitingBotReply","messagesState","isSessionAssignedToAI","lastMessage","isLastMessageAUserMessage","usePreludeData","useSWR","useWidgetRouter","uploadAbortControllers","useUploadFiles","files","setFiles","api","appendFiles","newFiles","file","v4","prev","uploadFile","updateFileById","id","update","f","removeFileById","fileItem","controller","response","percentage","error","handleCancelUpload","fileId","successFiles","emptyTheFiles","WidgetTriggerProvider","isOpen","setIsOpen","openAfterNSeconds","timeout","useWidgetTrigger","useModes","modesComponents","modes","activeModeId","activeMode","mode","Component","_b","modeComponent"],"mappings":"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"}
1
+ {"version":3,"file":"useModes-BJqYvlSG.cjs","sources":["../src/headless/react/ComponentRegistry.ts","../src/headless/react/WidgetProvider.tsx","../src/headless/react/hooks/useConfig.ts","../src/headless/react/hooks/usePrimitiveState.ts","../src/headless/react/hooks/useContact.ts","../src/headless/react/hooks/useMessages.ts","../src/headless/react/hooks/useSessions.ts","../src/headless/react/hooks/useIsAwaitingBotReply.ts","../src/headless/react/hooks/usePreludeData.ts","../src/headless/react/hooks/useWidgetRouter.ts","../src/headless/react/hooks/useUploadFiles.ts","../src/headless/react/hooks/useWidgetTrigger.tsx","../src/headless/react/hooks/useModes.ts"],"sourcesContent":["import type { WidgetComponentKey } from '../core';\nimport type { WidgetComponentType } from './types/components';\n\nexport class ComponentRegistry {\n components: WidgetComponentType[] = [];\n\n constructor(opts: { components?: WidgetComponentType[] }) {\n const { components } = opts;\n\n if (components) {\n components.forEach((c) => this.register(c));\n }\n\n if (this.components.length === 0) {\n throw new Error('No components registered');\n }\n if (!this.get('fallback')) {\n throw new Error('No fallback component registered');\n }\n }\n\n // TODO test that this registers or replaces the component\n register(component: WidgetComponentType) {\n // Replace the key if it already exists\n const index = this.components.findIndex((c) => c.key === component.key);\n if (index !== -1) {\n this.components[index] = component;\n } else {\n this.components.push(component);\n }\n return this;\n }\n\n private get(key: WidgetComponentKey) {\n const c = this.components.find(\n (c) => c.key.toUpperCase() === key.toUpperCase(),\n );\n if (c) return c;\n return null;\n }\n\n public getComponent(key: string) {\n return this.get(key)?.component;\n }\n}\n","import React, {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { version } from '../../../package.json';\nimport { type ExternalStorage, type WidgetConfig, WidgetCtx } from '../core';\nimport { ComponentRegistry } from './ComponentRegistry';\nimport type { WidgetComponentType } from './types/components';\n\ninterface WidgetProviderValue {\n widgetCtx: WidgetCtx;\n config: WidgetConfig;\n components?: WidgetComponentType[];\n componentStore: ComponentRegistry;\n version: string;\n contentIframeRef?: React.MutableRefObject<HTMLIFrameElement | null>;\n}\n\nconst context = createContext<WidgetProviderValue | null>(null);\n\nexport function WidgetProvider({\n options: config,\n children,\n components,\n storage,\n loadingComponent,\n}: {\n options: WidgetConfig;\n children: React.ReactNode;\n components?: WidgetComponentType[];\n storage?: ExternalStorage;\n /**\n * Custom loading component while the widget is initializing\n * Not to be confused with the `loading` custom component which renders when the bot's reply is pending\n */\n loadingComponent?: React.ReactNode;\n}) {\n const contentIframeRef = useRef<HTMLIFrameElement | null>(null);\n\n const didInitialize = useRef(false);\n const [widgetCtx, setWidgetCtx] = useState<WidgetCtx | null>(null);\n\n const componentStore = useMemo(\n () =>\n new ComponentRegistry({\n components: components,\n }),\n [components],\n );\n\n useEffect(() => {\n if (didInitialize.current) return;\n didInitialize.current = true;\n\n WidgetCtx.initialize({ config, storage }).then(setWidgetCtx);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n if (!widgetCtx) {\n return loadingComponent || null;\n }\n\n return (\n <context.Provider\n value={{\n widgetCtx,\n config,\n components,\n componentStore,\n version,\n contentIframeRef,\n }}\n >\n {children}\n </context.Provider>\n );\n}\n\nexport function useWidget() {\n const ctx = useContext(context);\n if (!ctx) {\n throw new Error('useWidget must be used within a WidgetProvider');\n }\n return ctx;\n}\n","import { useWidget } from '../WidgetProvider';\n\nexport function useConfig() {\n const { config } = useWidget();\n\n return config;\n}\n","import { useSyncExternalStore } from 'react';\nimport type { PrimitiveState } from '../../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 { usePrimitiveState } from './usePrimitiveState';\nimport { useWidget } from '../WidgetProvider';\n\nexport function useMessages() {\n const { widgetCtx } = useWidget();\n const messagesState = usePrimitiveState(widgetCtx.messageCtx.state);\n\n return { messagesState, sendMessage: widgetCtx.messageCtx.sendMessage };\n}\n","import { useMemo } from 'react';\nimport { useWidget } from '../WidgetProvider';\nimport { usePrimitiveState } from './usePrimitiveState';\nimport { useConfig } from './useConfig';\n\nexport function useSessions() {\n const { widgetCtx } = useWidget();\n const { oneOpenSessionAllowed } = useConfig();\n const sessionState = usePrimitiveState(widgetCtx.sessionCtx.sessionState);\n const sessionsState = usePrimitiveState(widgetCtx.sessionCtx.sessionsState);\n\n const { openSessions, closedSessions } = useMemo(() => {\n return {\n openSessions: sessionsState.data.filter((s) => s.isOpened === true),\n closedSessions: sessionsState.data.filter((s) => s.isOpened === false),\n };\n }, [sessionsState.data]);\n\n const canCreateNewSession = useMemo(() => {\n if (oneOpenSessionAllowed) {\n return openSessions.length === 0;\n }\n return true;\n }, [oneOpenSessionAllowed, openSessions.length]);\n\n return {\n sessionState,\n sessionsState,\n loadMoreSessions: widgetCtx.sessionCtx.loadMoreSessions,\n resolveSession: widgetCtx.sessionCtx.resolveSession,\n createStateCheckpoint: widgetCtx.sessionCtx.createStateCheckpoint,\n openSessions,\n closedSessions,\n canCreateNewSession,\n };\n}\n","import { useMessages } from './useMessages';\nimport { useSessions } from './useSessions';\n\nexport function useIsAwaitingBotReply() {\n const { sessionState } = useSessions();\n const { messagesState } = useMessages();\n\n const isSessionAssignedToAI = sessionState.session?.assignee.kind === 'ai';\n // This check is useful in cases where the user might navigate in and out of a chat, and `isSendingMessage` is reset back to its default value\n const lastMessage =\n messagesState.messages.length > 0\n ? messagesState.messages[messagesState.messages.length - 1]\n : null;\n const isLastMessageAUserMessage = lastMessage?.type === 'FROM_USER';\n\n const isAwaitingBotReply =\n (isSessionAssignedToAI || sessionState.isCreatingSession) &&\n (messagesState.isSendingMessage || isLastMessageAUserMessage);\n\n return { isAwaitingBotReply };\n}\n","import useSWR from 'swr';\nimport { useWidget } from '../WidgetProvider';\n\nfunction usePreludeData() {\n const { widgetCtx } = useWidget();\n\n // TODO remove swr dependency\n return useSWR([widgetCtx.config.token], widgetCtx.api.widgetPrelude, {\n revalidateOnFocus: false,\n });\n}\n\nexport { usePreludeData };\n","import { useWidget } from '../WidgetProvider';\nimport { usePrimitiveState } from './usePrimitiveState';\n\nexport function useWidgetRouter() {\n const { widgetCtx } = useWidget();\n\n const routerState = usePrimitiveState(widgetCtx.routerCtx.state);\n\n return {\n routerState,\n toSessionsScreen: widgetCtx.routerCtx.toSessionsScreen,\n toChatScreen: widgetCtx.routerCtx.toChatScreen,\n };\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport { useWidget } from '../WidgetProvider';\nimport { v4 } from 'uuid';\n\nconst uploadAbortControllers: Map<string, AbortController> = new Map();\n\ninterface FileWithProgress {\n status: 'pending' | 'uploading' | 'success' | 'error';\n id: string;\n file: File;\n fileUrl?: string;\n progress: number;\n error?: string;\n}\n\nfunction useUploadFiles() {\n const [files, setFiles] = useState<FileWithProgress[]>([]);\n const {\n widgetCtx: { api },\n } = useWidget();\n function appendFiles(files: File[]) {\n const newFiles = files.map((file) => ({\n file,\n id: v4(),\n status: 'pending' as const,\n progress: 0,\n }));\n\n setFiles((prev) => [...prev, ...newFiles]);\n newFiles.forEach(uploadFile);\n }\n\n function updateFileById(id: string, update: Partial<FileWithProgress>) {\n setFiles((prev) =>\n prev.map((f) => (f.id === id ? { ...f, ...update } : f)),\n );\n }\n\n function removeFileById(id: string) {\n setFiles((prev) => prev.filter((f) => f.id !== id));\n }\n\n const uploadFile = async (fileItem: FileWithProgress) => {\n const controller = new AbortController();\n uploadAbortControllers.set(fileItem.id, controller);\n\n try {\n setFiles((prev) =>\n prev.map((f) =>\n f.id === fileItem.id ? { ...f, status: 'uploading', progress: 0 } : f,\n ),\n );\n\n const response = await api.uploadFile({\n file: fileItem.file,\n abortSignal: controller.signal,\n onProgress: (percentage) => {\n updateFileById(fileItem.id, { progress: percentage });\n },\n });\n\n updateFileById(fileItem.id, {\n status: 'success',\n fileUrl: response.fileUrl,\n progress: 100,\n });\n } catch (error) {\n if (!controller.signal.aborted) {\n updateFileById(fileItem.id, {\n status: 'error',\n error: error instanceof Error ? error.message : 'Upload failed',\n progress: 0,\n });\n }\n } finally {\n uploadAbortControllers.delete(fileItem.id);\n }\n };\n\n const handleCancelUpload = (fileId: string) => {\n const controller = uploadAbortControllers.get(fileId);\n if (controller) {\n controller.abort();\n uploadAbortControllers.delete(fileId);\n }\n removeFileById(fileId);\n };\n\n const successFiles = useMemo(() => {\n return files.filter((f) => f.status === 'success' && f.fileUrl);\n }, [files]);\n\n function emptyTheFiles() {\n uploadAbortControllers.forEach((controller) => controller.abort());\n uploadAbortControllers.clear();\n setFiles([]);\n }\n\n useEffect(() => {\n return () => {\n uploadAbortControllers.forEach((controller) => controller.abort());\n uploadAbortControllers.clear();\n };\n }, []);\n\n return {\n allFiles: files,\n appendFiles,\n handleCancelUpload,\n successFiles,\n emptyTheFiles,\n getFileById: (id: string) => files.find((f) => f.id === id),\n getUploadProgress: (id: string) =>\n files.find((f) => f.id === id)?.progress ?? 0,\n getUploadStatus: (id: string) => files.find((f) => f.id === id)?.status,\n hasErrors: files.some((f) => f.status === 'error'),\n isUploading: files.some((f) => f.status === 'uploading'),\n };\n}\n\nexport { useUploadFiles, type FileWithProgress };\n","import React, {\n createContext,\n useContext,\n useEffect,\n useState,\n type Dispatch,\n type ReactNode,\n type SetStateAction,\n} from 'react';\nimport { useConfig } from './useConfig';\n\ntype WidgetTriggerCtx = {\n isOpen: boolean;\n setIsOpen: Dispatch<SetStateAction<boolean>>;\n};\n\nconst context = createContext<WidgetTriggerCtx | null>(null);\n\nexport function WidgetTriggerProvider({ children }: { children: ReactNode }) {\n const config = useConfig();\n const [isOpen, setIsOpen] = useState(() => {\n if (config.inline) return true;\n return config.isOpen ?? false;\n });\n\n useEffect(() => {\n setIsOpen((prev) => config.isOpen ?? prev);\n }, [config.isOpen]);\n\n useEffect(() => {\n const openAfterNSeconds = config.openAfterNSeconds;\n if (typeof openAfterNSeconds !== 'number' || isNaN(openAfterNSeconds))\n return;\n\n const timeout = setTimeout(() => setIsOpen(true), openAfterNSeconds * 1000);\n\n return () => clearTimeout(timeout);\n }, [config.openAfterNSeconds]);\n\n return (\n <context.Provider value={{ isOpen, setIsOpen }}>\n {children}\n </context.Provider>\n );\n}\n\nexport function useWidgetTrigger() {\n const ctx = useContext(context);\n if (!ctx) {\n throw new Error(\n 'useWidgetTrigger must be used within a WidgetTriggerProvider',\n );\n }\n return ctx;\n}\n","import { useWidget } from '../WidgetProvider';\nimport { useConfig } from './useConfig';\nimport { useSessions } from './useSessions';\n\nexport function useModes() {\n const { widgetCtx } = useWidget();\n const { modesComponents } = useConfig();\n const { sessionState } = useSessions();\n\n const modes = widgetCtx.modes;\n const activeModeId = sessionState.session?.modeId;\n const activeMode = modes.find((mode) => mode.id === activeModeId);\n\n const Component = modesComponents?.find((modeComponent) =>\n [\n activeMode?.id || '',\n activeMode?.name?.toLowerCase() || '',\n activeMode?.slug?.toLowerCase() || '',\n ].includes(modeComponent.key.toLowerCase()),\n )?.component;\n\n return {\n modes,\n modesComponents,\n activeModeId,\n activeMode,\n Component,\n };\n}\n"],"names":["ComponentRegistry","opts","components","c","component","index","key","_a","context","createContext","WidgetProvider","config","children","storage","loadingComponent","contentIframeRef","useRef","didInitialize","widgetCtx","setWidgetCtx","useState","componentStore","useMemo","useEffect","WidgetCtx","jsx","version","useWidget","ctx","useContext","useConfig","usePrimitiveState","p","useSyncExternalStore","useContact","useMessages","useSessions","oneOpenSessionAllowed","sessionState","sessionsState","openSessions","closedSessions","s","canCreateNewSession","useIsAwaitingBotReply","messagesState","isSessionAssignedToAI","lastMessage","isLastMessageAUserMessage","usePreludeData","useSWR","useWidgetRouter","uploadAbortControllers","useUploadFiles","files","setFiles","api","appendFiles","newFiles","file","v4","prev","uploadFile","updateFileById","id","update","f","removeFileById","fileItem","controller","response","percentage","error","handleCancelUpload","fileId","successFiles","emptyTheFiles","WidgetTriggerProvider","isOpen","setIsOpen","openAfterNSeconds","timeout","useWidgetTrigger","useModes","modesComponents","modes","activeModeId","activeMode","mode","Component","_b","modeComponent"],"mappings":"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"}
@@ -3,7 +3,7 @@ import { createContext as U, useRef as b, useState as w, useMemo as m, useEffect
3
3
  import { v4 as O } from "uuid";
4
4
  import { jsx as W } from "react/jsx-runtime";
5
5
  import { W as R } from "./widget.ctx-CfUvw50X.js";
6
- const N = "3.0.94";
6
+ const N = "3.0.96";
7
7
  class T {
8
8
  constructor(t) {
9
9
  this.components = [];
@@ -37,7 +37,7 @@ function D({
37
37
  storage: o,
38
38
  loadingComponent: i
39
39
  }) {
40
- const a = b(null), u = b(!1), [d, S] = w(null), p = m(
40
+ const a = b(null), u = b(!1), [d, S] = w(null), f = m(
41
41
  () => new T({
42
42
  components: n
43
43
  }),
@@ -52,7 +52,7 @@ function D({
52
52
  widgetCtx: d,
53
53
  config: e,
54
54
  components: n,
55
- componentStore: p,
55
+ componentStore: f,
56
56
  version: N,
57
57
  contentIframeRef: a
58
58
  },
@@ -135,7 +135,7 @@ function H() {
135
135
  }
136
136
  function i(s, r) {
137
137
  t(
138
- (c) => c.map((f) => f.id === s ? { ...f, ...r } : f)
138
+ (c) => c.map((p) => p.id === s ? { ...p, ...r } : p)
139
139
  );
140
140
  }
141
141
  function a(s) {
@@ -146,15 +146,15 @@ function H() {
146
146
  l.set(s.id, r);
147
147
  try {
148
148
  t(
149
- (f) => f.map(
149
+ (p) => p.map(
150
150
  (x) => x.id === s.id ? { ...x, status: "uploading", progress: 0 } : x
151
151
  )
152
152
  );
153
153
  const c = await n.uploadFile({
154
154
  file: s.file,
155
155
  abortSignal: r.signal,
156
- onProgress: (f) => {
157
- i(s.id, { progress: f });
156
+ onProgress: (p) => {
157
+ i(s.id, { progress: p });
158
158
  }
159
159
  });
160
160
  i(s.id, {
@@ -175,7 +175,7 @@ function H() {
175
175
  const r = l.get(s);
176
176
  r && (r.abort(), l.delete(s)), a(s);
177
177
  }, S = m(() => e.filter((s) => s.status === "success" && s.fileUrl), [e]);
178
- function p() {
178
+ function f() {
179
179
  l.forEach((s) => s.abort()), l.clear(), t([]);
180
180
  }
181
181
  return h(() => () => {
@@ -185,7 +185,7 @@ function H() {
185
185
  appendFiles: o,
186
186
  handleCancelUpload: d,
187
187
  successFiles: S,
188
- emptyTheFiles: p,
188
+ emptyTheFiles: f,
189
189
  getFileById: (s) => e.find((r) => r.id === s),
190
190
  getUploadProgress: (s) => {
191
191
  var r;
@@ -201,7 +201,7 @@ function H() {
201
201
  }
202
202
  const A = U(null);
203
203
  function J({ children: e }) {
204
- const t = y(), [n, o] = w(t.isOpen ?? !1);
204
+ const t = y(), [n, o] = w(() => t.inline ? !0 : t.isOpen ?? !1);
205
205
  return h(() => {
206
206
  o((i) => t.isOpen ?? i);
207
207
  }, [t.isOpen]), h(() => {
@@ -222,14 +222,14 @@ function K() {
222
222
  }
223
223
  function Q() {
224
224
  var d, S;
225
- const { widgetCtx: e } = g(), { modesComponents: t } = y(), { sessionState: n } = E(), o = e.modes, i = (d = n.session) == null ? void 0 : d.modeId, a = o.find((p) => p.id === i), u = (S = t == null ? void 0 : t.find(
226
- (p) => {
225
+ const { widgetCtx: e } = g(), { modesComponents: t } = y(), { sessionState: n } = E(), o = e.modes, i = (d = n.session) == null ? void 0 : d.modeId, a = o.find((f) => f.id === i), u = (S = t == null ? void 0 : t.find(
226
+ (f) => {
227
227
  var s, r;
228
228
  return [
229
229
  (a == null ? void 0 : a.id) || "",
230
230
  ((s = a == null ? void 0 : a.name) == null ? void 0 : s.toLowerCase()) || "",
231
231
  ((r = a == null ? void 0 : a.slug) == null ? void 0 : r.toLowerCase()) || ""
232
- ].includes(p.key.toLowerCase());
232
+ ].includes(f.key.toLowerCase());
233
233
  }
234
234
  )) == null ? void 0 : S.component;
235
235
  return {
@@ -256,4 +256,4 @@ export {
256
256
  Q as l,
257
257
  g as u
258
258
  };
259
- //# sourceMappingURL=useModes-B5-vdm1q.js.map
259
+ //# sourceMappingURL=useModes-Dm1CBDor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useModes-B5-vdm1q.js","sources":["../src/headless/react/ComponentRegistry.ts","../src/headless/react/WidgetProvider.tsx","../src/headless/react/hooks/useConfig.ts","../src/headless/react/hooks/usePrimitiveState.ts","../src/headless/react/hooks/useContact.ts","../src/headless/react/hooks/useMessages.ts","../src/headless/react/hooks/useSessions.ts","../src/headless/react/hooks/useIsAwaitingBotReply.ts","../src/headless/react/hooks/usePreludeData.ts","../src/headless/react/hooks/useWidgetRouter.ts","../src/headless/react/hooks/useUploadFiles.ts","../src/headless/react/hooks/useWidgetTrigger.tsx","../src/headless/react/hooks/useModes.ts"],"sourcesContent":["import type { WidgetComponentKey } from '../core';\nimport type { WidgetComponentType } from './types/components';\n\nexport class ComponentRegistry {\n components: WidgetComponentType[] = [];\n\n constructor(opts: { components?: WidgetComponentType[] }) {\n const { components } = opts;\n\n if (components) {\n components.forEach((c) => this.register(c));\n }\n\n if (this.components.length === 0) {\n throw new Error('No components registered');\n }\n if (!this.get('fallback')) {\n throw new Error('No fallback component registered');\n }\n }\n\n // TODO test that this registers or replaces the component\n register(component: WidgetComponentType) {\n // Replace the key if it already exists\n const index = this.components.findIndex((c) => c.key === component.key);\n if (index !== -1) {\n this.components[index] = component;\n } else {\n this.components.push(component);\n }\n return this;\n }\n\n private get(key: WidgetComponentKey) {\n const c = this.components.find(\n (c) => c.key.toUpperCase() === key.toUpperCase(),\n );\n if (c) return c;\n return null;\n }\n\n public getComponent(key: string) {\n return this.get(key)?.component;\n }\n}\n","import React, {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { version } from '../../../package.json';\nimport { type ExternalStorage, type WidgetConfig, WidgetCtx } from '../core';\nimport { ComponentRegistry } from './ComponentRegistry';\nimport type { WidgetComponentType } from './types/components';\n\ninterface WidgetProviderValue {\n widgetCtx: WidgetCtx;\n config: WidgetConfig;\n components?: WidgetComponentType[];\n componentStore: ComponentRegistry;\n version: string;\n contentIframeRef?: React.MutableRefObject<HTMLIFrameElement | null>;\n}\n\nconst context = createContext<WidgetProviderValue | null>(null);\n\nexport function WidgetProvider({\n options: config,\n children,\n components,\n storage,\n loadingComponent,\n}: {\n options: WidgetConfig;\n children: React.ReactNode;\n components?: WidgetComponentType[];\n storage?: ExternalStorage;\n /**\n * Custom loading component while the widget is initializing\n * Not to be confused with the `loading` custom component which renders when the bot's reply is pending\n */\n loadingComponent?: React.ReactNode;\n}) {\n const contentIframeRef = useRef<HTMLIFrameElement | null>(null);\n\n const didInitialize = useRef(false);\n const [widgetCtx, setWidgetCtx] = useState<WidgetCtx | null>(null);\n\n const componentStore = useMemo(\n () =>\n new ComponentRegistry({\n components: components,\n }),\n [components],\n );\n\n useEffect(() => {\n if (didInitialize.current) return;\n didInitialize.current = true;\n\n WidgetCtx.initialize({ config, storage }).then(setWidgetCtx);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n if (!widgetCtx) {\n return loadingComponent || null;\n }\n\n return (\n <context.Provider\n value={{\n widgetCtx,\n config,\n components,\n componentStore,\n version,\n contentIframeRef,\n }}\n >\n {children}\n </context.Provider>\n );\n}\n\nexport function useWidget() {\n const ctx = useContext(context);\n if (!ctx) {\n throw new Error('useWidget must be used within a WidgetProvider');\n }\n return ctx;\n}\n","import { useWidget } from '../WidgetProvider';\n\nexport function useConfig() {\n const { config } = useWidget();\n\n return config;\n}\n","import { useSyncExternalStore } from 'react';\nimport type { PrimitiveState } from '../../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 { usePrimitiveState } from './usePrimitiveState';\nimport { useWidget } from '../WidgetProvider';\n\nexport function useMessages() {\n const { widgetCtx } = useWidget();\n const messagesState = usePrimitiveState(widgetCtx.messageCtx.state);\n\n return { messagesState, sendMessage: widgetCtx.messageCtx.sendMessage };\n}\n","import { useMemo } from 'react';\nimport { useWidget } from '../WidgetProvider';\nimport { usePrimitiveState } from './usePrimitiveState';\nimport { useConfig } from './useConfig';\n\nexport function useSessions() {\n const { widgetCtx } = useWidget();\n const { oneOpenSessionAllowed } = useConfig();\n const sessionState = usePrimitiveState(widgetCtx.sessionCtx.sessionState);\n const sessionsState = usePrimitiveState(widgetCtx.sessionCtx.sessionsState);\n\n const { openSessions, closedSessions } = useMemo(() => {\n return {\n openSessions: sessionsState.data.filter((s) => s.isOpened === true),\n closedSessions: sessionsState.data.filter((s) => s.isOpened === false),\n };\n }, [sessionsState.data]);\n\n const canCreateNewSession = useMemo(() => {\n if (oneOpenSessionAllowed) {\n return openSessions.length === 0;\n }\n return true;\n }, [oneOpenSessionAllowed, openSessions.length]);\n\n return {\n sessionState,\n sessionsState,\n loadMoreSessions: widgetCtx.sessionCtx.loadMoreSessions,\n resolveSession: widgetCtx.sessionCtx.resolveSession,\n createStateCheckpoint: widgetCtx.sessionCtx.createStateCheckpoint,\n openSessions,\n closedSessions,\n canCreateNewSession,\n };\n}\n","import { useMessages } from './useMessages';\nimport { useSessions } from './useSessions';\n\nexport function useIsAwaitingBotReply() {\n const { sessionState } = useSessions();\n const { messagesState } = useMessages();\n\n const isSessionAssignedToAI = sessionState.session?.assignee.kind === 'ai';\n // This check is useful in cases where the user might navigate in and out of a chat, and `isSendingMessage` is reset back to its default value\n const lastMessage =\n messagesState.messages.length > 0\n ? messagesState.messages[messagesState.messages.length - 1]\n : null;\n const isLastMessageAUserMessage = lastMessage?.type === 'FROM_USER';\n\n const isAwaitingBotReply =\n (isSessionAssignedToAI || sessionState.isCreatingSession) &&\n (messagesState.isSendingMessage || isLastMessageAUserMessage);\n\n return { isAwaitingBotReply };\n}\n","import useSWR from 'swr';\nimport { useWidget } from '../WidgetProvider';\n\nfunction usePreludeData() {\n const { widgetCtx } = useWidget();\n\n // TODO remove swr dependency\n return useSWR([widgetCtx.config.token], widgetCtx.api.widgetPrelude, {\n revalidateOnFocus: false,\n });\n}\n\nexport { usePreludeData };\n","import { useWidget } from '../WidgetProvider';\nimport { usePrimitiveState } from './usePrimitiveState';\n\nexport function useWidgetRouter() {\n const { widgetCtx } = useWidget();\n\n const routerState = usePrimitiveState(widgetCtx.routerCtx.state);\n\n return {\n routerState,\n toSessionsScreen: widgetCtx.routerCtx.toSessionsScreen,\n toChatScreen: widgetCtx.routerCtx.toChatScreen,\n };\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport { useWidget } from '../WidgetProvider';\nimport { v4 } from 'uuid';\n\nconst uploadAbortControllers: Map<string, AbortController> = new Map();\n\ninterface FileWithProgress {\n status: 'pending' | 'uploading' | 'success' | 'error';\n id: string;\n file: File;\n fileUrl?: string;\n progress: number;\n error?: string;\n}\n\nfunction useUploadFiles() {\n const [files, setFiles] = useState<FileWithProgress[]>([]);\n const {\n widgetCtx: { api },\n } = useWidget();\n function appendFiles(files: File[]) {\n const newFiles = files.map((file) => ({\n file,\n id: v4(),\n status: 'pending' as const,\n progress: 0,\n }));\n\n setFiles((prev) => [...prev, ...newFiles]);\n newFiles.forEach(uploadFile);\n }\n\n function updateFileById(id: string, update: Partial<FileWithProgress>) {\n setFiles((prev) =>\n prev.map((f) => (f.id === id ? { ...f, ...update } : f)),\n );\n }\n\n function removeFileById(id: string) {\n setFiles((prev) => prev.filter((f) => f.id !== id));\n }\n\n const uploadFile = async (fileItem: FileWithProgress) => {\n const controller = new AbortController();\n uploadAbortControllers.set(fileItem.id, controller);\n\n try {\n setFiles((prev) =>\n prev.map((f) =>\n f.id === fileItem.id ? { ...f, status: 'uploading', progress: 0 } : f,\n ),\n );\n\n const response = await api.uploadFile({\n file: fileItem.file,\n abortSignal: controller.signal,\n onProgress: (percentage) => {\n updateFileById(fileItem.id, { progress: percentage });\n },\n });\n\n updateFileById(fileItem.id, {\n status: 'success',\n fileUrl: response.fileUrl,\n progress: 100,\n });\n } catch (error) {\n if (!controller.signal.aborted) {\n updateFileById(fileItem.id, {\n status: 'error',\n error: error instanceof Error ? error.message : 'Upload failed',\n progress: 0,\n });\n }\n } finally {\n uploadAbortControllers.delete(fileItem.id);\n }\n };\n\n const handleCancelUpload = (fileId: string) => {\n const controller = uploadAbortControllers.get(fileId);\n if (controller) {\n controller.abort();\n uploadAbortControllers.delete(fileId);\n }\n removeFileById(fileId);\n };\n\n const successFiles = useMemo(() => {\n return files.filter((f) => f.status === 'success' && f.fileUrl);\n }, [files]);\n\n function emptyTheFiles() {\n uploadAbortControllers.forEach((controller) => controller.abort());\n uploadAbortControllers.clear();\n setFiles([]);\n }\n\n useEffect(() => {\n return () => {\n uploadAbortControllers.forEach((controller) => controller.abort());\n uploadAbortControllers.clear();\n };\n }, []);\n\n return {\n allFiles: files,\n appendFiles,\n handleCancelUpload,\n successFiles,\n emptyTheFiles,\n getFileById: (id: string) => files.find((f) => f.id === id),\n getUploadProgress: (id: string) =>\n files.find((f) => f.id === id)?.progress ?? 0,\n getUploadStatus: (id: string) => files.find((f) => f.id === id)?.status,\n hasErrors: files.some((f) => f.status === 'error'),\n isUploading: files.some((f) => f.status === 'uploading'),\n };\n}\n\nexport { useUploadFiles, type FileWithProgress };\n","import React, {\n createContext,\n useContext,\n useEffect,\n useState,\n type Dispatch,\n type ReactNode,\n type SetStateAction,\n} from 'react';\nimport { useConfig } from './useConfig';\n\ntype WidgetTriggerCtx = {\n isOpen: boolean;\n setIsOpen: Dispatch<SetStateAction<boolean>>;\n};\n\nconst context = createContext<WidgetTriggerCtx | null>(null);\n\nexport function WidgetTriggerProvider({ children }: { children: ReactNode }) {\n const config = useConfig();\n const [isOpen, setIsOpen] = useState(config.isOpen ?? false);\n\n useEffect(() => {\n setIsOpen((prev) => config.isOpen ?? prev);\n }, [config.isOpen]);\n\n useEffect(() => {\n const openAfterNSeconds = config.openAfterNSeconds;\n if (typeof openAfterNSeconds !== 'number' || isNaN(openAfterNSeconds))\n return;\n\n const timeout = setTimeout(() => setIsOpen(true), openAfterNSeconds * 1000);\n\n return () => clearTimeout(timeout);\n }, [config.openAfterNSeconds]);\n\n return (\n <context.Provider value={{ isOpen, setIsOpen }}>\n {children}\n </context.Provider>\n );\n}\n\nexport function useWidgetTrigger() {\n const ctx = useContext(context);\n if (!ctx) {\n throw new Error(\n 'useWidgetTrigger must be used within a WidgetTriggerProvider',\n );\n }\n return ctx;\n}\n","import { useWidget } from '../WidgetProvider';\nimport { useConfig } from './useConfig';\nimport { useSessions } from './useSessions';\n\nexport function useModes() {\n const { widgetCtx } = useWidget();\n const { modesComponents } = useConfig();\n const { sessionState } = useSessions();\n\n const modes = widgetCtx.modes;\n const activeModeId = sessionState.session?.modeId;\n const activeMode = modes.find((mode) => mode.id === activeModeId);\n\n const Component = modesComponents?.find((modeComponent) =>\n [\n activeMode?.id || '',\n activeMode?.name?.toLowerCase() || '',\n activeMode?.slug?.toLowerCase() || '',\n ].includes(modeComponent.key.toLowerCase()),\n )?.component;\n\n return {\n modes,\n modesComponents,\n activeModeId,\n activeMode,\n Component,\n };\n}\n"],"names":["ComponentRegistry","opts","components","c","component","index","key","_a","context","createContext","WidgetProvider","config","children","storage","loadingComponent","contentIframeRef","useRef","didInitialize","widgetCtx","setWidgetCtx","useState","componentStore","useMemo","useEffect","WidgetCtx","jsx","version","useWidget","ctx","useContext","useConfig","usePrimitiveState","p","useSyncExternalStore","useContact","useMessages","useSessions","oneOpenSessionAllowed","sessionState","sessionsState","openSessions","closedSessions","s","canCreateNewSession","useIsAwaitingBotReply","messagesState","isSessionAssignedToAI","lastMessage","isLastMessageAUserMessage","usePreludeData","useSWR","useWidgetRouter","uploadAbortControllers","useUploadFiles","files","setFiles","api","appendFiles","newFiles","file","v4","prev","uploadFile","updateFileById","id","update","removeFileById","f","fileItem","controller","response","percentage","error","handleCancelUpload","fileId","successFiles","emptyTheFiles","WidgetTriggerProvider","isOpen","setIsOpen","openAfterNSeconds","timeout","useWidgetTrigger","useModes","modesComponents","modes","activeModeId","activeMode","mode","Component","_b","modeComponent"],"mappings":"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"}
1
+ {"version":3,"file":"useModes-Dm1CBDor.js","sources":["../src/headless/react/ComponentRegistry.ts","../src/headless/react/WidgetProvider.tsx","../src/headless/react/hooks/useConfig.ts","../src/headless/react/hooks/usePrimitiveState.ts","../src/headless/react/hooks/useContact.ts","../src/headless/react/hooks/useMessages.ts","../src/headless/react/hooks/useSessions.ts","../src/headless/react/hooks/useIsAwaitingBotReply.ts","../src/headless/react/hooks/usePreludeData.ts","../src/headless/react/hooks/useWidgetRouter.ts","../src/headless/react/hooks/useUploadFiles.ts","../src/headless/react/hooks/useWidgetTrigger.tsx","../src/headless/react/hooks/useModes.ts"],"sourcesContent":["import type { WidgetComponentKey } from '../core';\nimport type { WidgetComponentType } from './types/components';\n\nexport class ComponentRegistry {\n components: WidgetComponentType[] = [];\n\n constructor(opts: { components?: WidgetComponentType[] }) {\n const { components } = opts;\n\n if (components) {\n components.forEach((c) => this.register(c));\n }\n\n if (this.components.length === 0) {\n throw new Error('No components registered');\n }\n if (!this.get('fallback')) {\n throw new Error('No fallback component registered');\n }\n }\n\n // TODO test that this registers or replaces the component\n register(component: WidgetComponentType) {\n // Replace the key if it already exists\n const index = this.components.findIndex((c) => c.key === component.key);\n if (index !== -1) {\n this.components[index] = component;\n } else {\n this.components.push(component);\n }\n return this;\n }\n\n private get(key: WidgetComponentKey) {\n const c = this.components.find(\n (c) => c.key.toUpperCase() === key.toUpperCase(),\n );\n if (c) return c;\n return null;\n }\n\n public getComponent(key: string) {\n return this.get(key)?.component;\n }\n}\n","import React, {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { version } from '../../../package.json';\nimport { type ExternalStorage, type WidgetConfig, WidgetCtx } from '../core';\nimport { ComponentRegistry } from './ComponentRegistry';\nimport type { WidgetComponentType } from './types/components';\n\ninterface WidgetProviderValue {\n widgetCtx: WidgetCtx;\n config: WidgetConfig;\n components?: WidgetComponentType[];\n componentStore: ComponentRegistry;\n version: string;\n contentIframeRef?: React.MutableRefObject<HTMLIFrameElement | null>;\n}\n\nconst context = createContext<WidgetProviderValue | null>(null);\n\nexport function WidgetProvider({\n options: config,\n children,\n components,\n storage,\n loadingComponent,\n}: {\n options: WidgetConfig;\n children: React.ReactNode;\n components?: WidgetComponentType[];\n storage?: ExternalStorage;\n /**\n * Custom loading component while the widget is initializing\n * Not to be confused with the `loading` custom component which renders when the bot's reply is pending\n */\n loadingComponent?: React.ReactNode;\n}) {\n const contentIframeRef = useRef<HTMLIFrameElement | null>(null);\n\n const didInitialize = useRef(false);\n const [widgetCtx, setWidgetCtx] = useState<WidgetCtx | null>(null);\n\n const componentStore = useMemo(\n () =>\n new ComponentRegistry({\n components: components,\n }),\n [components],\n );\n\n useEffect(() => {\n if (didInitialize.current) return;\n didInitialize.current = true;\n\n WidgetCtx.initialize({ config, storage }).then(setWidgetCtx);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n if (!widgetCtx) {\n return loadingComponent || null;\n }\n\n return (\n <context.Provider\n value={{\n widgetCtx,\n config,\n components,\n componentStore,\n version,\n contentIframeRef,\n }}\n >\n {children}\n </context.Provider>\n );\n}\n\nexport function useWidget() {\n const ctx = useContext(context);\n if (!ctx) {\n throw new Error('useWidget must be used within a WidgetProvider');\n }\n return ctx;\n}\n","import { useWidget } from '../WidgetProvider';\n\nexport function useConfig() {\n const { config } = useWidget();\n\n return config;\n}\n","import { useSyncExternalStore } from 'react';\nimport type { PrimitiveState } from '../../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 { usePrimitiveState } from './usePrimitiveState';\nimport { useWidget } from '../WidgetProvider';\n\nexport function useMessages() {\n const { widgetCtx } = useWidget();\n const messagesState = usePrimitiveState(widgetCtx.messageCtx.state);\n\n return { messagesState, sendMessage: widgetCtx.messageCtx.sendMessage };\n}\n","import { useMemo } from 'react';\nimport { useWidget } from '../WidgetProvider';\nimport { usePrimitiveState } from './usePrimitiveState';\nimport { useConfig } from './useConfig';\n\nexport function useSessions() {\n const { widgetCtx } = useWidget();\n const { oneOpenSessionAllowed } = useConfig();\n const sessionState = usePrimitiveState(widgetCtx.sessionCtx.sessionState);\n const sessionsState = usePrimitiveState(widgetCtx.sessionCtx.sessionsState);\n\n const { openSessions, closedSessions } = useMemo(() => {\n return {\n openSessions: sessionsState.data.filter((s) => s.isOpened === true),\n closedSessions: sessionsState.data.filter((s) => s.isOpened === false),\n };\n }, [sessionsState.data]);\n\n const canCreateNewSession = useMemo(() => {\n if (oneOpenSessionAllowed) {\n return openSessions.length === 0;\n }\n return true;\n }, [oneOpenSessionAllowed, openSessions.length]);\n\n return {\n sessionState,\n sessionsState,\n loadMoreSessions: widgetCtx.sessionCtx.loadMoreSessions,\n resolveSession: widgetCtx.sessionCtx.resolveSession,\n createStateCheckpoint: widgetCtx.sessionCtx.createStateCheckpoint,\n openSessions,\n closedSessions,\n canCreateNewSession,\n };\n}\n","import { useMessages } from './useMessages';\nimport { useSessions } from './useSessions';\n\nexport function useIsAwaitingBotReply() {\n const { sessionState } = useSessions();\n const { messagesState } = useMessages();\n\n const isSessionAssignedToAI = sessionState.session?.assignee.kind === 'ai';\n // This check is useful in cases where the user might navigate in and out of a chat, and `isSendingMessage` is reset back to its default value\n const lastMessage =\n messagesState.messages.length > 0\n ? messagesState.messages[messagesState.messages.length - 1]\n : null;\n const isLastMessageAUserMessage = lastMessage?.type === 'FROM_USER';\n\n const isAwaitingBotReply =\n (isSessionAssignedToAI || sessionState.isCreatingSession) &&\n (messagesState.isSendingMessage || isLastMessageAUserMessage);\n\n return { isAwaitingBotReply };\n}\n","import useSWR from 'swr';\nimport { useWidget } from '../WidgetProvider';\n\nfunction usePreludeData() {\n const { widgetCtx } = useWidget();\n\n // TODO remove swr dependency\n return useSWR([widgetCtx.config.token], widgetCtx.api.widgetPrelude, {\n revalidateOnFocus: false,\n });\n}\n\nexport { usePreludeData };\n","import { useWidget } from '../WidgetProvider';\nimport { usePrimitiveState } from './usePrimitiveState';\n\nexport function useWidgetRouter() {\n const { widgetCtx } = useWidget();\n\n const routerState = usePrimitiveState(widgetCtx.routerCtx.state);\n\n return {\n routerState,\n toSessionsScreen: widgetCtx.routerCtx.toSessionsScreen,\n toChatScreen: widgetCtx.routerCtx.toChatScreen,\n };\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport { useWidget } from '../WidgetProvider';\nimport { v4 } from 'uuid';\n\nconst uploadAbortControllers: Map<string, AbortController> = new Map();\n\ninterface FileWithProgress {\n status: 'pending' | 'uploading' | 'success' | 'error';\n id: string;\n file: File;\n fileUrl?: string;\n progress: number;\n error?: string;\n}\n\nfunction useUploadFiles() {\n const [files, setFiles] = useState<FileWithProgress[]>([]);\n const {\n widgetCtx: { api },\n } = useWidget();\n function appendFiles(files: File[]) {\n const newFiles = files.map((file) => ({\n file,\n id: v4(),\n status: 'pending' as const,\n progress: 0,\n }));\n\n setFiles((prev) => [...prev, ...newFiles]);\n newFiles.forEach(uploadFile);\n }\n\n function updateFileById(id: string, update: Partial<FileWithProgress>) {\n setFiles((prev) =>\n prev.map((f) => (f.id === id ? { ...f, ...update } : f)),\n );\n }\n\n function removeFileById(id: string) {\n setFiles((prev) => prev.filter((f) => f.id !== id));\n }\n\n const uploadFile = async (fileItem: FileWithProgress) => {\n const controller = new AbortController();\n uploadAbortControllers.set(fileItem.id, controller);\n\n try {\n setFiles((prev) =>\n prev.map((f) =>\n f.id === fileItem.id ? { ...f, status: 'uploading', progress: 0 } : f,\n ),\n );\n\n const response = await api.uploadFile({\n file: fileItem.file,\n abortSignal: controller.signal,\n onProgress: (percentage) => {\n updateFileById(fileItem.id, { progress: percentage });\n },\n });\n\n updateFileById(fileItem.id, {\n status: 'success',\n fileUrl: response.fileUrl,\n progress: 100,\n });\n } catch (error) {\n if (!controller.signal.aborted) {\n updateFileById(fileItem.id, {\n status: 'error',\n error: error instanceof Error ? error.message : 'Upload failed',\n progress: 0,\n });\n }\n } finally {\n uploadAbortControllers.delete(fileItem.id);\n }\n };\n\n const handleCancelUpload = (fileId: string) => {\n const controller = uploadAbortControllers.get(fileId);\n if (controller) {\n controller.abort();\n uploadAbortControllers.delete(fileId);\n }\n removeFileById(fileId);\n };\n\n const successFiles = useMemo(() => {\n return files.filter((f) => f.status === 'success' && f.fileUrl);\n }, [files]);\n\n function emptyTheFiles() {\n uploadAbortControllers.forEach((controller) => controller.abort());\n uploadAbortControllers.clear();\n setFiles([]);\n }\n\n useEffect(() => {\n return () => {\n uploadAbortControllers.forEach((controller) => controller.abort());\n uploadAbortControllers.clear();\n };\n }, []);\n\n return {\n allFiles: files,\n appendFiles,\n handleCancelUpload,\n successFiles,\n emptyTheFiles,\n getFileById: (id: string) => files.find((f) => f.id === id),\n getUploadProgress: (id: string) =>\n files.find((f) => f.id === id)?.progress ?? 0,\n getUploadStatus: (id: string) => files.find((f) => f.id === id)?.status,\n hasErrors: files.some((f) => f.status === 'error'),\n isUploading: files.some((f) => f.status === 'uploading'),\n };\n}\n\nexport { useUploadFiles, type FileWithProgress };\n","import React, {\n createContext,\n useContext,\n useEffect,\n useState,\n type Dispatch,\n type ReactNode,\n type SetStateAction,\n} from 'react';\nimport { useConfig } from './useConfig';\n\ntype WidgetTriggerCtx = {\n isOpen: boolean;\n setIsOpen: Dispatch<SetStateAction<boolean>>;\n};\n\nconst context = createContext<WidgetTriggerCtx | null>(null);\n\nexport function WidgetTriggerProvider({ children }: { children: ReactNode }) {\n const config = useConfig();\n const [isOpen, setIsOpen] = useState(() => {\n if (config.inline) return true;\n return config.isOpen ?? false;\n });\n\n useEffect(() => {\n setIsOpen((prev) => config.isOpen ?? prev);\n }, [config.isOpen]);\n\n useEffect(() => {\n const openAfterNSeconds = config.openAfterNSeconds;\n if (typeof openAfterNSeconds !== 'number' || isNaN(openAfterNSeconds))\n return;\n\n const timeout = setTimeout(() => setIsOpen(true), openAfterNSeconds * 1000);\n\n return () => clearTimeout(timeout);\n }, [config.openAfterNSeconds]);\n\n return (\n <context.Provider value={{ isOpen, setIsOpen }}>\n {children}\n </context.Provider>\n );\n}\n\nexport function useWidgetTrigger() {\n const ctx = useContext(context);\n if (!ctx) {\n throw new Error(\n 'useWidgetTrigger must be used within a WidgetTriggerProvider',\n );\n }\n return ctx;\n}\n","import { useWidget } from '../WidgetProvider';\nimport { useConfig } from './useConfig';\nimport { useSessions } from './useSessions';\n\nexport function useModes() {\n const { widgetCtx } = useWidget();\n const { modesComponents } = useConfig();\n const { sessionState } = useSessions();\n\n const modes = widgetCtx.modes;\n const activeModeId = sessionState.session?.modeId;\n const activeMode = modes.find((mode) => mode.id === activeModeId);\n\n const Component = modesComponents?.find((modeComponent) =>\n [\n activeMode?.id || '',\n activeMode?.name?.toLowerCase() || '',\n activeMode?.slug?.toLowerCase() || '',\n ].includes(modeComponent.key.toLowerCase()),\n )?.component;\n\n return {\n modes,\n modesComponents,\n activeModeId,\n activeMode,\n Component,\n };\n}\n"],"names":["ComponentRegistry","opts","components","c","component","index","key","_a","context","createContext","WidgetProvider","config","children","storage","loadingComponent","contentIframeRef","useRef","didInitialize","widgetCtx","setWidgetCtx","useState","componentStore","useMemo","useEffect","WidgetCtx","jsx","version","useWidget","ctx","useContext","useConfig","usePrimitiveState","p","useSyncExternalStore","useContact","useMessages","useSessions","oneOpenSessionAllowed","sessionState","sessionsState","openSessions","closedSessions","s","canCreateNewSession","useIsAwaitingBotReply","messagesState","isSessionAssignedToAI","lastMessage","isLastMessageAUserMessage","usePreludeData","useSWR","useWidgetRouter","uploadAbortControllers","useUploadFiles","files","setFiles","api","appendFiles","newFiles","file","v4","prev","uploadFile","updateFileById","id","update","f","removeFileById","fileItem","controller","response","percentage","error","handleCancelUpload","fileId","successFiles","emptyTheFiles","WidgetTriggerProvider","isOpen","setIsOpen","openAfterNSeconds","timeout","useWidgetTrigger","useModes","modesComponents","modes","activeModeId","activeMode","mode","Component","_b","modeComponent"],"mappings":";;;;;;AAGO,MAAMA,EAAkB;AAAA,EAG7B,YAAYC,GAA8C;AAF1D,SAAA,aAAoC;AAG5B,UAAA,EAAE,YAAAC,EAAe,IAAAD;AAMnB,QAJAC,KACFA,EAAW,QAAQ,CAACC,MAAM,KAAK,SAASA,CAAC,CAAC,GAGxC,KAAK,WAAW,WAAW;AACvB,YAAA,IAAI,MAAM,0BAA0B;AAE5C,QAAI,CAAC,KAAK,IAAI,UAAU;AAChB,YAAA,IAAI,MAAM,kCAAkC;AAAA,EAEtD;AAAA;AAAA,EAGA,SAASC,GAAgC;AAEjC,UAAAC,IAAQ,KAAK,WAAW,UAAU,CAACF,MAAMA,EAAE,QAAQC,EAAU,GAAG;AACtE,WAAIC,MAAU,KACP,KAAA,WAAWA,CAAK,IAAID,IAEpB,KAAA,WAAW,KAAKA,CAAS,GAEzB;AAAA,EACT;AAAA,EAEQ,IAAIE,GAAyB;AAC7B,UAAAH,IAAI,KAAK,WAAW;AAAA,MACxB,CAACA,MAAMA,EAAE,IAAI,YAAY,MAAMG,EAAI,YAAY;AAAA,IAAA;AAEjD,WAAIH,KACG;AAAA,EACT;AAAA,EAEO,aAAaG,GAAa;;AACxB,YAAAC,IAAA,KAAK,IAAID,CAAG,MAAZ,gBAAAC,EAAe;AAAA,EACxB;AACF;ACtBA,MAAMC,IAAUC,EAA0C,IAAI;AAEvD,SAASC,EAAe;AAAA,EAC7B,SAASC;AAAA,EACT,UAAAC;AAAA,EACA,YAAAV;AAAA,EACA,SAAAW;AAAA,EACA,kBAAAC;AACF,GAUG;AACK,QAAAC,IAAmBC,EAAiC,IAAI,GAExDC,IAAgBD,EAAO,EAAK,GAC5B,CAACE,GAAWC,CAAY,IAAIC,EAA2B,IAAI,GAE3DC,IAAiBC;AAAA,IACrB,MACE,IAAItB,EAAkB;AAAA,MACpB,YAAAE;AAAA,IAAA,CACD;AAAA,IACH,CAACA,CAAU;AAAA,EAAA;AAWb,SARAqB,EAAU,MAAM;AACd,IAAIN,EAAc,YAClBA,EAAc,UAAU,IAExBO,EAAU,WAAW,EAAE,QAAAb,GAAQ,SAAAE,GAAS,EAAE,KAAKM,CAAY;AAAA,EAE7D,GAAG,CAAE,CAAA,GAEAD,IAKH,gBAAAO;AAAA,IAACjB,EAAQ;AAAA,IAAR;AAAA,MACC,OAAO;AAAA,QACL,WAAAU;AAAA,QACA,QAAAP;AAAA,QACA,YAAAT;AAAA,QACA,gBAAAmB;AAAA,QACA,SAAAK;AAAA,QACA,kBAAAX;AAAA,MACF;AAAA,MAEC,UAAAH;AAAA,IAAA;AAAA,EAAA,IAdIE,KAAoB;AAiB/B;AAEO,SAASa,IAAY;AACpB,QAAAC,IAAMC,EAAWrB,CAAO;AAC9B,MAAI,CAACoB;AACG,UAAA,IAAI,MAAM,gDAAgD;AAE3D,SAAAA;AACT;ACtFO,SAASE,IAAY;AACpB,QAAA,EAAE,QAAAnB,MAAWgB;AAEZ,SAAAhB;AACT;ACHO,SAASoB,EAAqBC,GAAsB;AACzD,SAAOC,EAAqBD,EAAE,WAAWA,EAAE,KAAKA,EAAE,GAAG;AACvD;ACFO,SAASE,IAAa;AACrB,QAAA,EAAE,WAAAhB,MAAcS;AAGf,SAAA;AAAA,IACL,cAHmBI,EAAkBb,EAAU,WAAW,KAAK;AAAA,IAI/D,yBAAyBA,EAAU,WAAW;AAAA,EAAA;AAElD;ACRO,SAASiB,IAAc;AACtB,QAAA,EAAE,WAAAjB,MAAcS;AAGtB,SAAO,EAAE,eAFaI,EAAkBb,EAAU,WAAW,KAAK,GAE1C,aAAaA,EAAU,WAAW,YAAY;AACxE;ACHO,SAASkB,IAAc;AACtB,QAAA,EAAE,WAAAlB,MAAcS,KAChB,EAAE,uBAAAU,MAA0BP,KAC5BQ,IAAeP,EAAkBb,EAAU,WAAW,YAAY,GAClEqB,IAAgBR,EAAkBb,EAAU,WAAW,aAAa,GAEpE,EAAE,cAAAsB,GAAc,gBAAAC,EAAe,IAAInB,EAAQ,OACxC;AAAA,IACL,cAAciB,EAAc,KAAK,OAAO,CAACG,MAAMA,EAAE,aAAa,EAAI;AAAA,IAClE,gBAAgBH,EAAc,KAAK,OAAO,CAACG,MAAMA,EAAE,aAAa,EAAK;AAAA,EAAA,IAEtE,CAACH,EAAc,IAAI,CAAC,GAEjBI,IAAsBrB,EAAQ,MAC9Be,IACKG,EAAa,WAAW,IAE1B,IACN,CAACH,GAAuBG,EAAa,MAAM,CAAC;AAExC,SAAA;AAAA,IACL,cAAAF;AAAA,IACA,eAAAC;AAAA,IACA,kBAAkBrB,EAAU,WAAW;AAAA,IACvC,gBAAgBA,EAAU,WAAW;AAAA,IACrC,uBAAuBA,EAAU,WAAW;AAAA,IAC5C,cAAAsB;AAAA,IACA,gBAAAC;AAAA,IACA,qBAAAE;AAAA,EAAA;AAEJ;AChCO,SAASC,IAAwB;;AAChC,QAAA,EAAE,cAAAN,MAAiBF,KACnB,EAAE,eAAAS,MAAkBV,KAEpBW,MAAwBvC,IAAA+B,EAAa,YAAb,gBAAA/B,EAAsB,SAAS,UAAS,MAEhEwC,IACJF,EAAc,SAAS,SAAS,IAC5BA,EAAc,SAASA,EAAc,SAAS,SAAS,CAAC,IACxD,MACAG,KAA4BD,KAAA,gBAAAA,EAAa,UAAS;AAMxD,SAAO,EAAE,qBAHND,KAAyBR,EAAa,uBACtCO,EAAc,oBAAoBG,GAET;AAC9B;ACjBA,SAASC,IAAiB;AAClB,QAAA,EAAE,WAAA/B,MAAcS;AAGf,SAAAuB,EAAO,CAAChC,EAAU,OAAO,KAAK,GAAGA,EAAU,IAAI,eAAe;AAAA,IACnE,mBAAmB;AAAA,EAAA,CACpB;AACH;ACPO,SAASiC,IAAkB;AAC1B,QAAA,EAAE,WAAAjC,MAAcS;AAIf,SAAA;AAAA,IACL,aAHkBI,EAAkBb,EAAU,UAAU,KAAK;AAAA,IAI7D,kBAAkBA,EAAU,UAAU;AAAA,IACtC,cAAcA,EAAU,UAAU;AAAA,EAAA;AAEtC;ACTA,MAAMkC,wBAA2D;AAWjE,SAASC,IAAiB;AACxB,QAAM,CAACC,GAAOC,CAAQ,IAAInC,EAA6B,CAAE,CAAA,GACnD;AAAA,IACJ,WAAW,EAAE,KAAAoC,EAAI;AAAA,MACf7B,EAAU;AACd,WAAS8B,EAAYH,GAAe;AAClC,UAAMI,IAAWJ,EAAM,IAAI,CAACK,OAAU;AAAA,MACpC,MAAAA;AAAA,MACA,IAAIC,EAAG;AAAA,MACP,QAAQ;AAAA,MACR,UAAU;AAAA,IACV,EAAA;AAEF,IAAAL,EAAS,CAACM,MAAS,CAAC,GAAGA,GAAM,GAAGH,CAAQ,CAAC,GACzCA,EAAS,QAAQI,CAAU;AAAA,EAC7B;AAES,WAAAC,EAAeC,GAAYC,GAAmC;AACrE,IAAAV;AAAA,MAAS,CAACM,MACRA,EAAK,IAAI,CAACK,MAAOA,EAAE,OAAOF,IAAK,EAAE,GAAGE,GAAG,GAAGD,EAAA,IAAWC,CAAE;AAAA,IAAA;AAAA,EAE3D;AAEA,WAASC,EAAeH,GAAY;AACzB,IAAAT,EAAA,CAACM,MAASA,EAAK,OAAO,CAACK,MAAMA,EAAE,OAAOF,CAAE,CAAC;AAAA,EACpD;AAEM,QAAAF,IAAa,OAAOM,MAA+B;AACjD,UAAAC,IAAa,IAAI;AACA,IAAAjB,EAAA,IAAIgB,EAAS,IAAIC,CAAU;AAE9C,QAAA;AACF,MAAAd;AAAA,QAAS,CAACM,MACRA,EAAK;AAAA,UAAI,CAACK,MACRA,EAAE,OAAOE,EAAS,KAAK,EAAE,GAAGF,GAAG,QAAQ,aAAa,UAAU,EAAM,IAAAA;AAAA,QACtE;AAAA,MAAA;AAGI,YAAAI,IAAW,MAAMd,EAAI,WAAW;AAAA,QACpC,MAAMY,EAAS;AAAA,QACf,aAAaC,EAAW;AAAA,QACxB,YAAY,CAACE,MAAe;AAC1B,UAAAR,EAAeK,EAAS,IAAI,EAAE,UAAUG,EAAY,CAAA;AAAA,QACtD;AAAA,MAAA,CACD;AAED,MAAAR,EAAeK,EAAS,IAAI;AAAA,QAC1B,QAAQ;AAAA,QACR,SAASE,EAAS;AAAA,QAClB,UAAU;AAAA,MAAA,CACX;AAAA,aACME,GAAO;AACV,MAACH,EAAW,OAAO,WACrBN,EAAeK,EAAS,IAAI;AAAA,QAC1B,QAAQ;AAAA,QACR,OAAOI,aAAiB,QAAQA,EAAM,UAAU;AAAA,QAChD,UAAU;AAAA,MAAA,CACX;AAAA,IACH,UACA;AACuB,MAAApB,EAAA,OAAOgB,EAAS,EAAE;AAAA,IAC3C;AAAA,EAAA,GAGIK,IAAqB,CAACC,MAAmB;AACvC,UAAAL,IAAajB,EAAuB,IAAIsB,CAAM;AACpD,IAAIL,MACFA,EAAW,MAAM,GACjBjB,EAAuB,OAAOsB,CAAM,IAEtCP,EAAeO,CAAM;AAAA,EAAA,GAGjBC,IAAerD,EAAQ,MACpBgC,EAAM,OAAO,CAACY,MAAMA,EAAE,WAAW,aAAaA,EAAE,OAAO,GAC7D,CAACZ,CAAK,CAAC;AAEV,WAASsB,IAAgB;AACvB,IAAAxB,EAAuB,QAAQ,CAACiB,MAAeA,EAAW,MAAO,CAAA,GACjEjB,EAAuB,MAAM,GAC7BG,EAAS,CAAE,CAAA;AAAA,EACb;AAEA,SAAAhC,EAAU,MACD,MAAM;AACX,IAAA6B,EAAuB,QAAQ,CAACiB,MAAeA,EAAW,MAAO,CAAA,GACjEjB,EAAuB,MAAM;AAAA,EAAA,GAE9B,CAAE,CAAA,GAEE;AAAA,IACL,UAAUE;AAAA,IACV,aAAAG;AAAA,IACA,oBAAAgB;AAAA,IACA,cAAAE;AAAA,IACA,eAAAC;AAAA,IACA,aAAa,CAACZ,MAAeV,EAAM,KAAK,CAACY,MAAMA,EAAE,OAAOF,CAAE;AAAA,IAC1D,mBAAmB,CAACA;;AAClB,eAAAzD,IAAA+C,EAAM,KAAK,CAACY,MAAMA,EAAE,OAAOF,CAAE,MAA7B,gBAAAzD,EAAgC,aAAY;AAAA;AAAA,IAC9C,iBAAiB,CAACyD,MAAe;;AAAA,cAAAzD,IAAA+C,EAAM,KAAK,CAACY,MAAMA,EAAE,OAAOF,CAAE,MAA7B,gBAAAzD,EAAgC;AAAA;AAAA,IACjE,WAAW+C,EAAM,KAAK,CAACY,MAAMA,EAAE,WAAW,OAAO;AAAA,IACjD,aAAaZ,EAAM,KAAK,CAACY,MAAMA,EAAE,WAAW,WAAW;AAAA,EAAA;AAE3D;ACtGA,MAAM1D,IAAUC,EAAuC,IAAI;AAE3C,SAAAoE,EAAsB,EAAE,UAAAjE,KAAqC;AAC3E,QAAMD,IAASmB,KACT,CAACgD,GAAQC,CAAS,IAAI3D,EAAS,MAC/BT,EAAO,SAAe,KACnBA,EAAO,UAAU,EACzB;AAED,SAAAY,EAAU,MAAM;AACd,IAAAwD,EAAU,CAAClB,MAASlD,EAAO,UAAUkD,CAAI;AAAA,EAAA,GACxC,CAAClD,EAAO,MAAM,CAAC,GAElBY,EAAU,MAAM;AACd,UAAMyD,IAAoBrE,EAAO;AACjC,QAAI,OAAOqE,KAAsB,YAAY,MAAMA,CAAiB;AAClE;AAEF,UAAMC,IAAU,WAAW,MAAMF,EAAU,EAAI,GAAGC,IAAoB,GAAI;AAEnE,WAAA,MAAM,aAAaC,CAAO;AAAA,EAAA,GAChC,CAACtE,EAAO,iBAAiB,CAAC,GAG3B,gBAAAc,EAACjB,EAAQ,UAAR,EAAiB,OAAO,EAAE,QAAAsE,GAAQ,WAAAC,EAAU,GAC1C,UAAAnE,EACH,CAAA;AAEJ;AAEO,SAASsE,IAAmB;AAC3B,QAAAtD,IAAMC,EAAWrB,CAAO;AAC9B,MAAI,CAACoB;AACH,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAGG,SAAAA;AACT;AClDO,SAASuD,IAAW;;AACnB,QAAA,EAAE,WAAAjE,MAAcS,KAChB,EAAE,iBAAAyD,MAAoBtD,KACtB,EAAE,cAAAQ,MAAiBF,KAEnBiD,IAAQnE,EAAU,OAClBoE,KAAe/E,IAAA+B,EAAa,YAAb,gBAAA/B,EAAsB,QACrCgF,IAAaF,EAAM,KAAK,CAACG,MAASA,EAAK,OAAOF,CAAY,GAE1DG,KAAYC,IAAAN,KAAA,gBAAAA,EAAiB;AAAA,IAAK,CAACO,MACvC;;AAAA;AAAA,SACEJ,KAAA,gBAAAA,EAAY,OAAM;AAAA,UAClBhF,IAAAgF,KAAA,gBAAAA,EAAY,SAAZ,gBAAAhF,EAAkB,kBAAiB;AAAA,UACnCmF,IAAAH,KAAA,gBAAAA,EAAY,SAAZ,gBAAAG,EAAkB,kBAAiB;AAAA,MACnC,EAAA,SAASC,EAAc,IAAI,aAAa;AAAA;AAAA,QAL1B,gBAAAD,EAMf;AAEI,SAAA;AAAA,IACL,OAAAL;AAAA,IACA,iBAAAD;AAAA,IACA,cAAAE;AAAA,IACA,YAAAC;AAAA,IACA,WAAAE;AAAA,EAAA;AAEJ;"}