@webority/mobile-chat 0.133.0 → 0.135.0
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/lib/commonjs/AgentByline.js +1 -1
- package/lib/commonjs/ChatAppearanceScope.js +1 -0
- package/lib/commonjs/ChatComposer.js +1 -1
- package/lib/commonjs/ChatConversationActions.js +1 -1
- package/lib/commonjs/ChatDictationButton.js +1 -1
- package/lib/commonjs/ChatEmbed.js +1 -1
- package/lib/commonjs/ChatFooter.js +1 -1
- package/lib/commonjs/ChatFrame.js +1 -1
- package/lib/commonjs/ChatHistory.js +1 -1
- package/lib/commonjs/ChatLauncher.js +1 -0
- package/lib/commonjs/ChatLiveBar.js +1 -1
- package/lib/commonjs/ChatMessageActions.js +1 -1
- package/lib/commonjs/ChatNudge.js +1 -1
- package/lib/commonjs/ChatOpenTickets.js +1 -1
- package/lib/commonjs/ChatPanel.js +1 -0
- package/lib/commonjs/ChatPastChats.js +1 -0
- package/lib/commonjs/ChatScreen.js +1 -1
- package/lib/commonjs/ChatSheet.js +1 -1
- package/lib/commonjs/ChatStarters.js +1 -1
- package/lib/commonjs/ChatThread.js +1 -1
- package/lib/commonjs/ReadAloudButton.js +1 -1
- package/lib/commonjs/chatShared.js +1 -1
- package/lib/commonjs/features.map.json +3 -3
- package/lib/commonjs/index.js +1 -1
- package/lib/commonjs/loaders/ChatLoader.js +1 -1
- package/lib/commonjs/renderers/ActionPart.js +1 -1
- package/lib/commonjs/renderers/ChartPart.js +1 -1
- package/lib/commonjs/renderers/FigureText.js +1 -1
- package/lib/commonjs/renderers/FiguresPart.js +1 -1
- package/lib/commonjs/renderers/FilePart.js +1 -1
- package/lib/commonjs/renderers/HandoffPart.js +1 -1
- package/lib/commonjs/renderers/ImagePart.js +1 -1
- package/lib/commonjs/renderers/InputRequestPart.js +1 -1
- package/lib/commonjs/renderers/NoticePart.js +1 -1
- package/lib/commonjs/renderers/QuickRepliesPart.js +1 -1
- package/lib/commonjs/renderers/RecordCardPart.js +1 -1
- package/lib/commonjs/renderers/SourcesPart.js +1 -1
- package/lib/commonjs/renderers/TablePart.js +1 -1
- package/lib/commonjs/renderers/TicketPart.js +1 -1
- package/lib/commonjs/renderers/VoiceClipPart.js +1 -1
- package/lib/commonjs/speech/phoneSpeech.js +1 -1
- package/lib/commonjs/speech/speechText.js +1 -1
- package/lib/commonjs/useChat.js +1 -1
- package/lib/commonjs/useChatHaptics.js +1 -1
- package/lib/commonjs/useChatSound.js +1 -0
- package/lib/module/AgentByline.js +1 -1
- package/lib/module/ChatAppearanceScope.js +1 -0
- package/lib/module/ChatComposer.js +1 -1
- package/lib/module/ChatConversationActions.js +1 -1
- package/lib/module/ChatDictationButton.js +1 -1
- package/lib/module/ChatEmbed.js +1 -1
- package/lib/module/ChatFooter.js +1 -1
- package/lib/module/ChatFrame.js +1 -1
- package/lib/module/ChatHistory.js +1 -1
- package/lib/module/ChatLauncher.js +1 -0
- package/lib/module/ChatLiveBar.js +1 -1
- package/lib/module/ChatMessageActions.js +1 -1
- package/lib/module/ChatNudge.js +1 -1
- package/lib/module/ChatOpenTickets.js +1 -1
- package/lib/module/ChatPanel.js +1 -0
- package/lib/module/ChatPastChats.js +1 -0
- package/lib/module/ChatScreen.js +1 -1
- package/lib/module/ChatSheet.js +1 -1
- package/lib/module/ChatStarters.js +1 -1
- package/lib/module/ChatThread.js +1 -1
- package/lib/module/ReadAloudButton.js +1 -1
- package/lib/module/chatShared.js +1 -1
- package/lib/module/features.map.json +3 -3
- package/lib/module/index.js +1 -1
- package/lib/module/loaders/ChatLoader.js +1 -1
- package/lib/module/renderers/ActionPart.js +1 -1
- package/lib/module/renderers/ChartPart.js +1 -1
- package/lib/module/renderers/FigureText.js +1 -1
- package/lib/module/renderers/FiguresPart.js +1 -1
- package/lib/module/renderers/FilePart.js +1 -1
- package/lib/module/renderers/HandoffPart.js +1 -1
- package/lib/module/renderers/ImagePart.js +1 -1
- package/lib/module/renderers/InputRequestPart.js +1 -1
- package/lib/module/renderers/NoticePart.js +1 -1
- package/lib/module/renderers/QuickRepliesPart.js +1 -1
- package/lib/module/renderers/RecordCardPart.js +1 -1
- package/lib/module/renderers/SourcesPart.js +1 -1
- package/lib/module/renderers/TablePart.js +1 -1
- package/lib/module/renderers/TicketPart.js +1 -1
- package/lib/module/renderers/VoiceClipPart.js +1 -1
- package/lib/module/speech/phoneSpeech.js +1 -1
- package/lib/module/speech/speechText.js +1 -1
- package/lib/module/useChat.js +1 -1
- package/lib/module/useChatHaptics.js +1 -1
- package/lib/module/useChatSound.js +1 -0
- package/lib/typescript/commonjs/ChatAppearanceScope.d.ts +11 -0
- package/lib/typescript/commonjs/ChatComposer.d.ts +5 -2
- package/lib/typescript/commonjs/ChatConversationActions.d.ts +1 -1
- package/lib/typescript/commonjs/ChatDictationButton.d.ts +3 -1
- package/lib/typescript/commonjs/ChatEmbed.d.ts +1 -1
- package/lib/typescript/commonjs/ChatFrame.d.ts +15 -4
- package/lib/typescript/commonjs/ChatLauncher.d.ts +22 -0
- package/lib/typescript/commonjs/ChatPanel.d.ts +39 -0
- package/lib/typescript/commonjs/ChatPastChats.d.ts +21 -0
- package/lib/typescript/commonjs/ChatScreen.d.ts +1 -1
- package/lib/typescript/commonjs/ChatSheet.d.ts +1 -6
- package/lib/typescript/commonjs/ChatThread.d.ts +3 -1
- package/lib/typescript/commonjs/chatShared.d.ts +2 -0
- package/lib/typescript/commonjs/index.d.ts +2 -1
- package/lib/typescript/commonjs/renderers/ChartPart.d.ts +1 -1
- package/lib/typescript/commonjs/renderers/FigureText.d.ts +4 -2
- package/lib/typescript/commonjs/renderers/HandoffPart.d.ts +1 -1
- package/lib/typescript/commonjs/renderers/ImagePart.d.ts +2 -1
- package/lib/typescript/commonjs/renderers/VoiceClipPart.d.ts +1 -1
- package/lib/typescript/commonjs/speech/speechText.d.ts +3 -3
- package/lib/typescript/commonjs/types.d.ts +28 -2
- package/lib/typescript/commonjs/useChat.d.ts +2 -0
- package/lib/typescript/commonjs/useChatSound.d.ts +35 -0
- package/lib/typescript/module/ChatAppearanceScope.d.ts +11 -0
- package/lib/typescript/module/ChatComposer.d.ts +5 -2
- package/lib/typescript/module/ChatConversationActions.d.ts +1 -1
- package/lib/typescript/module/ChatDictationButton.d.ts +3 -1
- package/lib/typescript/module/ChatEmbed.d.ts +1 -1
- package/lib/typescript/module/ChatFrame.d.ts +15 -4
- package/lib/typescript/module/ChatLauncher.d.ts +22 -0
- package/lib/typescript/module/ChatPanel.d.ts +39 -0
- package/lib/typescript/module/ChatPastChats.d.ts +21 -0
- package/lib/typescript/module/ChatScreen.d.ts +1 -1
- package/lib/typescript/module/ChatSheet.d.ts +1 -6
- package/lib/typescript/module/ChatThread.d.ts +3 -1
- package/lib/typescript/module/chatShared.d.ts +2 -0
- package/lib/typescript/module/index.d.ts +2 -1
- package/lib/typescript/module/renderers/ChartPart.d.ts +1 -1
- package/lib/typescript/module/renderers/FigureText.d.ts +4 -2
- package/lib/typescript/module/renderers/HandoffPart.d.ts +1 -1
- package/lib/typescript/module/renderers/ImagePart.d.ts +2 -1
- package/lib/typescript/module/renderers/VoiceClipPart.d.ts +1 -1
- package/lib/typescript/module/speech/speechText.d.ts +3 -3
- package/lib/typescript/module/types.d.ts +28 -2
- package/lib/typescript/module/useChat.d.ts +2 -0
- package/lib/typescript/module/useChatSound.d.ts +35 -0
- package/package.json +10 -9
package/lib/module/ChatThread.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{createTurnApi,messagePlainText}from"@webority/chat-core";import{Button,MessageBubble,MessageList,Text,useTheme}from"@webority/mobile-ui";import{createElement,memo,useEffect,useMemo,useRef}from"react";import{AccessibilityInfo,View}from"react-native";import{AgentByline}from"./AgentByline.js";import{ChatEntrance}from"./ChatEntrance.js";import{ChatMessageActions}from"./ChatMessageActions.js";import{defaultOpenTarget,messageSignature}from"./chatShared.js";import{ChatLoader}from"./loaders/ChatLoader.js";import{TypingPill}from"./loaders/TypingPill.js";import{defaultRenderers}from"./renderers/index.js";import{NoticePart}from"./renderers/NoticePart.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const MINE=new Set(["Visitor","Customer"]),joinedText=e=>e.filter(e=>"Text"===e.kind).map(e=>e.text).join("\n\n"),renderPart=(e,t,s,a,r,i)=>{const n=e[t.kind];if(n)return createElement(n,{key:i,part:t,message:s,turn:a,pickAttachments:r});const o={kind:"Notice",code:"NeedsNewerApp",text:a.labels.needsNewerApp};return createElement(NoticePart,{key:i,part:o,message:s,turn:a})},sameMessage=(e,t)=>e.signature===t.signature&&e.message.id===t.message.id&&e.message.rating===t.message.rating&&e.message.stored===t.message.stored&&e.groupPosition===t.groupPosition&&e.isLast===t.isLast&&e.isLastVisitor===t.isLastVisitor&&e.thinking===t.thinking&&e.streaming===t.streaming&&e.pickAttachments===t.pickAttachments&&e.labels===t.labels&&e.all===t.all&&e.layoutParts===t.layoutParts&&e.chat.session===t.chat.session&&e.chat.features===t.chat.features&&e.chat.onNavigate===t.chat.onNavigate&&e.onNavigate===t.onNavigate&&e.onOpenAttachment===t.onOpenAttachment&&e.onOpenTarget===t.onOpenTarget&&e.openTicket===t.openTicket&&e.handoffHosts===t.handoffHosts;function ThreadMessageView({chat:e,message:t,labels:s,all:a,layoutParts:r,groupPosition:i,isLast:n,isLastVisitor:o,pickAttachments:l,onOpenAttachment:
|
|
1
|
+
"use strict";import{createTurnApi,formatChatDateTime,handoffSettledIds,messagePlainText}from"@webority/chat-core";import{Button,MessageBubble,MessageList,Text,useTheme}from"@webority/mobile-ui";import{createElement,memo,useEffect,useMemo,useRef}from"react";import{AccessibilityInfo,View}from"react-native";import{AgentByline}from"./AgentByline.js";import{ChatEntrance}from"./ChatEntrance.js";import{ChatMessageActions}from"./ChatMessageActions.js";import{defaultOpenTarget,focusForAccessibility,messageSignature}from"./chatShared.js";import{ChatLoader}from"./loaders/ChatLoader.js";import{TypingPill}from"./loaders/TypingPill.js";import{defaultRenderers}from"./renderers/index.js";import{NoticePart}from"./renderers/NoticePart.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const MINE=new Set(["Visitor","Customer"]),joinedText=e=>e.filter(e=>"Text"===e.kind).map(e=>e.text).join("\n\n"),renderPart=(e,t,s,a,r,i)=>{const n=e[t.kind];if(n)return createElement(n,{key:i,part:t,message:s,turn:a,pickAttachments:r});const o={kind:"Notice",code:"NeedsNewerApp",text:a.labels.needsNewerApp};return createElement(NoticePart,{key:i,part:o,message:s,turn:a})},sameMessage=(e,t)=>e.signature===t.signature&&e.message.id===t.message.id&&e.message.rating===t.message.rating&&e.message.stored===t.message.stored&&e.groupPosition===t.groupPosition&&e.isLast===t.isLast&&e.handoffSettled===t.handoffSettled&&e.isLastVisitor===t.isLastVisitor&&e.thinking===t.thinking&&e.streaming===t.streaming&&e.pickAttachments===t.pickAttachments&&e.labels===t.labels&&e.all===t.all&&e.layoutParts===t.layoutParts&&e.chat.session===t.chat.session&&e.chat.features===t.chat.features&&e.chat.onNavigate===t.chat.onNavigate&&e.onNavigate===t.onNavigate&&e.onOpenAttachment===t.onOpenAttachment&&e.onOpenTarget===t.onOpenTarget&&e.openTicket===t.openTicket&&e.resolveLink===t.resolveLink&&e.focusComposer===t.focusComposer&&e.byline===t.byline&&e.handoffHosts===t.handoffHosts;function ThreadMessageView({chat:e,message:t,labels:s,all:a,layoutParts:r,groupPosition:i,isLast:n,isLastVisitor:o,pickAttachments:l,onOpenAttachment:c,onOpenTarget:g,onNavigate:m,openTicket:d,handoffHosts:p,resolveLink:u,focusComposer:h,byline:f,sourceRows:y,testID:x}){const T=useTheme(),k=Object.assign(createTurnApi(e.session,{messageId:t.id,labels:s,openAttachment:c,openTarget:g??defaultOpenTarget,onNavigate:m??e.onNavigate,openTicket:d,handoffHosts:p,openCitation:e=>{return t=String(e),void focusForAccessibility(y.current.get(t));var t}}),{resolveLink:u,focusComposer:h,registerSourceRow:(e,t)=>{t?y.current.set(e,t):y.current.delete(e)}});let b=0;const nextSlot=()=>(b+=1,b),A=_jsx(ChatMessageActions,{chat:e,message:t,labels:s,isLast:n,isLastVisitor:o,testID:`${x}-actions`});if(MINE.has(t.author.kind)){const e=t.parts.filter(e=>"File"===e.kind),r=_jsxs(View,{style:{gap:T.space.xs},children:[e.map(e=>renderPart(a,e,t,k,l,`${t.id}-file-${nextSlot()}`)),A]});return _jsx(MessageBubble,{side:"mine",text:joinedText(t.parts),labels:{you:s.you},groupPosition:i,footer:r,testID:x})}const j="Agent"===t.author.kind,w=t.author.displayName||s.agent,v=(r?r(t):t.parts).map(e=>Array.isArray(e)?_jsx(View,{style:{flexDirection:"row",flexWrap:"wrap",gap:T.space.xs},children:e.map(e=>renderPart(a,e,t,k,l,`${t.id}-part-${nextSlot()}`))},`${t.id}-group-${nextSlot()}`):renderPart(a,e,t,k,l,`${t.id}-item-${nextSlot()}`)),N=j&&f?[_jsx(AgentByline,{author:t.author,labels:s},`${t.id}-byline`),...v]:v,_=messagePlainText(t.parts);return _jsx(MessageBubble,{side:"theirs",author:j?void 0:t.author.displayName||s.assistant,text:j?`${s.agentSays(w)} ${_}`:_,streaming:t.streaming,groupPosition:i,footer:A,testID:x,children:N})}const ThreadMessage=memo(ThreadMessageView,sameMessage),TYPING_ORB_MARK=14,TYPING_ASSISTANT_MARK=8,TypingMark=({size:e})=>{const t=useTheme();return _jsx(View,{style:{width:e,height:e,borderRadius:t.radius.pill,backgroundColor:t.colors.primary}})},TYPING_DOT=6,TypingDots=()=>{const e=useTheme();return _jsx(View,{style:{flexDirection:"row",alignItems:"center",gap:e.space.xxs},children:[0,1,2].map(t=>_jsx(View,{style:{width:6,height:6,borderRadius:3,backgroundColor:e.colors["text-muted"]}},t))})},TurnGap=()=>{const e=useTheme();return _jsx(View,{style:{height:e.space.lg}})},followNew=()=>!0;export function ChatThread({chat:e,labels:t,renderers:s,layoutParts:a,loader:r="Steps",motion:i="On",pickAttachments:n,onOpenAttachment:o,onOpenTarget:l,onNavigate:c,openTicket:g,handoffHosts:m,resolveLink:d,focusComposer:p,keyboardAware:u,keyboardOffset:h,empty:f,style:y,testID:x="chat-thread"}){const T=useTheme(),k=useMemo(()=>({...defaultRenderers,...s}),[s]),b=e.messages[0],A=e.greeting??"",j=useMemo(()=>""!==A&&void 0!==b&&MINE.has(b.author.kind)?{...b,id:"greeting",author:{...b.author,kind:"Assistant",displayName:null,avatarUrl:null},parts:[{kind:"Text",text:A}],stored:!1,streaming:!1,restored:!1,rating:null}:null,[A,b]),w=useMemo(()=>{const t=e.messages.filter(e=>!(e.streaming&&0===e.parts.length)).reverse();return j?[...t,j]:t},[e.messages,j]),v=e.messages[e.messages.length-1]?.id,N=useRef(new Map),_=useRef(null);useEffect(()=>{if(null!==_.current)for(const s of e.messages){if(MINE.has(s.author.kind)||s.streaming||s.restored||_.current.has(s.id))continue;if("Agent"===s.author.kind&&!s.stored)continue;_.current.add(s.id);const e=messagePlainText(s.parts);""!==e&&AccessibilityInfo.announceForAccessibility("Agent"===s.author.kind?`${t.agentSays(s.author.displayName||t.agent)} ${e}`:e)}else _.current=new Set(e.messages.map(e=>e.id))},[e.messages,t]);const M=useMemo(()=>{for(let t=e.messages.length-1;t>=0;t-=1){const s=e.messages[t];if(s?.stored&&"Visitor"===s.author.kind)return s.id}},[e.messages]),P=useMemo(()=>{const t=new Set;return e.messages.forEach((s,a)=>{if("Agent"!==s.author.kind)return;const r=e.messages[a-1];"Agent"===r?.author.kind&&(r.author.displayName||"")===(s.author.displayName||"")||t.add(s.id)}),t},[e.messages]),L=useMemo(()=>handoffSettledIds(e.messages),[e.messages]),I=e.turnError,S="daily_limit"===I?.code,C=null!==I&&/feature_off$/.test(I.code),$=S&&I?.resetsDateTimeUtc?` ${t.dailyLimitRefresh(formatChatDateTime(I.resetsDateTimeUtc))}`:"",D=e.streaming||null===I&&!e.stopped?null:_jsxs(View,{style:{gap:T.space.xs},testID:`${x}-error`,children:[_jsx(Text,null!==I?{variant:"bodySmall",color:"danger",accessibilityRole:S?void 0:"alert",accessibilityLiveRegion:S?"polite":void 0,children:`${I.message}${$}`}:{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:t.stopped}),!e.features.Retry||S||C?null:_jsx(View,{style:{flexDirection:"row"},children:_jsx(Button,{label:t.retry,variant:"link",size:"sm",onPress:()=>{e.retry()},testID:`${x}-retry`})})]}),V=e.thinking&&null!==e.profile?_jsx(ChatLoader,{style:r,steps:e.steps,phrases:e.profile.experience.pacing.thinkingPhrases,intervalMs:e.profile.experience.pacing.phraseIntervalMs,announce:t.preparingAnswer(e.profile.assistant.name),motion:i}):null,O=!0===e.pending?.typing?_jsx(TypingPill,{motion:i,mark:_jsx(TypingMark,{size:"Orb"===r?14:8})}):null,R=null!==e.agentTyping&&"WithAgent"===e.conversationState?_jsxs(View,{style:{gap:T.space.xs,alignSelf:"flex-start"},children:[_jsx(TypingPill,{motion:i,mark:_jsx(TypingDots,{})}),_jsx(Text,{variant:"caption",color:"secondary",accessibilityLiveRegion:"polite",children:t.agentTyping(e.agentTyping.displayName||t.agent)})]}):null,E=O||V||D||R?_jsxs(View,{style:{gap:T.space.sm},children:[O,V,R,D]}):void 0;return _jsx(MessageList,{messages:w,keyExtractor:e=>e.id,renderMessage:({item:s,groupPosition:r})=>_jsx(ChatEntrance,{animate:!s.restored,children:_jsx(ThreadMessage,{chat:e,message:s,signature:messageSignature(s),labels:t,all:k,layoutParts:a,groupPosition:r,isLast:s.id===v,isLastVisitor:s.id===M,handoffSettled:L.has(s.id),thinking:e.thinking,streaming:e.streaming,pickAttachments:n,onOpenAttachment:o,onOpenTarget:l,onNavigate:c,openTicket:g,handoffHosts:m,resolveLink:d,focusComposer:p,byline:P.has(s.id),sourceRows:N,testID:`${x}-${s.id}`})}),getAuthorKey:e=>e.author.kind,getDate:e=>e.createdDateTimeUtc,followNew:followNew,typing:E,empty:f,ItemSeparatorComponent:TurnGap,keyboardAware:u,keyboardOffset:h,accessibilityLabel:t.thread,style:y,testID:x})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{messagePlainText}from"@webority/chat-core";import{Logger}from"@webority/mobile-core";import{IconButton,Text}from"@webority/mobile-ui";import{useEffect,useMemo,useRef,useState}from"react";import{PhoneSpeechError}from"./speech/phoneSpeech.js";import{useChatSpeech}from"./useChatSpeech.js";import{jsx as _jsx,Fragment as _Fragment,jsxs as _jsxs}from"react/jsx-runtime";export function ReadAloudButton({chat:e,message:t,labels:r,testID:o="chat-read-aloud"}){const s=useChatSpeech(e),[a,n]=useState(!1),[i,u]=useState(!1),c=useRef(null),l=useRef(!0),m=useMemo(()=>
|
|
1
|
+
"use strict";import{messagePlainText}from"@webority/chat-core";import{Logger}from"@webority/mobile-core";import{IconButton,Text}from"@webority/mobile-ui";import{useEffect,useMemo,useRef,useState}from"react";import{PhoneSpeechError}from"./speech/phoneSpeech.js";import{useChatSpeech}from"./useChatSpeech.js";import{jsx as _jsx,Fragment as _Fragment,jsxs as _jsxs}from"react/jsx-runtime";function spokenText(e){return messagePlainText(e.filter(e=>"Text"===e.kind)).replace(/ ?\[\d+\]/g,"").replace(/\s+/g," ").trim()}export function ReadAloudButton({chat:e,message:t,labels:r,testID:o="chat-read-aloud"}){const s=useChatSpeech(e),[a,n]=useState(!1),[i,u]=useState(!1),c=useRef(null),l=useRef(!0),m=useMemo(()=>spokenText(t.parts),[t.parts]);if(useEffect(()=>(l.current=!0,()=>{l.current=!1,c.current?.abort()}),[]),!e.features.ReadAloud||null===s||t.streaming||""===m.trim())return null;return _jsxs(_Fragment,{children:[_jsx(IconButton,{icon:a?"stop":"volume-high",accessibilityLabel:a?r.readAloudStop:r.readAloud,variant:"ghost",tone:"neutral",size:"sm",onPress:()=>{if(a)return void c.current?.abort();u(!1);const e=new AbortController;c.current=e,n(!0);(async()=>{try{await s.speak(m,{signal:e.signal})}catch(t){if(!l.current||e.signal.aborted)return;u(!0),t instanceof PhoneSpeechError||Logger.error("[chat] read aloud failed",t)}finally{l.current&&(c.current=null,n(!1))}})()},testID:o}),i?_jsx(Text,{variant:"caption",color:"danger",accessibilityLiveRegion:"polite",children:r.readAloudFailed}):null]})}
|
package/lib/module/chatShared.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{Linking}from"react-native";export function messageSignature(t){let e=0;for(const
|
|
1
|
+
"use strict";import{AccessibilityInfo,findNodeHandle,Linking,Platform}from"react-native";export function focusForAccessibility(t){if(null==t)return;if("web"===Platform.OS)return void t.focus?.();const e=findNodeHandle(t);null!==e&&AccessibilityInfo.setAccessibilityFocus(e)}export function messageSignature(t){let e=0;for(const i of t.parts)"Text"===i.kind&&(e+=i.text.length);return`${t.id}|${t.parts.length}|${e}`}const ABSOLUTE_WEB_URL=/^https?:\/\//i;export function defaultOpenTarget(t){ABSOLUTE_WEB_URL.test(t)&&Linking.openURL(t).catch(()=>{})}
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
"ResumeLast": "src/ChatStarters.tsx",
|
|
6
6
|
"OpenTickets": "src/ChatOpenTickets.tsx",
|
|
7
7
|
"History": "src/ChatFrame.tsx",
|
|
8
|
-
"Rename": "src/
|
|
9
|
-
"Delete": "src/
|
|
8
|
+
"Rename": "src/ChatPastChats.tsx",
|
|
9
|
+
"Delete": "src/ChatPastChats.tsx",
|
|
10
10
|
"SuggestedReplies": "src/renderers/QuickRepliesPart.tsx",
|
|
11
11
|
"Stop": "src/ChatComposer.tsx",
|
|
12
12
|
"Retry": "src/ChatThread.tsx",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"VoiceClips": "src/renderers/VoiceClipPart.tsx",
|
|
31
31
|
"Sounds": "src/useChatHaptics.ts",
|
|
32
32
|
"AutoOpen": null,
|
|
33
|
-
"BehaviourStarters": "src/
|
|
33
|
+
"BehaviourStarters": "../chat-core/src/session.ts",
|
|
34
34
|
"LeadShortcuts": "src/renderers/InputRequestPart.tsx",
|
|
35
35
|
"LeadRecap": "src/renderers/ActionPart.tsx",
|
|
36
36
|
"FigureText": "src/renderers/TextPart.tsx",
|
package/lib/module/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";export{AgentByline}from"./AgentByline.js";export{ChatComposer}from"./ChatComposer.js";export{ChatConversationActions}from"./ChatConversationActions.js";export{ChatDictationButton}from"./ChatDictationButton.js";export{ChatEmbed}from"./ChatEmbed.js";export{ChatFooter}from"./ChatFooter.js";export{ChatHistory}from"./ChatHistory.js";export{ChatLiveBar}from"./ChatLiveBar.js";export{ChatMessageActions}from"./ChatMessageActions.js";export{ChatNudge}from"./ChatNudge.js";export{ChatOpenTickets}from"./ChatOpenTickets.js";export{ChatScreen}from"./ChatScreen.js";export{ChatSheet}from"./ChatSheet.js";export{ChatStarters}from"./ChatStarters.js";export{ChatThread}from"./ChatThread.js";export{defaultOpenTarget,messageSignature}from"./chatShared.js";export{ChatLoader}from"./loaders/ChatLoader.js";export{TypingPill}from"./loaders/TypingPill.js";export{CHAT_PUSH_TYPE,chatConversationIdFromPush}from"./pushOpen.js";export{ReadAloudButton}from"./ReadAloudButton.js";export{defaultRenderers}from"./renderers/index.js";export{useChat}from"./useChat.js";export{useChatSpeech}from"./useChatSpeech.js";
|
|
1
|
+
"use strict";export{AgentByline}from"./AgentByline.js";export{ChatComposer}from"./ChatComposer.js";export{ChatConversationActions}from"./ChatConversationActions.js";export{ChatDictationButton}from"./ChatDictationButton.js";export{ChatEmbed}from"./ChatEmbed.js";export{ChatFooter}from"./ChatFooter.js";export{ChatHistory}from"./ChatHistory.js";export{ChatLiveBar}from"./ChatLiveBar.js";export{ChatMessageActions}from"./ChatMessageActions.js";export{ChatNudge}from"./ChatNudge.js";export{ChatOpenTickets}from"./ChatOpenTickets.js";export{ChatPastChats}from"./ChatPastChats.js";export{ChatScreen}from"./ChatScreen.js";export{ChatSheet}from"./ChatSheet.js";export{ChatStarters}from"./ChatStarters.js";export{ChatThread}from"./ChatThread.js";export{defaultOpenTarget,messageSignature}from"./chatShared.js";export{ChatLoader}from"./loaders/ChatLoader.js";export{TypingPill}from"./loaders/TypingPill.js";export{CHAT_PUSH_TYPE,chatConversationIdFromPush}from"./pushOpen.js";export{ReadAloudButton}from"./ReadAloudButton.js";export{defaultRenderers}from"./renderers/index.js";export{useChat}from"./useChat.js";export{useChatSpeech}from"./useChatSpeech.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{LOADER_STYLES,loaderView}from"@webority/chat-core";import{Text,useReducedMotion}from"@webority/mobile-ui";import{useEffect,useRef,useState}from"react";import{StyleSheet,View}from"react-native";import{OrbLoader}from"./OrbLoader.js";import{PhrasesLoader}from"./PhrasesLoader.js";import{SkeletonLoader}from"./SkeletonLoader.js";import{StepsLoader}from"./StepsLoader.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const ANNOUNCE_DELAY_MS=500;export function ChatLoader({style:e="Steps",steps:t=[],phrases:r,intervalMs:s,motion:o="On",announce:i,testID:a="chat-loader"}){if(!LOADER_STYLES.includes(e))throw new Error(`ChatLoader style must be one of ${LOADER_STYLES.join(", ")}; got "${e}".`);const
|
|
1
|
+
"use strict";import{LOADER_STYLES,loaderView}from"@webority/chat-core";import{Text,useReducedMotion}from"@webority/mobile-ui";import{useEffect,useRef,useState}from"react";import{StyleSheet,View}from"react-native";import{OrbLoader}from"./OrbLoader.js";import{PhrasesLoader}from"./PhrasesLoader.js";import{SkeletonLoader}from"./SkeletonLoader.js";import{StepsLoader}from"./StepsLoader.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const ANNOUNCE_DELAY_MS=500;export function ChatLoader({style:e="Steps",steps:t=[],phrases:r,intervalMs:s,motion:o="On",announce:i,testID:a="chat-loader"}){if(!LOADER_STYLES.includes(e))throw new Error(`ChatLoader style must be one of ${LOADER_STYLES.join(", ")}; got "${e}".`);const n=useReducedMotion(),c="Reduced"===o||n,[u,d]=useState({style:e,count:0});useEffect(()=>{d({style:e,count:0})},[e]),useEffect(()=>{if(c)return;const t=setInterval(()=>{d(t=>({style:e,count:(t.style===e?t.count:0)+1}))},s);return()=>clearInterval(t)},[e,s,c]);const l=useRef(i),[f,m]=useState("");useEffect(()=>{const e=setTimeout(()=>m(l.current),500);return()=>clearTimeout(e)},[]);const L=c||u.style!==e?0:u.count,S=loaderView(e,t,r,L);return _jsxs(View,{role:"status",accessibilityLabel:S.label,accessibilityLiveRegion:"polite",testID:a,children:[loaderBody(e,S,c),_jsx(Text,{accessibilityLiveRegion:"polite",style:styles.announce,children:f})]})}const loaderBody=(e,t,r)=>{switch(e){case"Steps":return _jsx(StepsLoader,{view:t,reduced:r});case"Phrases":return _jsx(PhrasesLoader,{view:t,reduced:r});case"Orb":return _jsx(OrbLoader,{view:t,reduced:r});case"Skeleton":return _jsx(SkeletonLoader,{view:t,reduced:r})}},styles=StyleSheet.create({announce:{position:"absolute",width:1,height:1,opacity:0,overflow:"hidden"}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{formatChatDate}from"@webority/chat-core";import{Button,Card,OptionSheet,Text,useTheme}from"@webority/mobile-ui";import{useState}from"react";import{View}from"react-native";import{NoticePart}from"./NoticePart.js";import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";const statusLine=(e,t)=>{switch(e.state){case"Confirmed":return t.actionConfirmed;case"Done":return t.actionDone;case"Rejected":return t.actionRejected;case"Expired":return t.actionExpired;case"Failed":return t.actionFailed;case"Repeat":return e.decidedDateTimeUtc?t.actionRepeat(formatChatDate(e.decidedDateTimeUtc)):t.actionDone;case"Pending":return""}};function ActionBody({part:e,turn:t}){const n=useTheme(),{labels:
|
|
1
|
+
"use strict";import{formatChatDate}from"@webority/chat-core";import{parseInline}from"@webority/markdown-core";import{Button,Card,OptionSheet,Text,useTheme}from"@webority/mobile-ui";import{useState}from"react";import{Linking,Text as RNText,View}from"react-native";import{NoticePart}from"./NoticePart.js";import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";const LEAD_CAPTURE="ChatLeadCapture",SAFE_LINK=/^https?:/,inlineNodes=(e,t)=>e.map(e=>{if("text"===e.type||"code"===e.type||"citation"===e.type)return e.text;if("link"===e.type){const n=inlineNodes(e.children,t);return SAFE_LINK.test(e.href)?_jsx(RNText,{accessibilityRole:"link",style:{color:t.colors.link,textDecorationLine:"underline"},onPress:()=>{Linking.openURL(e.href).catch(()=>{})},children:n},e.key):_jsx(RNText,{children:n},e.key)}if("image"===e.type)return null;const n="strong"===e.type?{fontWeight:t.weight.bold}:"em"===e.type?{fontStyle:"italic"}:{textDecorationLine:"line-through"};return _jsx(RNText,{style:n,children:inlineNodes(e.children,t)},e.key)}),splitLine=e=>{const t=e.indexOf(": ");return t<0?{term:e,detail:null}:{term:e.slice(0,t),detail:e.slice(t+2)}},statusLine=(e,t)=>{switch(e.state){case"Confirmed":return t.actionConfirmed;case"Done":return e.decidedDateTimeUtc?`${t.actionDone} ${formatChatDate(e.decidedDateTimeUtc)}`:t.actionDone;case"Rejected":return t.actionRejected;case"Expired":return t.actionExpired;case"Failed":return t.actionFailed;case"Repeat":return e.decidedDateTimeUtc?t.actionRepeat(formatChatDate(e.decidedDateTimeUtc)):t.actionDone;case"Pending":return""}};function ActionBody({part:e,turn:t}){const n=useTheme(),{labels:i,features:a}=t,[r,o]=useState(null),[s,l]=useState(""),[c,d]=useState(!1),run=async(e,t)=>{o(e),l("");try{await t()}catch(e){const t=e?.message;l("string"==typeof t&&""!==t?t:i.actionFailed),o(null)}},u=(e.editFields??[]).map(e=>({label:e.label,value:e.id})),m=a.LeadRecap&&e.actionKind===LEAD_CAPTURE,p=m&&u.length>0,x=m&&e.confirmLabel||i.actionConfirm,h=m&&e.rejectLabel||i.actionDismiss,f=null!==r;return _jsxs(Card,{variant:"outline",padding:"sm",children:[_jsxs(View,{style:{gap:n.space.sm},children:[_jsx(Text,{variant:"label",children:e.title}),e.lines.map(e=>{if(!m)return _jsx(Text,{variant:"bodySmall",children:e},e);const{term:t,detail:i}=splitLine(e);return _jsxs(View,{style:{flexDirection:"row",flexWrap:"wrap",gap:n.space.xs},children:[_jsx(Text,{variant:"label",children:t}),null!==i?_jsx(Text,{variant:"bodySmall",children:i}):null]},e)}),m&&e.consentText?_jsx(Text,{variant:"caption",color:"secondary",children:inlineNodes(parseInline(e.consentText),n)}):null,"Pending"===e.state?_jsxs(_Fragment,{children:[""!==s?_jsx(Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:s}):null,_jsxs(View,{style:{flexDirection:"row",flexWrap:"wrap",gap:n.space.sm},children:[_jsx(Button,{label:"confirm"===r?i.actionWorking:x,loading:"confirm"===r,disabled:f,onPress:()=>{run("confirm",()=>t.confirmAction(e.actionId))}}),_jsx(Button,{label:h,variant:"ghost",disabled:f,onPress:()=>{run("reject",()=>t.rejectAction(e.actionId))}})]})]}):_jsx(Text,{variant:"bodySmall",color:"Done"===e.state||"Confirmed"===e.state||"Repeat"===e.state?"success":"secondary",children:statusLine(e,i)}),p?_jsx(Button,{label:i.editSomething,variant:"ghost",disabled:f||"Pending"!==e.state,onPress:()=>d(!0)}):null,e.note?_jsx(Text,{variant:"caption",color:"secondary",children:e.note}):null]}),p?_jsx(OptionSheet,{open:c,onClose:()=>d(!1),title:i.editSomething,options:u,onChange:(e,n)=>{d(!1),t.chooseQuickReply({id:`lead.edit:${String(n.value)}`,label:n.label,action:"Send",target:null,navigateAfterMs:null,icon:null,variant:null})}}):null]})}export function ActionPart(e){const{part:t,message:n,turn:i}=e;if("Action"!==t.kind){const e={kind:"Notice",code:"NeedsNewerApp",text:i.labels.needsNewerApp};return _jsx(NoticePart,{part:e,message:n,turn:i})}return _jsx(ActionBody,{part:t,turn:i},t.actionId)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{formatFigure,toFigureText}from"@webority/chat-core";import{formatCompactNumber,formatNumber,formatPercent}from"@webority/mobile-core";import{BarChart,ProgressBar,Sparkline,Text,useTheme}from"@webority/mobile-ui";import{View}from"react-native";import{FigureText,runsToText}from"./FigureText.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const TONES=["primary","info","success","warning","danger","neutral"],toneAt=e=>TONES[e%TONES.length]??"primary",withPositions=e=>e.reduce((e,t)=>(e.push({key:e.length,item:t}),e),[]),writeValue=(e,t)=>{const r=0!==e&&Math.abs(e)<.001?runsToText(formatFigure(e)):formatNumber(e,{maximumFractionDigits:2});return t?`${r} ${t}`:r};export function ChartPart({part:e,turn:t}){const r=useTheme()
|
|
1
|
+
"use strict";import{formatFigure,toFigureText}from"@webority/chat-core";import{formatCompactNumber,formatNumber,formatPercent}from"@webority/mobile-core";import{BarChart,Button,ProgressBar,Sparkline,Text,useTheme}from"@webority/mobile-ui";import{useState}from"react";import{View}from"react-native";import{FigureText,runsToText}from"./FigureText.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const TONES=["primary","info","success","warning","danger","neutral"],toneAt=e=>TONES[e%TONES.length]??"primary",MAX_SERIES=8,withPositions=e=>e.reduce((e,t)=>(e.push({key:e.length,item:t}),e),[]),writeValue=(e,t)=>{const r=0!==e&&Math.abs(e)<.001?runsToText(formatFigure(e)):formatNumber(e,{maximumFractionDigits:2});return t?`${r} ${t}`:r};export function ChartPart({part:e,turn:t}){const r=useTheme(),[a,i]=useState(!1),l="Donut"===e.chartType?e.series.slice(0,1):e.series.slice(0,8);if(l.every(e=>0===e.points.length))return _jsxs(View,{style:{gap:r.space.sm},children:[e.title?_jsx(FigureText,{text:e.title,variant:"label",color:"primary",strong:!0}):null,_jsx(Text,{variant:"bodySmall",color:"secondary",children:t.labels.chartEmpty})]});const{unit:s}=e,o=e.title?toFigureText(e.title):t.labels.chart,n=l.length>1;return _jsxs(View,{accessibilityLabel:o,style:{gap:r.space.sm},children:[e.title?_jsx(FigureText,{text:e.title,variant:"label",color:"primary",strong:!0}):null,_jsx(Button,{label:a?t.labels.chartShowChart:t.labels.chartShowTable,variant:"link",size:"sm",onPress:()=>i(e=>!e)}),withPositions(l).map(({key:i,item:l})=>{const c=toneAt(i),m=toFigureText(l.name)||o,u=l.points;if(0===u.length)return _jsxs(View,{style:{gap:r.space.xs},children:[n?_jsx(Text,{variant:"caption",color:"secondary",children:toFigureText(l.name)}):null,_jsx(Text,{variant:"bodySmall",color:"secondary",children:t.labels.chartEmpty})]},i);const x=u.map(e=>e.value),h=x.reduce((e,t)=>Math.min(e,t)),p=x.reduce((e,t)=>Math.max(e,t)),b=u[0],y=u[u.length-1];let g;if(a)g=_jsx(View,{accessibilityRole:"summary",style:{gap:r.space.xs},children:withPositions(u).map(({key:e,item:t})=>_jsxs(View,{style:{flexDirection:"row",justifyContent:"space-between",gap:r.space.sm},children:[_jsx(Text,{variant:"bodySmall",color:"primary",children:toFigureText(t.label)}),_jsx(Text,{variant:"bodySmall",color:"primary",children:writeValue(t.value,s)})]},e))});else if("Bar"===e.chartType)g=_jsx(BarChart,{data:u.map(e=>({label:toFigureText(e.label),value:e.value})),height:u.length>4?300:240,label:m,formatValue:e=>writeValue(e,s),formatTick:e=>s?`${formatCompactNumber(e)} ${s}`:formatCompactNumber(e),tone:c});else if("Line"===e.chartType)g=_jsxs(View,{style:{gap:r.space.xs},children:[_jsx(Sparkline,{data:x,height:160,fill:!0,tone:c,label:m,formatLabel:e=>writeValue(e,s)}),_jsxs(View,{style:{flexDirection:"row",justifyContent:"space-between"},children:[_jsx(Text,{variant:"caption",color:"tertiary",children:toFigureText(b.label)}),u.length>1?_jsx(Text,{variant:"caption",color:"tertiary",children:toFigureText(y.label)}):null]}),_jsx(Text,{variant:"caption",color:"secondary",children:`${t.labels.chartLow(writeValue(h,s))} ${t.labels.chartHigh(writeValue(p,s))}`})]});else{const e=x.reduce((e,t)=>e+(Number.isFinite(t)&&t>0?t:0),0);g=_jsx(View,{accessibilityRole:"list",style:{gap:r.space.sm},children:withPositions(u).map(({key:t,item:r})=>{const a=e>0&&Number.isFinite(r.value)&&r.value>0?r.value/e:0;return _jsx(ProgressBar,{progress:a,height:8,tone:toneAt(t),label:_jsx(FigureText,{text:r.label,variant:"bodySmall"}),valueLabel:`${writeValue(r.value,s)} (${formatPercent(a,{maximumFractionDigits:0})})`},t)})})}return _jsxs(View,{style:{gap:r.space.xs},children:[n?_jsx(Text,{variant:"caption",color:"secondary",children:toFigureText(l.name)}):null,g]},i)})]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{toFigureRuns}from"@webority/chat-core";import{Text,useTheme}from"@webority/mobile-ui";import{Fragment,useMemo}from"react";import{Text as RNText,View}from"react-native";import{jsx as _jsx}from"react/jsx-runtime";const sizeStepOf=
|
|
1
|
+
"use strict";import{toFigureRuns}from"@webority/chat-core";import{Text,useTheme}from"@webority/mobile-ui";import{Fragment,useMemo}from"react";import{Text as RNText,View}from"react-native";import{jsx as _jsx}from"react/jsx-runtime";const sizeStepOf=e=>"caption"===e?"xs":"bodySmall"===e||"label"===e?"sm":"title"===e?"lg":"base",inkFor=(e,t)=>"secondary"===t?e.colors["text-muted"]:"tertiary"===t?e.colors["text-subtle"]:"success"===t||"warning"===t||"danger"===t||"info"===t?e.colors[`${t}-text`]:e.colors["text-body"];export function runsToText(e){return e.map(e=>e.text).join("")}const withOffsets=e=>e.reduce((e,t)=>{const r=e[e.length-1],n=r?r.offset+r.run.text.length:0;return e.push({offset:n,run:t}),e},[]);function runNode(e,t,r){if("text"===e.kind)return e.text;const n="sub"===e.kind?Math.round(.4*t):-Math.round(.45*t),o=Math.round(.75*t);return _jsx(View,{style:{transform:[{translateY:n}]},children:_jsx(RNText,{style:{fontSize:o,lineHeight:o,includeFontPadding:!1,color:r},children:e.text})})}export function FigureRuns({runs:e,variant:t="bodySmall",color:r,strong:n=!1,numberOfLines:o,accessibilityLabel:s,testID:i,heading:u}){const a=useTheme(),c=a.text[sizeStepOf(t)].size,l=inkFor(a,r);return _jsx(Text,{variant:t,color:r,weight:n?"semibold":void 0,numberOfLines:o,testID:i,accessibilityRole:u?"header":void 0,accessibilityLabel:s??runsToText(e),children:withOffsets(e).map(({offset:e,run:t})=>_jsx(Fragment,{children:runNode(t,c,l)},e))})}export function FigureText({text:e,variant:t="bodySmall",enabled:r=!0,...n}){const o=useMemo(()=>r?toFigureRuns(e):[{kind:"text",text:e}],[e,r]);return _jsx(FigureRuns,{runs:o,variant:t,...n})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{formatFigure,toFigureText}from"@webority/chat-core";import{formatNumber}from"@webority/mobile-core";import{StatTile,useTheme}from"@webority/mobile-ui";import{View}from"react-native";import{FigureRuns,runsToText}from"./FigureText.js";import{jsx as _jsx}from"react/jsx-runtime";const TONE={Neutral:"neutral",Positive:"success",Caution:"warning",Negative:"danger"},withPositions=e=>e.reduce((e,t)=>(e.push({key:e.length,item:t}),e),[]),valueRunsOf=e=>{
|
|
1
|
+
"use strict";import{formatFigure,toFigureRuns,toFigureText}from"@webority/chat-core";import{formatNumber}from"@webority/mobile-core";import{StatTile,useTheme}from"@webority/mobile-ui";import{View}from"react-native";import{FigureRuns,runsToText}from"./FigureText.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const TONE={Neutral:"neutral",Positive:"success",Caution:"warning",Negative:"danger"},withPositions=e=>e.reduce((e,t)=>(e.push({key:e.length,item:t}),e),[]),valueRunsOf=e=>{if(0!==e.value&&Math.abs(e.value)<.001)return formatFigure(e.value);const t=formatNumber(e.value,{maximumFractionDigits:2});return[{kind:"text",text:e.value<0?t.replace("-","−"):t}]};export function FiguresPart({part:e,turn:t}){const i=useTheme();return 0===e.figures.length?null:_jsx(View,{accessibilityRole:"summary",accessibilityLabel:t.labels.figures,style:{flexDirection:"row",flexWrap:"wrap",gap:i.space.sm},children:withPositions(e.figures).map(({key:e,item:i})=>{const r=valueRunsOf(i),s=t.labels.figureStatus(i.status),u=toFigureText(i.label);return _jsx(View,{style:{flexGrow:1,minWidth:110},children:_jsx(StatTile,{label:u,value:_jsxs(View,{style:{flexDirection:"row",alignItems:"flex-end",flexWrap:"wrap"},children:[_jsx(FigureRuns,{runs:r,variant:"title",color:"primary",strong:!0}),i.unit?_jsx(FigureRuns,{runs:[{kind:"text",text:" "},...toFigureRuns(i.unit)],variant:"bodySmall",color:"secondary"}):null]}),tone:TONE[i.status],caption:s||void 0,accessibilityLabel:`${u}: ${runsToText(r)}${i.unit?` ${i.unit}`:""}${s?`, ${s}`:""}`})},e)})})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{formatFileSize}from"@webority/chat-core";import{Chip}from"@webority/mobile-ui";import{NoticePart}from"./NoticePart.js";import{jsx as _jsx}from"react/jsx-runtime";export function FilePart(e){const{part:t,message:i,turn:r}=e;if("File"!==t.kind){const e={kind:"Notice",code:"NeedsNewerApp",text:r.labels.needsNewerApp};return _jsx(NoticePart,{part:e,message:i,turn:r})}const{openAttachment:o}=r;return _jsx(Chip,{label:`${t.fileName} (${formatFileSize(t.length)})`,leftIcon:"
|
|
1
|
+
"use strict";import{formatFileSize}from"@webority/chat-core";import{Chip}from"@webority/mobile-ui";import{NoticePart}from"./NoticePart.js";import{jsx as _jsx}from"react/jsx-runtime";export function FilePart(e){const{part:t,message:i,turn:r}=e;if("File"!==t.kind){const e={kind:"Notice",code:"NeedsNewerApp",text:r.labels.needsNewerApp};return _jsx(NoticePart,{part:e,message:i,turn:r})}const{openAttachment:o}=r;return _jsx(Chip,{label:`${t.fileName} (${formatFileSize(t.length)})`,leftIcon:"document-text",variant:"soft",size:"sm",accessibilityLabel:r.labels.fileOpen(t.fileName),onPress:o?()=>o(t):void 0})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{Avatar,Card,Spinner,Text,useTheme}from"@webority/mobile-ui";import{View}from"react-native";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";export function HandoffPart({part:e,turn:
|
|
1
|
+
"use strict";import{Avatar,Card,Spinner,Text,useTheme}from"@webority/mobile-ui";import{View}from"react-native";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";export function HandoffPart({part:e,turn:t}){const s=useTheme(),{labels:i}=t;if(!0===t.handoffSettled&&("Requested"===e.state||"Waiting"===e.state))return null;const a=t.isLast&&("Requested"===e.state||"Waiting"===e.state||"Joined"===e.state),n=e.agent?.displayName||i.handoffAgentFallback,r=e.agent?.avatarUrl;let o;switch(e.state){case"Requested":o=_jsxs(View,{style:{flexDirection:"row",alignItems:"center",gap:s.space.sm},children:[_jsx(Spinner,{size:"sm"}),_jsx(Text,{variant:"bodySmall",children:i.handoffRequested})]});break;case"Waiting":o=_jsxs(View,{style:{gap:s.space.xs},children:[_jsxs(View,{style:{flexDirection:"row",alignItems:"center",gap:s.space.sm},children:[_jsx(Spinner,{size:"sm"}),"number"==typeof e.queuePosition?null:_jsx(Text,{variant:"label",children:i.handoffWaiting})]}),"number"==typeof e.queuePosition?_jsx(Text,{variant:"caption",color:"secondary",children:i.handoffQueued(e.queuePosition)}):null,_jsx(Text,{variant:"caption",color:"secondary",children:i.handoffQueuedText})]});break;case"Joined":o=_jsxs(View,{style:{gap:s.space.xs},children:[_jsxs(View,{style:{flexDirection:"row",alignItems:"center",gap:s.space.sm},children:[_jsxs(View,{style:{position:"relative"},children:[_jsx(Avatar,{size:"sm",name:n,source:r?{uri:r}:void 0}),_jsx(View,{accessibilityElementsHidden:!0,importantForAccessibility:"no-hide-descendants",style:{position:"absolute",right:0,bottom:0,width:8,height:8,borderRadius:s.radius.pill,backgroundColor:s.colors["success-text"]}})]}),_jsx(Text,{variant:"label",children:i.handoffJoined(n)})]}),_jsx(Text,{variant:"caption",color:"secondary",children:i.handoffJoinedText(n)})]});break;case"Left":o=_jsxs(View,{style:{gap:s.space.xs},children:[_jsx(Text,{variant:"bodySmall",children:i.handoffLeft(n)}),_jsx(Text,{variant:"caption",color:"secondary",children:i.handoffLeftText})]});break;case"Ended":o=_jsxs(View,{style:{gap:s.space.xs},children:[_jsx(Text,{variant:"bodySmall",children:i.handoffEnded}),_jsx(Text,{variant:"caption",color:"secondary",children:i.handoffEndedText})]})}return void 0===o?null:_jsx(Card,{variant:"outline",padding:"sm",accessibilityLiveRegion:a?"polite":void 0,children:o})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{AuthedImage,Button,Modal,Text,useTheme,ZoomableImage}from"@webority/mobile-ui";import{useState}from"react";import{Pressable,View}from"react-native";import{useSafeAreaInsets}from"react-native-safe-area-context";import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";
|
|
1
|
+
"use strict";import{AuthedImage,Button,Modal,Text,useTheme,ZoomableImage}from"@webority/mobile-ui";import{useMemo,useRef,useState}from"react";import{Pressable,View}from"react-native";import{useSafeAreaInsets}from"react-native-safe-area-context";import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";export function ImagePart({part:e,turn:t}){const a=useTheme(),s=useSafeAreaInsets(),[l,i]=useState(!1),[r,n]=useState(0),c=useRef(t.readAttachment);c.current=t.readAttachment;const o=useMemo(()=>({get:async()=>({data:await c.current(e.attachmentId)})}),[e.attachmentId]),m=`chat-attachment:${e.attachmentId}`,h=`${m}#${r}`,u=null!==e.width&&null!==e.height&&e.width>0&&e.height>0?e.width/e.height:null,d=_jsx(Text,{variant:"bodySmall",color:"secondary",children:e.alt}),b=_jsxs(View,{style:{gap:a.space.xs},children:[d,_jsx(Button,{variant:"soft",size:"sm",label:t.labels.retry,onPress:()=>n(e=>e+1),testID:`image-retry-${e.attachmentId}`})]});return _jsxs(_Fragment,{children:[_jsx(Pressable,{accessibilityRole:"imagebutton",accessibilityLabel:t.labels.imageOpen(e.alt),onPress:()=>i(!0),children:_jsx(AuthedImage,{uri:m,cacheKey:h,client:o,contentFit:"contain",accessible:!0,accessibilityLabel:e.alt,labels:{loading:t.labels.imageLoading},style:{width:"100%",...null===u?{minHeight:160}:{aspectRatio:u},maxHeight:320,borderRadius:a.radius.md},placeholder:d,fallback:b})}),_jsx(Modal,{open:l,onClose:()=>i(!1),backdropPressClose:!1,presentation:"fullScreen",accessibilityLabel:e.alt,children:_jsxs(View,{style:{flex:1,backgroundColor:a.colors.bg},children:[_jsx(ZoomableImage,{style:{flex:1},accessibilityLabel:e.alt,children:_jsx(AuthedImage,{uri:m,cacheKey:h,client:o,contentFit:"contain",style:{flex:1},accessibilityLabel:e.alt})}),_jsx(View,{style:{position:"absolute",top:s.top+a.space.sm,right:a.space.sm},children:_jsx(Button,{variant:"soft",size:"sm",label:t.labels.close,onPress:()=>i(!1)})})]})})]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{Button,Card,Checkbox,Chip,ChoiceGroup,Input,ProgressBar,Text,useTheme}from"@webority/mobile-ui";import{useState}from"react";import{View}from"react-native";import{NoticePart}from"./NoticePart.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const FIELD_TYPES=new Set(["Email","Phone","Name","Company","Text","LongText","Choice","MultiChoice","TimeSlot","File","Consent"]),isUndrawnField=
|
|
1
|
+
"use strict";import{Button,Card,Checkbox,Chip,ChoiceGroup,Input,ProgressBar,Text,useTheme}from"@webority/mobile-ui";import{useCallback,useEffect,useRef,useState}from"react";import{View}from"react-native";import{focusForAccessibility}from"../chatShared.js";import{NoticePart}from"./NoticePart.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const FIELD_TYPES=new Set(["Email","Phone","Name","Company","Text","LongText","Choice","MultiChoice","TimeSlot","File","Consent"]),isUndrawnField=e=>!FIELD_TYPES.has(e.type),fileNameOf=(e,t)=>{const i=e.name;return"string"==typeof i&&""!==i?i:t},slotFormat=new Intl.DateTimeFormat(void 0,{weekday:"short",day:"numeric",month:"short",hour:"numeric",minute:"2-digit"}),selectedIds=e=>""===e?[]:JSON.parse(e),KEYBOARD_TYPES={Email:"email-address",Phone:"phone-pad"},AUTO_COMPLETE={Email:"email",Phone:"tel",Name:"name",Company:"organization"},optionalSuffix=(e,t)=>e.required?"":` (${t.inputOptional})`,firstErrorKey=(e,t)=>e.find(e=>void 0!==t[e.key])?.key;function OpenRequest({part:e,turn:t,pickAttachments:i}){const r=useTheme(),{labels:s,features:a}=t,[n,l]=useState({}),[o,c]=useState({}),[u,d]=useState(""),[p,y]=useState(!1),[f,m]=useState({}),[x,h]=useState({}),[b,k]=useState({}),v=useRef({}),g=useRef({}),j=useRef(f),_=useRef(0),T=useRef(!1),C=useCallback(e=>{const t=v.current[e];if(t)return void t.focus();const i=g.current[e];i&&focusForAccessibility(i)},[]);useEffect(()=>{if(p||!T.current)return;T.current=!1;const t=firstErrorKey(e.fields,o);void 0!==t&&C(t)},[p,o,e.fields,C]);const setValue=(e,t)=>l(i=>({...i,[e]:t})),commitUploads=e=>{j.current=e,m(e)},patchUpload=(e,t)=>{const i=j.current[e];i&&commitUploads({...j.current,[e]:{...i,...t}})},isLiveUpload=(e,t)=>j.current[e]?.token===t,S=Object.values(f).some(e=>"Ready"!==e.status),leave=async e=>{y(!0),d("");try{await e()}catch{d(s.errorGeneric),y(!1)}},w=a.LeadShortcuts,R=w&&1===e.fields.length&&!e.fields[0].required,E=w&&e.cancellable;return _jsx(Card,{variant:"outline",padding:"sm",accessibilityLabel:e.title||void 0,children:_jsxs(View,{style:{gap:r.space.sm},children:[e.title?_jsx(Text,{variant:"label",accessibilityRole:"header",children:e.title}):null,e.allowTyped?_jsx(Text,{variant:"caption",color:"secondary",children:s.typeAnswer}):null,e.fields.map(a=>{const l=n[a.key]??"",c=o[a.key];if("File"===a.type){const e=f[a.key];return _jsxs(View,{style:{gap:r.space.xs},children:[_jsx(Text,{variant:"label",children:`${a.label}${optionalSuffix(a,s)}`}),e?_jsxs(View,{style:{gap:r.space.xxs},children:[_jsx(Chip,{label:e.fileName,variant:"soft",onRemove:()=>{return e=a.key,commitUploads(Object.fromEntries(Object.entries(j.current).filter(([t])=>t!==e))),void setValue(e,"");var e},labels:{remove:s.inputRemoveFile}}),"Uploading"===e.status?_jsx(ProgressBar,{progress:e.progress??void 0,label:s.attachmentUploading,height:4}):null,"Failed"===e.status?_jsx(Text,{variant:"caption",color:"danger",accessibilityLiveRegion:"assertive",children:s.attachmentFailed}):null]}):_jsx(View,{style:{flexDirection:"row"},children:_jsx(Button,{label:s.inputChooseFile,variant:"soft",size:"sm",leftIcon:"paperclip",disabled:p||void 0===i,onPress:()=>{(async e=>{if(!i)return;let r;try{r=await i()}catch{return void d(s.errorGeneric)}const a=r[0];if(!a)return;_.current+=1;const n=_.current;commitUploads({...j.current,[e.key]:{fileName:fileNameOf(a,e.label),status:"Uploading",progress:null,token:n}});try{const i=await t.uploadInputFile(a,t=>{isLiveUpload(e.key,n)&&patchUpload(e.key,{progress:t})});isLiveUpload(e.key,n)&&(setValue(e.key,i),patchUpload(e.key,{status:"Ready",progress:null}))}catch{isLiveUpload(e.key,n)&&(setValue(e.key,""),patchUpload(e.key,{status:"Failed",progress:null}))}})(a)}})}),c?_jsx(Text,{variant:"caption",color:"danger",accessibilityLiveRegion:"assertive",children:c}):null]},a.key)}if("MultiChoice"===a.type){const e=(a.options??[]).map(e=>({label:e.label,value:e.id}));return _jsxs(View,{style:{gap:r.space.xs},children:[_jsx(Text,{variant:"label",children:`${a.label}${optionalSuffix(a,s)}`}),_jsx(View,{ref:e=>{g.current[a.key]=e},children:_jsx(ChoiceGroup,{selectionMode:"multiple",options:e,value:selectedIds(l),onChange:t=>setValue(a.key,JSON.stringify(e.filter(e=>t.includes(e.value)).map(e=>e.value))),accessibilityLabel:a.label,error:c,disabled:p})})]},a.key)}if("Choice"===a.type||"TimeSlot"===a.type){const e="TimeSlot"===a.type?(a.slots??[]).map(e=>({label:slotFormat.format(new Date(e.startDateTimeUtc)),value:e.id})):(a.options??[]).map(e=>({label:e.label,value:e.id}));return _jsxs(View,{style:{gap:r.space.xs},children:[_jsx(Text,{variant:"label",children:`${a.label}${optionalSuffix(a,s)}`}),_jsx(View,{ref:e=>{g.current[a.key]=e},children:_jsx(ChoiceGroup,{options:e,value:""===l?void 0:l,onChange:e=>setValue(a.key,String(e)),accessibilityLabel:a.label,error:c,disabled:p})})]},a.key)}if("Consent"===a.type)return _jsx(Checkbox,{checked:"true"===l,onChange:e=>setValue(a.key,e?"true":"false"),label:a.consentText??a.label,error:c,disabled:p},a.key);const u=_jsx(Input,{ref:e=>{v.current[a.key]=e},label:a.label,placeholder:a.placeholder??void 0,value:l,onChangeText:e=>setValue(a.key,e),maxLength:a.maxLength??void 0,required:a.required,error:c,help:a.required?void 0:s.inputOptional,labelMode:"top",disabled:p,type:a.secret?"password":"LongText"===a.type?"textarea":"input",keyboardType:KEYBOARD_TYPES[a.type]??"default",autoCapitalize:"Email"===a.type?"none":void 0,autoComplete:AUTO_COMPLETE[a.type]},a.key);if(!("Otp"===a.verify&&("Email"===a.type||"Phone"===a.type)))return u;const y=b[a.key];return _jsxs(View,{style:{gap:r.space.xs},children:[u,_jsxs(View,{style:{gap:r.space.xs},children:[_jsx(Button,{label:s.inputSendCode,variant:"soft",size:"sm",disabled:p,onPress:()=>{(async i=>{if("Otp"===i.verify)try{await t.sendOtp(e.requestId,{fieldKey:i.key,value:(n[i.key]??"").trim()}),k(e=>({...e,[i.key]:"sent"}))}catch{k(e=>({...e,[i.key]:"failed"}))}})(a)},testID:`otp-send-${a.key}`}),_jsx(Input,{label:s.inputEnterCode,value:x[a.key]??"",onChangeText:e=>h(t=>({...t,[a.key]:e})),keyboardType:"number-pad",autoComplete:"one-time-code",disabled:p}),y?_jsx(Text,{variant:"caption",color:"failed"===y?"danger":"secondary",accessibilityLiveRegion:"polite",children:"failed"===y?s.inputCodeFailed:s.inputCodeSent}):null]})]},a.key)}),""!==u?_jsx(Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:u}):null,_jsxs(View,{style:{flexDirection:"row",flexWrap:"wrap",gap:r.space.sm},children:[_jsx(Button,{label:p?s.inputSubmitting:e.submitLabel,loading:p,disabled:p||S,onPress:()=>{(async()=>{if(S)return;const i={},r={};for(const t of e.fields){const e=n[t.key]??"";if("Consent"===t.type){const a="true"===e;t.required&&!a&&(i[t.key]=s.inputConsentRequired),r[t.key]=a?"true":"false"}else if("Choice"===t.type||"TimeSlot"===t.type)t.required&&""===e&&(i[t.key]=s.inputRequired),r[t.key]=e;else if("MultiChoice"===t.type){const a=selectedIds(e);t.required&&0===a.length&&(i[t.key]=s.inputRequired),r[t.key]=JSON.stringify(a)}else if("File"===t.type)t.required&&""===e&&(i[t.key]=s.inputRequired),r[t.key]=e;else{const a=t.secret?e:e.trim();t.required&&""===a&&(i[t.key]=s.inputRequired),r[t.key]=a}}const a={};for(const t of e.fields){if("Otp"!==t.verify)continue;const e=(x[t.key]??"").trim();""===e&&(i[t.key]=s.inputRequired),a[t.key]=e}if(c(i),Object.keys(i).length>0){const t=firstErrorKey(e.fields,i);return void(void 0!==t&&C(t))}y(!0),d("");try{const i=await t.answerInput(e.requestId,r,Object.keys(a).length>0?a:null);if(i.ok)return;c(i.errors),T.current=!0,d(i.message??"")}catch{d(s.errorGeneric)}y(!1)})()}}),S?_jsx(Text,{variant:"caption",color:"secondary",children:s.attachmentUploading}):null,R?_jsx(Button,{label:s.skip,variant:"ghost",disabled:p,onPress:()=>{leave(()=>t.skipInput(e.requestId))}}):null,E?_jsx(Button,{label:s.cancel,variant:"ghost",disabled:p,onPress:()=>{leave(()=>t.cancelLead())}}):null]})]})})}export function InputRequestPart(e){const{part:t,message:i,turn:r,pickAttachments:s}=e;if("InputRequest"!==t.kind||t.fields.some(isUndrawnField)){const e={kind:"Notice",code:"NeedsNewerApp",text:r.labels.needsNewerApp};return _jsx(NoticePart,{part:e,message:i,turn:r})}return"Answered"===t.state?_jsx(Text,{variant:"bodySmall",color:"secondary",children:t.answeredSummary||r.labels.inputAnswered}):"Skipped"===t.state?_jsx(Text,{variant:"bodySmall",color:"secondary",children:r.labels.inputSkipped}):"Expired"===t.state?_jsx(Text,{variant:"bodySmall",color:"secondary",children:r.labels.inputExpired}):_jsx(OpenRequest,{part:t,turn:r,pickAttachments:s},t.requestId)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{Banner}from"@webority/mobile-ui";import{jsx as _jsx}from"react/jsx-runtime";export function NoticePart({part:
|
|
1
|
+
"use strict";import{Banner}from"@webority/mobile-ui";import{jsx as _jsx}from"react/jsx-runtime";export function NoticePart({part:e}){const t="AssistantUnavailable"===e.code?"danger":"ActionLimitReached"===e.code||"ConversationTooLong"===e.code?"warning":"info";return _jsx(Banner,{message:e.text,tone:t,accessibilityRole:"alert"})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{isHandoffTarget}from"@webority/chat-core";import{Chip,useTheme}from"@webority/mobile-ui";import{View}from"react-native";import{ChatEntrance}from"../ChatEntrance.js";import{defaultOpenTarget}from"../chatShared.js";import{jsx as _jsx}from"react/jsx-runtime";function lookOf(e){switch(e){case"Primary":
|
|
1
|
+
"use strict";import{CHAT_HANDOFF_REQUEST_ID,isHandoffTarget}from"@webority/chat-core";import{Chip,Text,useTheme}from"@webority/mobile-ui";import{View}from"react-native";import{ChatEntrance}from"../ChatEntrance.js";import{defaultOpenTarget}from"../chatShared.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const QUIET_LOOK={variant:"outline"};function lookOf(e){switch(e){case"Primary":case"Cta":return{variant:"solid",tone:"primary"};default:return QUIET_LOOK}}export function QuickRepliesPart({part:e,turn:n}){const t=useTheme();if(!n.features.SuggestedReplies||!n.isLast||n.busy||0===e.replies.length)return null;const i=n.openTarget,a=n.onNavigate,r=void 0!==i&&i!==defaultOpenTarget,o="Composer"===e.placement,s=e.replies.filter(e=>"Send"===e.action||"Open"===e.action&&e.target&&i||"Navigate"===e.action&&n.features.LinkHandoff);if(0===s.length)return null;const l=o?void 0:s.find(e=>e.id===CHAT_HANDOFF_REQUEST_ID&&"Send"===e.action),c=l?s.filter(e=>e!==l):s,f=l?1:0,sendChip=(e,t)=>_jsx(Chip,{label:e.label,variant:t.variant,tone:t.tone,leftIcon:e.icon?e.icon:void 0,onPress:()=>{n.chooseQuickReply(e),n.focusComposer?.()}});return _jsxs(View,{accessibilityRole:"summary",accessibilityLabel:n.labels.quickReplies,accessibilityLiveRegion:n.handoffPause?"polite":void 0,style:{flexDirection:"row",flexWrap:"wrap",gap:t.space.xs,...o?{paddingHorizontal:t.space.md}:null},children:[l?_jsx(ChatEntrance,{index:0,children:_jsxs(View,{style:{flexBasis:"100%",alignItems:"flex-start",gap:t.space.xs},children:[_jsx(Text,{variant:"label",children:l.label}),sendChip(l,lookOf("Primary"))]})},l.id):null,c.map((e,t)=>{const o=t+f,s=l?QUIET_LOOK:lookOf(e.variant),c=e.icon?e.icon:void 0;if("Send"===e.action)return _jsx(ChatEntrance,{index:o,children:sendChip(e,s)},e.id);const d=e.target;if("Open"===e.action&&d&&i)return _jsx(ChatEntrance,{index:o,children:_jsx(Chip,{label:e.label,variant:s.variant,tone:s.tone,leftIcon:c,onPress:()=>i(d)})},e.id);if("Navigate"===e.action){const t=(e=>{if(!e)return null;if(isHandoffTarget(e,n.handoffHosts))return e;const t=n.resolveLink?.(e);return"string"==typeof t&&""!==t?t:null})(d),l=null===t?void 0:(e=>e.startsWith("/")?i&&r?()=>i(e):a?()=>a(e):void 0:i?()=>i(e):void 0)(t);return _jsx(ChatEntrance,null===t||void 0===l?{index:o,children:_jsx(Text,{variant:"bodySmall",color:"primary",children:e.label})}:{index:o,children:_jsx(Chip,{label:n.handoffPause?n.labels.handoffMoment:e.label,variant:n.handoffPause?QUIET_LOOK.variant:s.variant,tone:n.handoffPause?void 0:s.tone,leftIcon:c,disabled:n.handoffPause,onPress:()=>n.beginHandoff(e,l)})},e.id)}return null})]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{formatChatValue}from"@webority/chat-core";import{Card,useTheme}from"@webority/mobile-ui";import{StyleSheet,View}from"react-native";import{FigureText}from"./FigureText.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const withPositions=e=>e.reduce((e,t)=>(e.push({key:e.length,item:t}),e),[]);export function RecordCardPart({part:e,turn:t}){const r=useTheme(),i=void 0!==t.openRecord&&null!==e.target;return _jsx(Card,{variant:"outline",padding:"sm",accessibilityRole:
|
|
1
|
+
"use strict";import{formatChatValue,toFigureText}from"@webority/chat-core";import{Button,Card,useTheme}from"@webority/mobile-ui";import{StyleSheet,View}from"react-native";import{FigureText}from"./FigureText.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const withPositions=e=>e.reduce((e,t)=>(e.push({key:e.length,item:t}),e),[]),NUMERIC=new Set(["Integer","Decimal","MoneyMinor","Percent"]);export function RecordCardPart({part:e,turn:t}){const r=useTheme(),i=void 0!==t.openRecord&&null!==e.target;return _jsx(Card,{variant:"outline",padding:"sm",accessibilityRole:"summary",children:_jsxs(View,{style:{gap:r.space.xs},children:[_jsx(FigureText,{text:e.title,variant:"label",color:"primary",strong:!0,numberOfLines:2,enabled:t.features.FigureText,heading:!0}),e.subtitle?_jsx(FigureText,{text:e.subtitle,variant:"bodySmall",color:"secondary",enabled:t.features.FigureText}):null,withPositions(e.fields).map(({key:e,item:i})=>_jsxs(View,{style:{gap:r.space.xs},children:[e>0?_jsx(View,{style:{height:StyleSheet.hairlineWidth,backgroundColor:r.colors["border-subtle"]}}):null,_jsxs(View,{style:{flexDirection:"row",justifyContent:"space-between",gap:r.space.sm},children:[_jsx(View,{style:{flexShrink:1},children:_jsx(FigureText,{text:i.label,variant:"caption",color:"secondary",enabled:t.features.FigureText})}),_jsx(View,{style:{flex:1,alignItems:NUMERIC.has(i.type)?"flex-end":"flex-start"},children:_jsx(FigureText,{text:formatChatValue(i.value,i.type,null),variant:"bodySmall",color:"primary",enabled:t.features.FigureText})})]})]},e)),i?_jsx(Button,{label:t.labels.recordOpen,variant:"link",size:"sm",accessibilityLabel:t.labels.recordOpenFor(toFigureText(e.title)),onPress:()=>t.openRecord?.(e),testID:`record-open-${e.recordId}`}):null]})})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{Chip,Text,useTheme}from"@webority/mobile-ui";import{View}from"react-native";import{ChatEntrance}from"../ChatEntrance.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const HTTP_LINK=/^https?:\/\//i;export function SourcesPart({part:e,turn:
|
|
1
|
+
"use strict";import{Chip,Text,useTheme}from"@webority/mobile-ui";import{View}from"react-native";import{ChatEntrance}from"../ChatEntrance.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const HTTP_LINK=/^https?:\/\//i;export function SourcesPart({part:e,turn:r}){const s=useTheme();if(!r.features.Sources||0===e.sources.length)return null;const t=r.openTarget;return _jsxs(View,{style:{gap:s.space.xs},children:[_jsx(Text,{variant:"caption",color:"secondary",children:r.labels.sources}),_jsx(View,{accessibilityRole:"list",accessibilityLabel:r.labels.sources,style:{flexDirection:"row",flexWrap:"wrap",gap:s.space.xs},children:e.sources.map((e,s)=>{const i=e.url,a=null!==i&&HTTP_LINK.test(i)&&void 0!==t?()=>t(i):void 0;return _jsx(ChatEntrance,{index:s,animate:!1,children:_jsx(View,{ref:s=>r.registerSourceRow?.(String(e.marker),s),children:_jsx(Chip,{label:`${e.marker} ${e.title}`,variant:"outline",size:"sm",accessibilityLabel:a?r.labels.openSource(e.title):void 0,onPress:a})})},e.marker)})})]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{formatChatValue,toFigureText}from"@webority/chat-core";import{Button,Card,Text,useTheme}from"@webority/mobile-ui";import{useState}from"react";import{ScrollView,StyleSheet,View}from"react-native";import{FigureText}from"./FigureText.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const PREVIEW_ROWS=
|
|
1
|
+
"use strict";import{formatChatValue,toFigureText}from"@webority/chat-core";import{AppIcon,Button,Card,Text,useTheme}from"@webority/mobile-ui";import{useState}from"react";import{ScrollView,StyleSheet,View}from"react-native";import{FigureText}from"./FigureText.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const PREVIEW_ROWS=25,COLUMN_WIDTH={Text:140,Integer:88,Decimal:96,MoneyMinor:112,Percent:80,Date:112,DateTimeUtc:152},NUMERIC=new Set(["Integer","Decimal","MoneyMinor","Percent"]),withPositions=e=>e.reduce((e,t)=>(e.push({key:e.length,item:t}),e),[]);export function TablePart({part:e,turn:t}){const r=useTheme(),[i,l]=useState(!1),[n,s]=useState(0),[o,a]=useState(0),[c,u]=useState(0);if(0===e.columns.length||0===e.rows.length)return null;const plain=e=>t.features.FigureText?toFigureText(e):e,x=o>c+n+1,m=i?e.rows:e.rows.slice(0,25),h={height:StyleSheet.hairlineWidth,backgroundColor:r.colors["border-subtle"]},d={paddingVertical:r.space.xs,paddingHorizontal:r.space.sm},cellValue=(t,r,i)=>{const l=t[r];return null==l?null:formatChatValue(l,i.type,e.currency)};return _jsxs(View,{accessibilityLabel:e.title?plain(e.title):t.labels.table,style:{gap:r.space.xs},children:[e.title?_jsx(FigureText,{text:e.title,variant:"label",color:"primary",strong:!0,enabled:t.features.FigureText}):null,_jsxs(Card,{variant:"outline",padding:"sm",onLayout:e=>u(e.nativeEvent.layout.width),children:[_jsx(ScrollView,{horizontal:!0,showsHorizontalScrollIndicator:!0,nestedScrollEnabled:!0,onScroll:e=>s(e.nativeEvent.contentOffset.x),onContentSizeChange:e=>a(e),scrollEventThrottle:16,children:_jsxs(View,{children:[_jsx(View,{style:{flexDirection:"row"},children:e.columns.map(e=>_jsx(View,{style:[d,{width:COLUMN_WIDTH[e.type],alignItems:NUMERIC.has(e.type)?"flex-end":"flex-start"}],children:_jsx(FigureText,{text:e.label,variant:"label",color:"secondary",strong:!0,numberOfLines:2,enabled:t.features.FigureText})},e.key))}),_jsx(View,{style:h}),withPositions(m).map(({key:r,item:i})=>{const l=e.columns.map((e,t)=>`${plain(e.label)}: ${cellValue(i,t,e)??"-"}`).join(", ");return _jsxs(View,{accessible:!0,accessibilityLabel:l,children:[_jsx(View,{accessibilityElementsHidden:!0,importantForAccessibility:"no-hide-descendants",style:{flexDirection:"row"},children:e.columns.map((e,r)=>{const l=cellValue(i,r,e);return _jsx(View,{style:[d,{width:COLUMN_WIDTH[e.type],alignItems:NUMERIC.has(e.type)?"flex-end":"flex-start"}],children:null===l?_jsx(Text,{variant:"bodySmall",color:"tertiary",children:"-"}):_jsx(FigureText,{text:l,variant:"bodySmall",color:"primary",numberOfLines:3,enabled:t.features.FigureText})},e.key)})}),_jsx(View,{style:h})]},r)})]})}),x?_jsx(View,{pointerEvents:"none",style:{position:"absolute",right:0,top:0,bottom:0,justifyContent:"center"},children:_jsx(AppIcon,{name:"chevron-right",size:"sm",color:"tertiary"})}):null]}),!i&&e.rows.length>25?_jsx(Button,{variant:"link",size:"sm",label:t.labels.tableShowAll(e.rows.length),onPress:()=>l(!0)}):null]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{Card,Chip,Text,useTheme}from"@webority/mobile-ui";import{View}from"react-native";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";export function TicketPart({part:e,turn:t}){const i=useTheme(),{labels:s,openTicket:r}=t,a=s.ticketAria(e.number),n=r?()=>r({ticketId:e.ticketId,number:e.number}):void 0;return _jsx(Card,{variant:"outline",padding:"sm",
|
|
1
|
+
"use strict";import{Button,Card,Chip,Text,useTheme}from"@webority/mobile-ui";import{View}from"react-native";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";export function TicketPart({part:e,turn:t}){const i=useTheme(),{labels:s,openTicket:r}=t,a=s.ticketAria(e.number),n=s.ticketStatus(e.status),l=r?()=>r({ticketId:e.ticketId,number:e.number}):void 0;return _jsx(Card,{variant:"outline",padding:"sm",accessibilityLabel:n?`${a}, ${n}`:a,children:_jsxs(View,{style:{gap:i.space.xs},children:[_jsxs(View,{style:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:i.space.sm},children:[_jsx(Text,{variant:"label",children:a}),n?_jsx(Chip,{size:"sm",variant:"soft",label:n}):null]}),_jsx(Text,{variant:"bodySmall",children:e.subject}),l?_jsx(Button,{label:s.ticketView,variant:"link",size:"sm",onPress:l,testID:`ticket-view-${e.ticketId}`}):null]})})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{Logger}from"@webority/mobile-core";import{IconButton,
|
|
1
|
+
"use strict";import{voiceClipBars}from"@webority/chat-core";import{Logger}from"@webority/mobile-core";import{Button,IconButton,Text,useTheme}from"@webority/mobile-ui";import{useEffect,useMemo,useRef,useState}from"react";import{StyleSheet,View}from"react-native";import{playFile}from"../speech/expoAudio.js";import{discardFile,PhoneSpeechError}from"../speech/phoneSpeech.js";import{audioExtension,formatClipTime}from"../speech/speechText.js";import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";const expoFileSystem=()=>{try{return require("expo-file-system")}catch{throw new PhoneSpeechError("Unavailable","Unavailable","Voice files are not available in this app.")}};export function VoiceClipPart({part:e,turn:t}){const r=useTheme(),i=useMemo(()=>buildStyles(r),[r]),a=t.labels,[o,s]=useState(!1),[c,l]=useState(!1),[n,u]=useState(!1),[p,m]=useState(0),[h,d]=useState(!1),x=useRef(null),y=useRef(null),f=useRef(!0);useEffect(()=>(f.current=!0,()=>{f.current=!1,x.current?.stop(),x.current=null,null!==y.current&&discardFile(y.current)}),[]);const startPlayback=e=>{const t=playFile(e,e=>{f.current&&(m(e.positionMs),u(e.playing))});x.current=t;const release=()=>!(!f.current||x.current!==t)&&(x.current=null,u(!1),!0);t.finished.then(()=>{release()&&m(0)},e=>{release()&&(l(!0),Logger.error("[chat] voice clip playback failed",e))})},v=t.features.VoiceClips,b=null!==e.transcript&&""!==e.transcript?e.transcript:null,w=e.durationMs>0?Math.min(1,Math.max(0,p/e.durationMs)):0,g=useMemo(()=>voiceClipBars(e.attachmentId,40).map((e,t)=>({id:`bar-${t}`,position:t,level:e})),[e.attachmentId]);return _jsxs(View,{accessibilityRole:"summary",accessibilityLabel:a.voiceClip,testID:"chat-voice-clip",style:i.root,children:[v?_jsxs(View,{style:i.row,children:[_jsx(IconButton,{icon:n?"pause":"play",accessibilityLabel:n?a.voiceClipPause:a.voiceClipPlay,variant:"ghost",tone:"neutral",size:"sm",loading:o,disabled:o,onPress:()=>{const r=x.current;null===r?null===y.current?o||(async()=>{s(!0),l(!1);try{const r=new Uint8Array(await t.readAttachment(e.attachmentId)),{File:i,Paths:a}=expoFileSystem(),o=new i(a.cache,`wchat-clip-${e.attachmentId}${audioExtension(r)}`);if(o.create({overwrite:!0}),o.write(r),!f.current)return void discardFile(o.uri);y.current=o.uri,startPlayback(o.uri)}catch(e){if(!f.current)return;l(!0),Logger.error("[chat] voice clip failed to load",e)}finally{f.current&&s(!1)}})():startPlayback(y.current):n?r.pause():r.resume()},testID:"chat-voice-clip-play"}),_jsx(View,{style:i.wave,children:g.map(e=>_jsx(View,{testID:"chat-voice-clip-bar",style:[i.bar,{height:Math.max(4,Math.round(28*e.level)),backgroundColor:e.position<Math.floor(40*w)?r.colors.primary:r.colors["text-subtle"]}]},e.id))}),_jsx(Text,{variant:"caption",color:"secondary",children:a.voiceClipTime(formatClipTime(p),formatClipTime(e.durationMs))})]}):null,v&&null!==b?_jsxs(_Fragment,{children:[_jsx(Button,{label:h?a.voiceClipHideTranscript:a.voiceClipShowTranscript,variant:"link",size:"sm",accessibilityState:{expanded:h},onPress:()=>d(e=>!e),testID:"chat-voice-clip-transcript-toggle"}),h?_jsx(Text,{variant:"body",children:b}):null]}):null,v||null===b?null:_jsx(Text,{variant:"body",children:b}),c?_jsx(Text,{variant:"caption",color:"danger",accessibilityLiveRegion:"polite",children:a.voiceClipFailed}):null]})}const buildStyles=e=>StyleSheet.create({root:{gap:e.space.xs},row:{flexDirection:"row",alignItems:"center",gap:e.space.xs},wave:{flexDirection:"row",alignItems:"center",gap:e.space.xxs},bar:{width:3}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{ChatSpeechError,createSpeechTokenSource}from"@webority/chat-core";import{Logger}from"@webority/mobile-core";import{Permissions}from"@webority/mobile-core/permissions";import{synthesizeSpeech,transcribeClip}from"./azureSpeech.js";import{playFile,startRecording}from"./expoAudio.js";import{clampSpeakText,DEFAULT_SPEECH_LANGUAGE,DEFAULT_SPEECH_VOICE,MAX_DICTATION_MS,MIN_DICTATION_MS}from"./speechText.js";export class PhoneSpeechError extends ChatSpeechError{constructor(e,t
|
|
1
|
+
"use strict";import{ChatSpeechError,createSpeechTokenSource}from"@webority/chat-core";import{Logger}from"@webority/mobile-core";import{Permissions}from"@webority/mobile-core/permissions";import{synthesizeSpeech,transcribeClip}from"./azureSpeech.js";import{playFile,startRecording}from"./expoAudio.js";import{clampSpeakText,DEFAULT_SPEECH_LANGUAGE,DEFAULT_SPEECH_VOICE,MAX_DICTATION_MS,MIN_DICTATION_MS}from"./speechText.js";export class PhoneSpeechError extends ChatSpeechError{constructor(e,r,t){super(e,t),this.name="PhoneSpeechError",this.phoneCode=r}}const expoFileSystem=()=>{try{return require("expo-file-system")}catch{throw new PhoneSpeechError("Unavailable","Unavailable","Voice files are not available in this app.")}};export function discardFile(e){try{const{File:r}=expoFileSystem();new r(e).delete()}catch(e){Logger.warn("Removing a temporary audio file failed:",e)}}const failed=e=>e instanceof ChatSpeechError?e:(Logger.error("[chat] speech failed",e),new PhoneSpeechError("Failed","Failed")),waitForDictation=e=>new Promise(r=>{if(e?.aborted)return void r();const done=()=>{clearTimeout(t),e?.removeEventListener("abort",done),r()},t=setTimeout(done,MAX_DICTATION_MS);e?.addEventListener("abort",done)});export function createPhoneSpeech(e){const r=e.language??DEFAULT_SPEECH_LANGUAGE,t=e.voice??DEFAULT_SPEECH_VOICE,o=createSpeechTokenSource(e.getToken);let a=null,i=null,n=Promise.resolve();const token=async()=>{try{return await o.get()}catch(e){throw failed(e)}},dictate=async e=>{a?.abort(),i?.abort();const t=n,o=new AbortController,forward=()=>o.abort();e.signal?.aborted&&o.abort(),e.signal?.addEventListener("abort",forward),i=o;const c=t.then(()=>(async(e,t)=>{const o=await Permissions.ensure("microphone").catch(()=>{throw new PhoneSpeechError("Blocked","MicDenied","The microphone permission could not be checked.")});if("blocked"===o)throw new PhoneSpeechError("Blocked","MicBlocked");if("unavailable"===o)throw new PhoneSpeechError("NoMicrophone","MicUnavailable");if("granted"!==o)throw new PhoneSpeechError("Blocked","MicDenied");let a,i;try{a=await startRecording()}catch(e){throw failed(e)}e.onStarted?.(),await waitForDictation(t);try{i=await a.stop()}catch(r){throw e.onEnd?.(),failed(r)}if(e.shouldDiscard?.())return discardFile(i.uri),void e.onEnd?.();if(i.durationMs<MIN_DICTATION_MS)return discardFile(i.uri),void e.onEnd?.();try{const t=await transcribeClip({token:await token(),uri:i.uri,language:e.language??r});""!==t&&e.onText?.(t,!0),e.onEnd?.()}catch(r){throw e.onEnd?.(),failed(r)}finally{discardFile(i.uri)}})(e,o.signal));n=c.then(()=>{},()=>{});try{await c}finally{e.signal?.removeEventListener("abort",forward),i===o&&(i=null)}};return{dictation:!0,readAloud:!0,streamsText:!1,startDictation:e=>dictate(e),speak:(e,o)=>(async(e,o)=>{a?.abort();const i=new AbortController;a=i;const forward=()=>i.abort();o.signal?.aborted&&i.abort(),o.signal?.addEventListener("abort",forward);const n=i.signal;let c=null,s=null;const onAbort=()=>{s?.stop()};try{const a=clampSpeakText(e);if(""===a)return;const i=await synthesizeSpeech({token:await token(),text:a,language:o.language??r,voice:t,signal:n});if(n.aborted)return;const{File:l,Paths:d}=expoFileSystem();if(c=new l(d.cache,`wchat-read-${Date.now()}.mp3`),c.create({overwrite:!0}),c.write(i),n.aborted)return;s=playFile(c.uri),n.addEventListener("abort",onAbort),n.aborted&&s.stop(),await s.finished}catch(e){if(n.aborted)return;throw failed(e)}finally{n.removeEventListener("abort",onAbort),o.signal?.removeEventListener("abort",forward),a===i&&(a=null),null!==c&&discardFile(c.uri)}})(e,o)}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";export const DEFAULT_SPEECH_LANGUAGE="en-IN";export const DEFAULT_SPEECH_VOICE="en-IN-NeerjaNeural";export const MAX_SPEAK_CHARS=
|
|
1
|
+
"use strict";export const DEFAULT_SPEECH_LANGUAGE="en-IN";export const DEFAULT_SPEECH_VOICE="en-IN-NeerjaNeural";export const MAX_SPEAK_CHARS=6e3;export const MAX_DICTATION_MS=3e5;export const MIN_DICTATION_MS=600;const ascii=t=>Array.from(t,t=>t.charCodeAt(0)),OGG=ascii("OggS"),RIFF=ascii("RIFF"),EBML=[26,69,223,163],ID3=ascii("ID3"),MPEG_FRAME_HEADERS=[[255,251],[255,243],[255,242]],startsWith=(t,e,r)=>r.every((r,s)=>t[e+s]===r);export function audioExtension(t){return startsWith(t,0,OGG)?".ogg":startsWith(t,0,RIFF)?".wav":startsWith(t,0,EBML)?".webm":startsWith(t,0,ID3)||MPEG_FRAME_HEADERS.some(e=>startsWith(t,0,e))?".mp3":".m4a"}export function escapeSsml(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}export function buildSsml(t,e,r){return`<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="${escapeSsml(e)}"><voice name="${escapeSsml(r)}">${escapeSsml(t)}</voice></speak>`}export function clampSpeakText(t){const e=t.trim();if(e.length<=6e3)return e;const r=e.slice(0,6e3),s=r.lastIndexOf(". ");return-1===s?r.trim():r.slice(0,s+1)}export function formatClipTime(t){if(!Number.isFinite(t)||t<0)return"0:00";const e=Math.round(t/1e3);return`${Math.floor(e/60)}:${String(e%60).padStart(2,"0")}`}export function joinDictation(t,e,r){const s=e.trim();if(""===s)return t;return`${t}${t.length>0&&!/\s$/.test(t)?" ":""}${s}`.slice(0,r)}
|
package/lib/module/useChat.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{createChatSession,emptyFeatures}from"@webority/chat-core";import{useCallback,useEffect,useMemo,useRef,useState,useSyncExternalStore}from"react";import{AppState}from"react-native";const requestFrame=e=>{const t=requestAnimationFrame(e);return()=>cancelAnimationFrame(t)},NO_SUBSCRIPTION=()=>()=>{},IDLE_STATE=Object.freeze({profile:null,profileError:null,features:Object.freeze(emptyFeatures()),conversationId:null,conversationState:"Open",title:null,continuesConversationId:null,messages:[],thinking:!1,steps:[],streaming:!1,loading:!1,loadError:null,turnError:null,stopped:!1,messagesLeftToday:null,editing:null,attachments:[],lastConversation:null,open:!1,muted:!1,greeting:null,starters:[],pending:null,agent:null,agentTyping:null,live:"Off",handoffPending:!1,handoffPause:!1,openTickets:[],draft:null}),IDLE_SESSION=new Proxy({},{get:(e,t)=>{if("symbol"!=typeof t&&"client"!==t&&"toJSON"!==t&&!t.startsWith("$$")){if("getState"===t)return()=>IDLE_STATE;if("subscribe"===t)return NO_SUBSCRIPTION;if("then"!==t)return()=>Promise.resolve()}}});export function useChat(e){const{client:t,screen:
|
|
1
|
+
"use strict";import{createChatSession,DEFAULT_CHAT_LABELS,emptyFeatures}from"@webority/chat-core";import{useReducedMotion}from"@webority/mobile-ui";import{useCallback,useEffect,useMemo,useRef,useState,useSyncExternalStore}from"react";import{AppState}from"react-native";const requestFrame=e=>{const t=requestAnimationFrame(e);return()=>cancelAnimationFrame(t)},NO_SUBSCRIPTION=()=>()=>{},IDLE_STATE=Object.freeze({profile:null,profileError:null,features:Object.freeze(emptyFeatures()),conversationId:null,conversationState:"Open",title:null,continuesConversationId:null,messages:[],thinking:!1,steps:[],streaming:!1,loading:!1,loadError:null,turnError:null,stopped:!1,messagesLeftToday:null,editing:null,attachments:[],lastConversation:null,open:!1,muted:!1,greeting:null,starters:[],pending:null,agent:null,agentTyping:null,live:"Off",handoffPending:!1,handoffPause:!1,openTickets:[],draft:null}),IDLE_SESSION=new Proxy({},{get:(e,t)=>{if("symbol"!=typeof t&&"client"!==t&&"toJSON"!==t&&!t.startsWith("$$")){if("getState"===t)return()=>IDLE_STATE;if("subscribe"===t)return NO_SUBSCRIPTION;if("then"!==t)return()=>Promise.resolve()}}});export function useChat(e){const{client:t,screen:r,layout:n,narrow:s,conversationId:o,pageContext:a,behaviour:c,prefs:u,getCaptchaToken:i,onEvent:l,onError:f,onNavigate:p}=e,m=JSON.stringify(s??{}),d=useRef(p);d.current=p;const S=useCallback(e=>d.current?.(e),[]),E=useRef(o);E.current=o;const v=useRef(a);v.current=a;const g=useRef(c);g.current=c;const h=useRef(i);h.current=i;const y=useRef(l);y.current=l;const C=useRef(f);C.current=f;const b=useRef(u);b.current=u;const A=useReducedMotion(),R=useRef(A);R.current=A;const[I,L]=useState(null),[T,w]=useState(null);useEffect(()=>{const e=createChatSession(t,{screen:r,layout:n,pathname:()=>r||"/",narrow:JSON.parse(m),conversationId:E.current??void 0,pageContext:()=>v.current,behaviour:()=>g.current?.()??null,prefs:b.current,getCaptchaToken:e=>h.current?.(e)??Promise.reject(new Error("No captcha handler.")),onEvent:(e,t)=>y.current?.(e,t),onError:e=>C.current?.(e),schedule:requestFrame,reducedMotion:()=>R.current});return L({client:t,screen:r,layout:n,narrowKey:m,session:e}),()=>e.dispose()},[t,r,n,m]);const O=null!==I&&I.client===t&&I.screen===r&&I.layout===n&&I.narrowKey===m?I.session:IDLE_SESSION,N=useSyncExternalStore(O.subscribe,O.getState),k=useMemo(()=>({load:()=>O.load(),submit:e=>O.submit(e),chooseQuickReply:e=>O.chooseQuickReply(e),answerInput:(e,t)=>O.answerInput(e,t),confirmAction:e=>O.confirmAction(e),rejectAction:(e,t)=>O.rejectAction(e,t),stop:()=>O.stop(),retry:()=>O.retry(),regenerate:()=>O.regenerate(),startEdit:e=>O.startEdit(e),cancelEdit:()=>O.cancelEdit(),attach:e=>O.attach(e),removeAttachment:e=>O.removeAttachment(e),openConversation:e=>O.openConversation(e),resumeLast:()=>O.resumeLast(),newConversation:()=>O.newConversation(),rate:(e,t,r)=>O.rate(e,t,r),reset:()=>O.reset(),requestHandoff:async e=>{w(null);try{await O.requestHandoff(e)}catch(e){const t=e instanceof Error&&""!==e.message?e.message:DEFAULT_CHAT_LABELS.errorGeneric;throw w(t),e}},notifyTyping:()=>O.notifyTyping(),resumeLive:()=>O.resumeLive()}),[O]),_=useRef(o);useEffect(()=>{O!==IDLE_SESSION&&o&&o!==_.current&&(_.current=o,O.openConversation(o))},[o,O]);const F=useRef("active"===AppState.currentState),P=useRef(!0),D=useCallback(()=>O.setLiveActive(F.current&&P.current),[O]),x=useCallback(e=>{P.current=e,D()},[D]);useEffect(()=>{D();const e=AppState.addEventListener("change",e=>{"active"===e?(F.current=!0,O.endHandoffPause()):F.current=!1,D()});return()=>e.remove()},[D,O]);const j=useCallback((e,t)=>{y.current?.(e,t)},[]);return{...N,...k,session:O,client:t,emit:j,setChatVisible:x,handoffError:T,onNavigate:p?S:void 0}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{useEffect,useRef}from"react";import{
|
|
1
|
+
"use strict";import{useEffect,useRef}from"react";import{Vibration}from"react-native";const isReply=e=>"Assistant"===e.author.kind||"Script"===e.author.kind||"Agent"===e.author.kind;export function useChatHaptics(e){const t=useRef(null),s=e.features.Sounds&&!0===e.profile?.experience.sound.vibrate&&!e.muted,i=e.profile?.experience.sound.vibrateMs??0;useEffect(()=>{if(null!==t.current)for(const r of e.messages){if(!isReply(r)||r.streaming||t.current.has(r.id))continue;if(t.current.add(r.id),r.restored)continue;const e=r.parts.some(e=>"Notice"===e.kind);s&&!e&&Vibration.vibrate(i)}else t.current=new Set(e.messages.map(e=>e.id))},[e.messages,s,i])}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";import{Logger}from"@webority/mobile-core";import{useEffect,useRef}from"react";export const CUES={open:{from:420,to:920,seconds:.16,peak:.16},reply:{from:680,to:540,seconds:.11,peak:.06},sent:{from:540,to:760,seconds:.09,peak:.05}};const SAMPLE_RATE=22050,ATTACK_SECONDS=.01,written=new Map;function cueBytes(e){const t=Math.round(22050*e.seconds),n=2*t,s=new Uint8Array(44+n),o=new DataView(s.buffer),text=(e,t)=>{for(let n=0;n<t.length;n+=1)o.setUint8(e+n,t.charCodeAt(n))};text(0,"RIFF"),o.setUint32(4,36+n,!0),text(8,"WAVE"),text(12,"fmt "),o.setUint32(16,16,!0),o.setUint16(20,1,!0),o.setUint16(22,1,!0),o.setUint32(24,22050,!0),o.setUint32(28,44100,!0),o.setUint16(32,2,!0),o.setUint16(34,16,!0),text(36,"data"),o.setUint32(40,n,!0);const r=Math.min(.01,e.seconds/2);let i=0;for(let n=0;n<t;n+=1){const t=n/22050,s=e.from+(e.to-e.from)*t/e.seconds;i+=2*Math.PI*s/22050;const a=t<r?t/r:(e.seconds-t)/(e.seconds-r);o.setInt16(44+2*n,Math.round(32767*e.peak*a*Math.sin(i)),!0)}return s}export function playCue(e,t=1){(async()=>{let n=written.get(e);if(void 0===n){const{File:t,Paths:s}=require("expo-file-system"),o=new t(s.cache,`wchat-cue-${e}.wav`);o.create({overwrite:!0}),o.write(cueBytes(CUES[e])),n=o.uri,written.set(e,n)}const{createAudioPlayer:s}=require("expo-audio"),o=s({uri:n});o.volume=t,o.addListener("playbackStatusUpdate",e=>{e.didJustFinish&&o.remove()}),o.play()})().catch(e=>{Logger.warn("[chat] sound cue failed",e)})}function takeUnseen(e,t,n){if(t){e.wasLoading=!0;for(const t of n)e.seen.add(t.id);return[]}if(e.wasLoading||!e.seeded){e.wasLoading=!1,e.seeded=!0;for(const t of n)e.seen.add(t.id);return[]}const s=[];for(const t of n)e.seen.has(t.id)||(e.seen.add(t.id),s.push(t));return s}export function useChatSound(e){const t=e.features.Sounds?e.profile?.experience.sound??null:null,n=useRef(e);n.current=e;const s=useRef(e.open),o=useRef({seen:new Set,seeded:!1,wasLoading:!1}),{open:r,loading:i,messages:a}=e;useEffect(()=>{const e=s.current;s.current=r;const c=takeUnseen(o.current,i,a);if(null!==t&&!n.current.muted&&t.volume>0){r&&!e&&t.open&&playCue("open",t.volume);for(const e of c){if(e.restored||e.parts.some(e=>"Notice"===e.kind))continue;const n=e.author.kind;"Visitor"===n?!e.stored&&t.sent&&playCue("sent",t.volume):"Assistant"!==n&&"Script"!==n&&"Agent"!==n||!t.reply||playCue("reply",t.volume)}}},[r,i,a,t])}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type React from "react";
|
|
2
|
+
import type { ChatAppearance } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Draws the accent colour, corner radius and font of the chat's appearance over its subtree, through a
|
|
5
|
+
* nested theme. With no appearance key set it draws its children as they are.
|
|
6
|
+
*/
|
|
7
|
+
export declare function ChatAppearanceScope({ appearance, children, }: {
|
|
8
|
+
appearance?: ChatAppearance;
|
|
9
|
+
children: React.ReactNode;
|
|
10
|
+
}): React.ReactElement;
|
|
11
|
+
//# sourceMappingURL=ChatAppearanceScope.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ChatLabels, type ChatLook, type ChatUploadFile } from "@webority/chat-core";
|
|
2
2
|
import type React from "react";
|
|
3
3
|
import type { UseChatResult } from "./useChat";
|
|
4
4
|
export interface ChatComposerProps {
|
|
@@ -9,6 +9,9 @@ export interface ChatComposerProps {
|
|
|
9
9
|
keyboardAware?: boolean;
|
|
10
10
|
safeArea?: boolean;
|
|
11
11
|
testID?: string;
|
|
12
|
+
focusRef?: React.MutableRefObject<(() => void) | null>;
|
|
13
|
+
/** The resolved look: its input ring and send reveal draw the box and the send button. */
|
|
14
|
+
look?: ChatLook;
|
|
12
15
|
}
|
|
13
|
-
export declare function ChatComposer({ chat, labels, pickAttachments, keyboardOffset, keyboardAware, safeArea, testID, }: ChatComposerProps): React.ReactElement;
|
|
16
|
+
export declare function ChatComposer({ chat, labels, pickAttachments, keyboardOffset, keyboardAware, safeArea, testID, focusRef, look, }: ChatComposerProps): React.ReactElement;
|
|
14
17
|
//# sourceMappingURL=ChatComposer.d.ts.map
|
|
@@ -4,6 +4,7 @@ import type { UseChatResult } from "./useChat";
|
|
|
4
4
|
export interface DictationNotice {
|
|
5
5
|
message: string;
|
|
6
6
|
openSettings: boolean;
|
|
7
|
+
tone: "danger" | "info";
|
|
7
8
|
}
|
|
8
9
|
export interface ChatDictationButtonProps {
|
|
9
10
|
chat: UseChatResult;
|
|
@@ -12,6 +13,7 @@ export interface ChatDictationButtonProps {
|
|
|
12
13
|
onText: (text: string) => void;
|
|
13
14
|
onNotice: (notice: DictationNotice | null) => void;
|
|
14
15
|
testID?: string;
|
|
16
|
+
stopRef?: React.MutableRefObject<(() => void) | null>;
|
|
15
17
|
}
|
|
16
|
-
export declare function ChatDictationButton({ chat, labels, disabled, onText, onNotice, testID, }: ChatDictationButtonProps): React.ReactElement | null;
|
|
18
|
+
export declare function ChatDictationButton({ chat, labels, disabled, onText, onNotice, testID, stopRef, }: ChatDictationButtonProps): React.ReactElement | null;
|
|
17
19
|
//# sourceMappingURL=ChatDictationButton.d.ts.map
|
|
@@ -7,5 +7,5 @@ export interface ChatEmbedProps extends ChatShellProps {
|
|
|
7
7
|
height?: number;
|
|
8
8
|
}
|
|
9
9
|
/** The chat drawn inside a bounded area of a screen, with a border and rounded corners. */
|
|
10
|
-
export declare function ChatEmbed({ chat, labels, renderers, layoutParts, loader,
|
|
10
|
+
export declare function ChatEmbed({ chat, labels, renderers, layoutParts, loader, look, appearance, pickAttachments, onOpenAttachment, onOpenTarget, onNavigate, openTicket, handoffHosts, resolveLink, keyboardOffset, title, headerActions, onClose, height, testID, }: ChatEmbedProps): React.ReactElement | null;
|
|
11
11
|
//# sourceMappingURL=ChatEmbed.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ChatLabels, type ChatLoaderStyle, type ChatLookInput, type ChatPart, type ChatUploadFile } from "@webority/chat-core";
|
|
2
2
|
import type React from "react";
|
|
3
|
-
import type { ChatLayoutParts, ChatOpenTicketHandler, ChatRenderers } from "./types";
|
|
3
|
+
import type { ChatAppearance, ChatLayoutParts, ChatOpenTicketHandler, ChatRenderers } from "./types";
|
|
4
4
|
import type { UseChatResult } from "./useChat";
|
|
5
5
|
export type ChatLayout = "screen" | "sheet" | "embedded";
|
|
6
6
|
/** The props every shell passes down to its frame. */
|
|
@@ -10,7 +10,8 @@ export interface ChatCommonProps {
|
|
|
10
10
|
renderers?: ChatRenderers;
|
|
11
11
|
layoutParts?: ChatLayoutParts;
|
|
12
12
|
loader?: ChatLoaderStyle;
|
|
13
|
-
motion
|
|
13
|
+
/** The look: its input ring and send reveal, its panel motion and its motion switch. Unset values take the defaults. */
|
|
14
|
+
look?: ChatLookInput;
|
|
14
15
|
pickAttachments?: () => Promise<ChatUploadFile[]>;
|
|
15
16
|
onOpenAttachment?: (part: Extract<ChatPart, {
|
|
16
17
|
kind: "File";
|
|
@@ -21,6 +22,8 @@ export interface ChatCommonProps {
|
|
|
21
22
|
openTicket?: ChatOpenTicketHandler;
|
|
22
23
|
/** Hosts an absolute https link or Navigate chip may open; any other absolute target is not linked. */
|
|
23
24
|
handoffHosts?: readonly string[];
|
|
25
|
+
/** Resolves a link in a reply to a host route or address; null leaves the link as text. */
|
|
26
|
+
resolveLink?: (href: string) => string | null;
|
|
24
27
|
keyboardOffset?: number;
|
|
25
28
|
testID?: string;
|
|
26
29
|
}
|
|
@@ -28,12 +31,20 @@ export interface ChatFrameProps extends ChatCommonProps {
|
|
|
28
31
|
layout: ChatLayout;
|
|
29
32
|
title?: string;
|
|
30
33
|
headerActions?: React.ReactNode;
|
|
34
|
+
/** The host sheet closes through this callback. */
|
|
35
|
+
onClose?: () => void;
|
|
36
|
+
/** Changes each time the panel opens, so the panel motion plays again. Default 0. */
|
|
37
|
+
enterKey?: number;
|
|
31
38
|
}
|
|
32
39
|
/** The props of the three shells: the frame's, with labels as a partial merged over the defaults. */
|
|
33
40
|
export interface ChatShellProps extends Omit<ChatCommonProps, "labels"> {
|
|
34
41
|
labels?: Partial<ChatLabels>;
|
|
35
42
|
title?: string;
|
|
36
43
|
headerActions?: React.ReactNode;
|
|
44
|
+
/** The host sheet closes through this callback. */
|
|
45
|
+
onClose?: () => void;
|
|
46
|
+
/** The web's appearance keys the phone reads: accent, corner radius and font, and the launcher side and offsets for a sheet. */
|
|
47
|
+
appearance?: ChatAppearance;
|
|
37
48
|
}
|
|
38
|
-
export declare function ChatFrame({ chat, labels, renderers, layoutParts, loader,
|
|
49
|
+
export declare function ChatFrame({ chat, labels, renderers, layoutParts, loader, look, pickAttachments, onOpenAttachment, onOpenTarget, onNavigate, openTicket, handoffHosts, resolveLink, keyboardOffset, layout, title, headerActions, onClose, enterKey, testID, }: ChatFrameProps): React.ReactElement | null;
|
|
39
50
|
//# sourceMappingURL=ChatFrame.d.ts.map
|