@webority/mobile-chat 0.122.0 → 0.125.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.
Files changed (66) hide show
  1. package/README.md +39 -7
  2. package/lib/commonjs/components/ActionCard.js +1 -1
  3. package/lib/commonjs/components/ChatComposer.js +1 -1
  4. package/lib/commonjs/components/ChatConversationList.js +1 -1
  5. package/lib/commonjs/components/ChatLauncher.js +1 -1
  6. package/lib/commonjs/components/ChatMarkdown.js +1 -1
  7. package/lib/commonjs/components/ChatMessage.js +1 -1
  8. package/lib/commonjs/components/ChatScreen.js +1 -1
  9. package/lib/commonjs/components/ChatThread.js +1 -1
  10. package/lib/commonjs/components/ComposerAttachments.js +1 -0
  11. package/lib/commonjs/components/ReplyRating.js +1 -1
  12. package/lib/commonjs/index.js +1 -1
  13. package/lib/commonjs/useChat.js +1 -1
  14. package/lib/module/components/ActionCard.js +1 -1
  15. package/lib/module/components/ChatComposer.js +1 -1
  16. package/lib/module/components/ChatConversationList.js +1 -1
  17. package/lib/module/components/ChatLauncher.js +1 -1
  18. package/lib/module/components/ChatMarkdown.js +1 -1
  19. package/lib/module/components/ChatMessage.js +1 -1
  20. package/lib/module/components/ChatScreen.js +1 -1
  21. package/lib/module/components/ChatThread.js +1 -1
  22. package/lib/module/components/ComposerAttachments.js +1 -0
  23. package/lib/module/components/ReplyRating.js +1 -1
  24. package/lib/module/index.js +1 -1
  25. package/lib/module/useChat.js +1 -1
  26. package/lib/typescript/commonjs/components/ActionCard.d.ts +2 -2
  27. package/lib/typescript/commonjs/components/ChatComposer.d.ts +12 -1
  28. package/lib/typescript/commonjs/components/ChatConversationList.d.ts +3 -4
  29. package/lib/typescript/commonjs/components/ChatLauncher.d.ts +1 -1
  30. package/lib/typescript/commonjs/components/ChatMarkdown.d.ts +8 -1
  31. package/lib/typescript/commonjs/components/ChatMessage.d.ts +23 -6
  32. package/lib/typescript/commonjs/components/ChatScreen.d.ts +7 -2
  33. package/lib/typescript/commonjs/components/ChatThread.d.ts +9 -1
  34. package/lib/typescript/commonjs/components/ComposerAttachments.d.ts +12 -0
  35. package/lib/typescript/commonjs/components/ReplyRating.d.ts +2 -2
  36. package/lib/typescript/commonjs/index.d.ts +2 -7
  37. package/lib/typescript/commonjs/useChat.d.ts +9 -53
  38. package/lib/typescript/module/components/ActionCard.d.ts +2 -2
  39. package/lib/typescript/module/components/ChatComposer.d.ts +12 -1
  40. package/lib/typescript/module/components/ChatConversationList.d.ts +3 -4
  41. package/lib/typescript/module/components/ChatLauncher.d.ts +1 -1
  42. package/lib/typescript/module/components/ChatMarkdown.d.ts +8 -1
  43. package/lib/typescript/module/components/ChatMessage.d.ts +23 -6
  44. package/lib/typescript/module/components/ChatScreen.d.ts +7 -2
  45. package/lib/typescript/module/components/ChatThread.d.ts +9 -1
  46. package/lib/typescript/module/components/ComposerAttachments.d.ts +12 -0
  47. package/lib/typescript/module/components/ReplyRating.d.ts +2 -2
  48. package/lib/typescript/module/index.d.ts +2 -7
  49. package/lib/typescript/module/useChat.d.ts +9 -53
  50. package/package.json +7 -6
  51. package/lib/commonjs/client.js +0 -1
  52. package/lib/commonjs/labels.js +0 -1
  53. package/lib/commonjs/sse.js +0 -1
  54. package/lib/commonjs/types.js +0 -1
  55. package/lib/module/client.js +0 -1
  56. package/lib/module/labels.js +0 -1
  57. package/lib/module/sse.js +0 -1
  58. package/lib/module/types.js +0 -1
  59. package/lib/typescript/commonjs/client.d.ts +0 -73
  60. package/lib/typescript/commonjs/labels.d.ts +0 -63
  61. package/lib/typescript/commonjs/sse.d.ts +0 -23
  62. package/lib/typescript/commonjs/types.d.ts +0 -71
  63. package/lib/typescript/module/client.d.ts +0 -73
  64. package/lib/typescript/module/labels.d.ts +0 -63
  65. package/lib/typescript/module/sse.d.ts +0 -23
  66. package/lib/typescript/module/types.d.ts +0 -71
package/README.md CHANGED
@@ -18,8 +18,9 @@ npm install @webority/mobile-chat
18
18
  | `@webority/mobile-core`, `@webority/mobile-ui` | the HTTP client the app passes in, dates, theme and components |
19
19
  | `react-native-keyboard-controller` | the question box rises with the keyboard (mobile-ui needs it too) |
20
20
  | `react-native-safe-area-context` | the question box and the launcher clear the home indicator (mobile-ui needs it too) |
21
+ | `expo-clipboard` | the copy action on a reply; the package reaches it through `@webority/mobile-core/clipboard` |
21
22
 
22
- All are required, and an app on mobile-ui already has them.
23
+ All are required. An app on mobile-ui already has the first three; `expo-clipboard` is the one an app adds.
23
24
 
24
25
  ## Wire it up
25
26
 
@@ -48,7 +49,7 @@ export const AssistantProvider = ({ children }) => {
48
49
  return <AssistantContext.Provider value={chat}>{children}</AssistantContext.Provider>;
49
50
  };
50
51
 
51
- // A stack screen.
52
+ // A stack screen. pickFiles opens the app's own picker and resolves to { uri, name, type } files.
52
53
  export const AssistantScreen = ({ navigation }) => (
53
54
  <ChatScreen
54
55
  chat={useAssistant()}
@@ -58,6 +59,8 @@ export const AssistantScreen = ({ navigation }) => (
58
59
  onLinkPress={(target) => navigation.navigate(target.screen, target.params)}
59
60
  confirmAction={supportClient.confirmAction}
60
61
  onViewTicket={(ticket) => navigation.navigate('SupportTicket', { id: ticket.id })}
62
+ pickAttachments={pickFiles}
63
+ onOpenAttachment={(attachment) => openAttachment(attachment)}
61
64
  />
62
65
  );
63
66
  ```
@@ -85,14 +88,22 @@ response arrived, `aborted` when the request was cancelled, or `invalid-response
85
88
 
86
89
  | Method | Request |
87
90
  |---|---|
88
- | `sendMessage({ message, conversationId, pageContext }, { signal, onEvent })` | `POST {base}/chat`, streamed; resolves with the `done` event |
91
+ | `sendMessage({ message, conversationId, pageContext, replacesMessageId, attachmentIds }, { signal, onEvent })` | `POST {base}/chat`, streamed; resolves with the `done` event, which carries `questionId` |
92
+ | `getSettings()` | `GET {base}/settings`: the attachment limits, `{ attachments: null }` when the server takes none |
93
+ | `uploadAttachment(file, { signal, onProgress })` | `POST {base}/attachments`, multipart |
94
+ | `deleteAttachment(id)` | `DELETE {base}/attachments/{id}` |
95
+ | `getAttachment(id)` | `GET {base}/attachments/{id}`, resolves with the bytes |
89
96
  | `getAllowance()` | `GET {base}/allowance` |
90
- | `listConversations({ skip, take })` | `GET {base}/conversations?skip=&take=` |
97
+ | `listConversations({ page, pageSize })` | `GET {base}/conversations?page=&pageSize=`, one page of `{ items, page, pageSize, totalCount, totalPages }` |
91
98
  | `getConversation(id)` | `GET {base}/conversations/{id}` |
99
+ | `renameConversation(id, title)` | `PUT {base}/conversations/{id}/title`, the new title in the body |
92
100
  | `deleteConversation(id)` | `DELETE {base}/conversations/{id}` |
93
101
  | `rateMessage(conversationId, messageId, { rating, note })` | `PUT {base}/conversations/{conversationId}/messages/{messageId}/rating` |
94
102
 
95
- `onEvent(name, data)` is called with `delta { text }`, `reset {}` and `actions { actions }` as they
103
+ The server must answer `GET {base}/settings`. An older server that does not answers 404, and each
104
+ question then fails with `assistant_outdated` ("The assistant needs an update before it can answer. Please try again later.").
105
+
106
+ `onEvent(name, data)` is called with `delta { text }`, `reset {}`, `tool {}` and `actions { actions }` as they
96
107
  arrive. `createSseParser(onEvent)` is exported too, for reading the same stream elsewhere. The
97
108
  server contract (refusal codes, the event stream, the read endpoints) is the one
98
109
  `@webority/chat-react` documents.
@@ -101,7 +112,9 @@ server contract (refusal codes, the event stream, the read endpoints) is the one
101
112
 
102
113
  `useChat({ client, pageContext })` returns `turns` (`[{ id, question, answer, streaming, error,
103
114
  actions, messageId, rating, ratingNote }]`, oldest first), `conversationId`, `messagesLeftToday`,
104
- `streaming`, `loading`, `loadError`, and `submit(message)`, `openConversation(id)`,
115
+ `streaming`, `loading`, `loadError`, `settings`, `settingsError`, `editing`, `attachments`, and
116
+ `submit(message)`, `stop()`, `retry(turnId)`, `regenerate(turnId)`, `startEdit(turnId)`,
117
+ `cancelEdit()`, `attach(files)`, `removeAttachment(key)`, `openConversation(id)`,
105
118
  `newConversation()`, `rate(turnId, rating, note?)`, `refreshAllowance()` and `reset()`.
106
119
  `pageContext` is read at the moment each question is sent.
107
120
 
@@ -120,10 +133,20 @@ package's, so a product passes one label set to both; `composerHint` is not show
120
133
  `title` (default "Assistant"), `headerActions` (before New chat, e.g. "All chats"), `empty`
121
134
  (shown before the first question), `disclaimer` (null hides it), `maxLength` (default 4000),
122
135
  `allowanceThreshold` (show the questions left at this many or fewer, default 10), `rating`
123
- (default true), `resolveLink`, `onLinkPress`, `confirmAction`, `onViewTicket`, `renderReply`,
136
+ (default true), `resolveLink`, `onLinkPress`, `confirmAction`, `onViewTicket`, `pickAttachments`,
137
+ `onOpenAttachment`, `onAskSuggestion(text)` (sends a suggested follow-up question under the last
138
+ settled answer), `isCitation(inner)` and `onOpenCitation(citation)` (a run of the reply that
139
+ `isCitation` accepts draws as an inline pressable text run, not a chip, and pressing it calls
140
+ `onOpenCitation`), `renderReply`,
124
141
  `keyboardOffset`.
125
142
  New chat is disabled until there is something to clear; the question box is disabled with no
126
143
  questions left, and the thread follows the newest text while an answer streams.
144
+ The five controls: Stop ends an answer while it streams and marks its turn stopped;
145
+ Try again sends a stopped or failed question again; New answer asks for another reply to the last
146
+ answered turn; Edit puts a question back in the box to change and resend; Attach a file adds files
147
+ to the next question. Attach a file shows only when `pickAttachments` is given and the server's
148
+ settings allow attachments; `pickAttachments` resolves to the files the person picked, and
149
+ `onOpenAttachment(attachment)` opens one shown in a message.
127
150
  - **`ChatThread`**, **`ChatMessage`**, **`ChatComposer`**: its parts, built on mobile-ui's
128
151
  `MessageList`, `MessageBubble`, `TypingIndicator` and `Composer`, for an app that lays out its
129
152
  own chat. The thread and the composer handle the keyboard themselves; pass
@@ -148,6 +171,15 @@ package's, so a product passes one label set to both; `composerHint` is not show
148
171
  `bottomOffset` to clear a tab bar, `compact`). Most apps open the chat from a header action or a
149
172
  Help row instead.
150
173
 
174
+ The labels the new parts read, all keys of `DEFAULT_CHAT_LABELS`: `copy` and `copied` (the reply's
175
+ Copy action and its confirmation); `toolStep(toolName)` (the waiting line while the assistant runs a
176
+ tool; it receives the server's tool name and defaults to "Looking this up", so the app maps each
177
+ tool to the person's words); `suggestions` (the heading over suggested questions); `renameConversation`, `conversationTitle`,
178
+ `renameSave` and `renameFailed` (the rename dialog in `ChatConversationList`).
179
+
180
+ `ChatConversationList` pages by `page` and `pageSize` (default 20) and renames a chat in place
181
+ through `renameConversation`.
182
+
151
183
  `renderReply(turn, { streaming })` on `ChatScreen`, `ChatThread` or `ChatMessage` draws each
152
184
  assistant reply your way (charts, maths); the question, thinking state, errors, action cards and
153
185
  rating stay the library's.
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ActionCard=void 0;var _mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_labels=require("../labels.js"),_jsxRuntime=require("react/jsx-runtime");const titleOf=(e,i)=>"Reply"===e.kind?i.actionReply(e.ticketNumber??""):"Reopen"===e.kind?i.actionReopen(e.ticketNumber??""):i.actionRaiseTicket,doneText=(e,i,t)=>"Reply"===e.kind?t.actionDoneReply(i):"Reopen"===e.kind?t.actionDoneReopen(i):t.actionDoneRaiseTicket(i),ActionCard=({action:e,confirmAction:i,onViewTicket:t,labels:n,testID:s="chat-action"})=>{const a=(0,_labels.mergeLabels)(n),o=(0,_mobileUi.useTheme)(),[r,l]=(0,_react.useState)("ready"),[c,d]=(0,_react.useState)(null),[m,x]=(0,_react.useState)("");if("dismissed"===r)return(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"secondary",testID:s,children:a.actionDismissed});if("done"===r&&c)return(0,_jsxRuntime.jsx)(_mobileUi.Banner,{tone:"success",message:doneText(e,c.number,a),actions:t?[{label:a.viewTicket,onPress:()=>t(c)}]:void 0,testID:s});const u="sending"===r,_=new Date(e.expiresDateTimeUtc).getTime()<=Date.now(),b="RaiseTicket"===e.kind?[e.category,e.subject].filter(Boolean).join(", "):"";return(0,_jsxRuntime.jsx)(_mobileUi.Card,{variant:"outline",padding:"sm",testID:s,children:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{gap:o.space.sm},children:[(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"label",children:titleOf(e,a)}),""!==b&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"secondary",children:b}),"Reopen"!==e.kind&&e.body?(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",children:e.body}):null,_?(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"secondary",children:a.actionExpired}):(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:"secondary",children:a.actionNote}),""!==m&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:m}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flexDirection:"row",flexWrap:"wrap",gap:o.space.sm},children:[(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:a.actionConfirm,size:"sm",loading:u,disabled:u,onPress:()=>{(async()=>{l("sending"),x("");try{d(await i(e.token)),l("done")}catch(e){const i=e?.message;x("string"==typeof i&&i?i:a.actionFailed),l("ready")}})()},testID:`${s}-confirm`}),(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:a.actionDismiss,size:"sm",variant:"outline",disabled:u,onPress:()=>l("dismissed"),testID:`${s}-dismiss`})]})]})]})})};exports.ActionCard=ActionCard;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ActionCard=void 0;var _chat=require("@webority/markdown-core/chat"),_mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_jsxRuntime=require("react/jsx-runtime");const titleOf=(e,i)=>"Reply"===e.kind?i.actionReply(e.ticketNumber??""):"Reopen"===e.kind?i.actionReopen(e.ticketNumber??""):i.actionRaiseTicket,doneText=(e,i,t)=>"Reply"===e.kind?t.actionDoneReply(i):"Reopen"===e.kind?t.actionDoneReopen(i):t.actionDoneRaiseTicket(i),ActionCard=({action:e,confirmAction:i,onViewTicket:t,labels:n,testID:s="chat-action"})=>{const a=(0,_chat.mergeLabels)(n),o=(0,_mobileUi.useTheme)(),[r,c]=(0,_react.useState)("ready"),[l,d]=(0,_react.useState)(null),[m,x]=(0,_react.useState)("");if("dismissed"===r)return(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"secondary",testID:s,children:a.actionDismissed});if("done"===r&&l)return(0,_jsxRuntime.jsx)(_mobileUi.Banner,{tone:"success",message:doneText(e,l.number,a),actions:t?[{label:a.viewTicket,onPress:()=>t(l)}]:void 0,testID:s});const u="sending"===r,_=new Date(e.expiresDateTimeUtc).getTime()<=Date.now(),b="RaiseTicket"===e.kind?[e.category,e.subject].filter(Boolean).join(", "):"";return(0,_jsxRuntime.jsx)(_mobileUi.Card,{variant:"outline",padding:"sm",testID:s,children:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{gap:o.space.sm},children:[(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"label",children:titleOf(e,a)}),""!==b&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"secondary",children:b}),"Reopen"!==e.kind&&e.body?(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",children:e.body}):null,_?(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"secondary",children:a.actionExpired}):(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:"secondary",children:a.actionNote}),""!==m&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:m}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flexDirection:"row",flexWrap:"wrap",gap:o.space.sm},children:[(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:a.actionConfirm,size:"sm",loading:u,disabled:u,onPress:()=>{(async()=>{c("sending"),x("");try{d(await i(e.token)),c("done")}catch(e){const i=e?.message;x("string"==typeof i&&i?i:a.actionFailed),c("ready")}})()},testID:`${s}-confirm`}),(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:a.actionDismiss,size:"sm",variant:"outline",disabled:u,onPress:()=>c("dismissed"),testID:`${s}-dismiss`})]})]})]})})};exports.ActionCard=ActionCard;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatComposer=void 0;var _mobileUi=require("@webority/mobile-ui"),_labels=require("../labels.js"),_jsxRuntime=require("react/jsx-runtime");const ChatComposer=({onSubmit:e,busy:o=!1,disabled:s=!1,maxLength:r=4e3,above:a,below:t,keyboardAware:l,keyboardOffset:b,safeArea:i,labels:d,testID:m="chat-composer"})=>{const n=(0,_labels.mergeLabels)(d);return(0,_jsxRuntime.jsx)(_mobileUi.Composer,{onSend:e,loading:o,disabled:s,maxLength:r,placeholder:n.placeholder,accessibilityLabel:n.composer,labels:{send:n.send},above:a,below:t,keyboardAware:l,keyboardOffset:b,safeArea:i,testID:m})};exports.ChatComposer=ChatComposer;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatComposer=void 0;var _chat=require("@webority/markdown-core/chat"),_mobileUi=require("@webority/mobile-ui"),_react=require("react"),_ComposerAttachments=require("./ComposerAttachments.js"),_jsxRuntime=require("react/jsx-runtime");const ChatComposer=({onSubmit:e,busy:t=!1,onStop:s,disabled:a=!1,maxLength:o=4e3,above:n,below:i,keyboardAware:r,keyboardOffset:c,safeArea:l,attachments:m=[],onAttach:d,onRemoveAttachment:b,editing:u,onCancelEdit:h,labels:p,testID:x="chat-composer"})=>{const _=(0,_chat.mergeLabels)(p),j=m.some(e=>"Uploading"===e.status),C=m.some(e=>"Ready"===e.status),[g,v]=(0,_react.useState)("");(0,_react.useEffect)(()=>{v(u?u.text:"")},[u]);const y=u?(0,_jsxRuntime.jsx)(_mobileUi.Banner,{message:_.editing,accessibilityRole:"summary",actions:h?[{label:_.cancel,onPress:h,testID:`${x}-cancel-edit`}]:void 0,testID:`${x}-editing`}):null,R=m.length>0?(0,_jsxRuntime.jsx)(_ComposerAttachments.ComposerAttachments,{attachments:m,onRemove:b,labels:p,testID:`${x}-attachments`}):null,A=y||R||n?(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[y,R,n]}):void 0,f=d?(0,_jsxRuntime.jsx)(_mobileUi.IconButton,{icon:"paperclip",accessibilityLabel:_.attach,variant:"ghost",tone:"neutral",disabled:a||t,onPress:d,testID:`${x}-attach`}):void 0;return(0,_jsxRuntime.jsx)(_mobileUi.Composer,{onSend:e,value:g,onChangeText:v,loading:t,onStop:s,stopLabel:_.stop,disabled:a,maxLength:o,canSend:!j&&(!!C||void 0),placeholder:_.placeholder,accessibilityLabel:_.composer,labels:{send:_.send},leading:f,above:A,below:i,keyboardAware:r,keyboardOffset:c,safeArea:l,testID:x})};exports.ChatComposer=ChatComposer;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatConversationList=void 0;var _mobileCore=require("@webority/mobile-core"),_mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_labels=require("../labels.js"),_jsxRuntime=require("react/jsx-runtime");const messageOf=(e,t)=>{const i=e?.message;return"string"==typeof i&&i?i:t},ChatConversationList=({client:e,onOpen:t,onDeleted:i,pageSize:s=20,labels:a,style:n,testID:l="chat-conversations"})=>{const r=(0,_labels.mergeLabels)(a),o=(0,_mobileUi.useTheme)(),[c,m]=(0,_react.useState)([]),[u,_]=(0,_react.useState)(!0),[d,b]=(0,_react.useState)(!1),[x,j]=(0,_react.useState)(""),[g,h]=(0,_react.useState)(!1),[p,v]=(0,_react.useState)(null),[y,f]=(0,_react.useState)(!1),[C,R]=(0,_react.useState)(""),I=r.loadFailed,S=(0,_react.useCallback)(async t=>{_(!0),j("");try{const i=await e.listConversations({skip:t,take:s});m(e=>0===t?i:[...e,...i]),h(i.length===s)}catch(e){j(messageOf(e,I))}finally{_(!1)}},[e,s,I]);(0,_react.useEffect)(()=>{S(0)},[S]);const U=!u&&""===x&&0===c.length;return(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:n,contentContainerStyle:{padding:o.space.md,gap:o.space.sm,flexGrow:1},refreshControl:(0,_jsxRuntime.jsx)(_reactNative.RefreshControl,{refreshing:d,onRefresh:()=>{(async()=>{b(!0),await S(0),b(!1)})()}}),accessibilityLabel:r.conversations,testID:l,children:[""!==x&&(0,_jsxRuntime.jsx)(_mobileUi.Banner,{tone:"danger",message:x,actions:[{label:r.retry,onPress:()=>{S(0)}}],testID:`${l}-error`}),U&&(0,_jsxRuntime.jsx)(_mobileUi.EmptyState,{size:"sm",title:r.conversationsEmptyTitle,description:r.conversationsEmptyText,testID:`${l}-empty`}),c.map(e=>(0,_jsxRuntime.jsx)(_mobileUi.Card,{variant:"outline",padding:"sm",onPress:()=>t(e),accessibilityLabel:e.title||r.untitled,testID:`${l}-item-${e.publicId}`,children:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flexDirection:"row",alignItems:"center",gap:o.space.sm},children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flex:1,minWidth:0},children:[(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"label",numberOfLines:1,children:e.title||r.untitled}),(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:"secondary",children:(0,_mobileCore.formatDateTime)(e.lastMessageDateTimeUtc)})]}),(0,_jsxRuntime.jsx)(_mobileUi.IconButton,{icon:"trash",tone:"danger",variant:"ghost",accessibilityLabel:r.deleteConversation,onPress:()=>{R(""),v(e)},testID:`${l}-delete-${e.publicId}`})]})},e.publicId)),u&&!d&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{gap:o.space.sm},accessibilityElementsHidden:!0,children:[(0,_jsxRuntime.jsx)(_mobileUi.Skeleton,{height:56}),(0,_jsxRuntime.jsx)(_mobileUi.Skeleton,{height:56}),(0,_jsxRuntime.jsx)(_mobileUi.Skeleton,{height:56})]}),!u&&g&&(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:r.loadMore,variant:"outline",onPress:()=>{S(c.length)},testID:`${l}-more`}),(0,_jsxRuntime.jsx)(_mobileUi.Dialog,{visible:null!==p,onClose:()=>{y||v(null)},tone:"warning",title:r.deleteConfirmTitle,message:C||r.deleteConfirmMessage,dismissOnAction:!1,actions:[{label:r.cancel,tone:"neutral",disabled:y,onPress:()=>v(null)},{label:r.deleteConfirm,tone:"danger",loading:y,onPress:()=>{(async()=>{if(p){f(!0),R("");try{await e.deleteConversation(p.publicId),m(e=>e.filter(e=>e.publicId!==p.publicId)),i?.(p.publicId),v(null)}catch(e){R(messageOf(e,r.deleteFailed))}finally{f(!1)}}})()}}],testID:`${l}-confirm`})]})};exports.ChatConversationList=ChatConversationList;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatConversationList=void 0;var _chat=require("@webority/markdown-core/chat"),_mobileCore=require("@webority/mobile-core"),_mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_jsxRuntime=require("react/jsx-runtime");const messageOf=(e,t)=>{const i=e?.message;return"string"==typeof i&&i?i:t},IDLE_STATE={items:[],totalCount:null,loading:!0,error:null,hasMore:!1},IDLE={getState:()=>IDLE_STATE,subscribe:()=>()=>{}},ChatConversationList=({client:e,onOpen:t,onDeleted:i,pageSize:s=20,labels:n,style:a,testID:r="chat-conversations"})=>{const l=(0,_chat.mergeLabels)(n),o=(0,_mobileUi.useTheme)(),[c,m]=(0,_react.useState)(null),u=c??IDLE,{items:d,loading:_,error:b,hasMore:x}=(0,_react.useSyncExternalStore)(u.subscribe,u.getState),[g,j]=(0,_react.useState)(!1),[h,p]=(0,_react.useState)(null),[v,y]=(0,_react.useState)(!1),[S,f]=(0,_react.useState)(""),[I,C]=(0,_react.useState)(null),[R,D]=(0,_react.useState)(""),[U,L]=(0,_react.useState)(!1),[T,w]=(0,_react.useState)(""),[E,$]=(0,_react.useState)(void 0),[P,O]=(0,_react.useState)("");(0,_react.useEffect)(()=>{const t=(0,_chat.createConversationList)({client:e,pageSize:s});return m(t),t.load(),()=>t.dispose()},[e,s]),(0,_react.useEffect)(()=>{let t=!0;return e.getSettings().then(e=>{t&&$(e.titleMaxLength)},e=>{t&&O(messageOf(e,l.renameFailed))}),()=>{t=!1}},[e,l.renameFailed]);const M=R.trim(),save=async()=>{if(I&&""!==M){L(!0),w("");try{await(c?.rename(I.publicId,M)),C(null)}catch(e){w(messageOf(e,l.renameFailed))}finally{L(!1)}}},q=!_&&!b&&0===d.length;return(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:a,contentContainerStyle:{padding:o.space.md,gap:o.space.sm,flexGrow:1},refreshControl:(0,_jsxRuntime.jsx)(_reactNative.RefreshControl,{refreshing:g,onRefresh:()=>{(async()=>{j(!0),await(c?.load()),j(!1)})()}}),accessibilityLabel:l.conversations,testID:r,children:[b&&(0,_jsxRuntime.jsx)(_mobileUi.Banner,{tone:"danger",message:b.message||l.loadFailed,actions:[{label:l.retry,onPress:()=>{c?.load()}}],testID:`${r}-error`}),q&&(0,_jsxRuntime.jsx)(_mobileUi.EmptyState,{size:"sm",title:l.conversationsEmptyTitle,description:l.conversationsEmptyText,testID:`${r}-empty`}),d.map(e=>(0,_jsxRuntime.jsx)(_mobileUi.Card,{variant:"outline",padding:"sm",onPress:()=>t(e),accessibilityLabel:e.title||l.untitled,testID:`${r}-item-${e.publicId}`,children:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flexDirection:"row",alignItems:"center",gap:o.space.sm},children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flex:1,minWidth:0},children:[(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"label",numberOfLines:1,children:e.title||l.untitled}),(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:"secondary",children:(0,_mobileCore.formatDateTime)(e.lastMessageDateTimeUtc)})]}),(0,_jsxRuntime.jsx)(_mobileUi.IconButton,{icon:"edit",variant:"ghost",accessibilityLabel:l.renameConversation,onPress:()=>{w(""),D(e.title??""),C(e)},testID:`${r}-rename-${e.publicId}`}),(0,_jsxRuntime.jsx)(_mobileUi.IconButton,{icon:"trash",tone:"danger",variant:"ghost",accessibilityLabel:l.deleteConversation,onPress:()=>{f(""),p(e)},testID:`${r}-delete-${e.publicId}`})]})},e.publicId)),_&&!g&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{gap:o.space.sm},accessibilityElementsHidden:!0,children:[(0,_jsxRuntime.jsx)(_mobileUi.Skeleton,{height:56}),(0,_jsxRuntime.jsx)(_mobileUi.Skeleton,{height:56}),(0,_jsxRuntime.jsx)(_mobileUi.Skeleton,{height:56})]}),!_&&x&&(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:l.loadMore,variant:"outline",onPress:()=>{c?.loadMore()},testID:`${r}-more`}),(0,_jsxRuntime.jsxs)(_mobileUi.Dialog,{visible:null!==I,onClose:()=>{U||C(null)},title:l.renameConversation,dismissOnAction:!1,actions:[{label:l.cancel,tone:"neutral",disabled:U,onPress:()=>C(null)},{label:l.renameSave,disabled:""===M||U,loading:U,onPress:()=>{save()}}],testID:`${r}-rename`,children:[(0,_jsxRuntime.jsx)(_mobileUi.Input,{label:l.conversationTitle,value:R,onChangeText:D,maxLength:E,returnKeyType:"done",onSubmitEditing:()=>{save()},testID:`${r}-rename-input`}),""!==(T||P)&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:"danger",testID:`${r}-rename-error`,children:T||P})]}),(0,_jsxRuntime.jsx)(_mobileUi.Dialog,{visible:null!==h,onClose:()=>{v||p(null)},tone:"warning",title:l.deleteConfirmTitle,message:S||l.deleteConfirmMessage,dismissOnAction:!1,actions:[{label:l.cancel,tone:"neutral",disabled:v,onPress:()=>p(null)},{label:l.deleteConfirm,tone:"danger",loading:v,onPress:()=>{(async()=>{if(h){y(!0),f("");try{await(c?.remove(h.publicId)),i?.(h.publicId),p(null)}catch(e){f(messageOf(e,l.deleteFailed))}finally{y(!1)}}})()}}],testID:`${r}-confirm`})]})};exports.ChatConversationList=ChatConversationList;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatLauncher=void 0;var _mobileUi=require("@webority/mobile-ui"),_labels=require("../labels.js"),_jsxRuntime=require("react/jsx-runtime");const ChatLauncher=({onPress:e,position:t="end",bottomOffset:s,compact:o=!1,labels:i,testID:r="chat-launcher"})=>{const a=(0,_labels.mergeLabels)(i);return(0,_jsxRuntime.jsx)(_mobileUi.FloatingActionButton,{icon:"messages",label:o?void 0:a.launcher,accessibilityLabel:a.launcher,position:"end"===t?"bottomRight":"bottomLeft",bottomOffset:s,onPress:e,testID:r})};exports.ChatLauncher=ChatLauncher;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatLauncher=void 0;var _chat=require("@webority/markdown-core/chat"),_mobileUi=require("@webority/mobile-ui"),_jsxRuntime=require("react/jsx-runtime");const ChatLauncher=({onPress:e,position:t="end",bottomOffset:o,compact:r=!1,labels:i,testID:s="chat-launcher"})=>{const a=(0,_chat.mergeLabels)(i);return(0,_jsxRuntime.jsx)(_mobileUi.FloatingActionButton,{icon:"messages",label:r?void 0:a.launcher,accessibilityLabel:a.launcher,position:"end"===t?"bottomRight":"bottomLeft",bottomOffset:o,onPress:e,testID:s})};exports.ChatLauncher=ChatLauncher;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatMarkdown=ChatMarkdown;var _mobileUi=require("@webority/mobile-ui"),_jsxRuntime=require("react/jsx-runtime");function ChatMarkdown({text:e,resolveLink:r,onLinkPress:t,testID:i}){return(0,_jsxRuntime.jsx)(_mobileUi.Markdown,{links:"app",headings:"text",resolveLink:r,onAppLinkPress:t,testID:i,children:e})}
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatMarkdown=ChatMarkdown;var _mobileUi=require("@webority/mobile-ui"),_jsxRuntime=require("react/jsx-runtime");function ChatMarkdown({text:e,resolveLink:i,onLinkPress:t,isCitation:n,onOpenCitation:r,testID:o}){return(0,_jsxRuntime.jsx)(_mobileUi.Markdown,{links:"app",headings:"text",resolveLink:i,onAppLinkPress:t,isCitation:n,onOpenCitation:r,testID:o,children:e})}
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatMessage=void 0;var _markdownCore=require("@webority/markdown-core"),_mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_labels=require("../labels.js"),_ActionCard=require("./ActionCard.js"),_ChatMarkdown=require("./ChatMarkdown.js"),_ReplyRating=require("./ReplyRating.js"),_jsxRuntime=require("react/jsx-runtime");function ChatMessageView({turn:e,onRate:t,resolveLink:i,onLinkPress:s,confirmAction:r,onViewTicket:a,renderReply:n,labels:o,testID:l="chat-message"}){const m=(0,_labels.mergeLabels)(o),u=(0,_mobileUi.useTheme)(),c=e.streaming&&!e.answer,_=(0,_react.useMemo)(()=>e.streaming?e.answer:(0,_markdownCore.markdownToPlainText)(e.answer),[e.streaming,e.answer]),g=(0,_react.useMemo)(()=>({you:m.you}),[m.you]);return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{gap:u.space.sm},testID:l,children:[""!==e.question&&(0,_jsxRuntime.jsx)(_mobileUi.MessageBubble,{side:"mine",text:e.question,labels:g,testID:`${l}-question`}),c?(0,_jsxRuntime.jsx)(_mobileUi.TypingIndicator,{label:m.thinking,testID:`${l}-thinking`}):null,""!==e.answer?(0,_jsxRuntime.jsx)(_mobileUi.MessageBubble,{side:"theirs",author:m.assistant,text:_,streaming:e.streaming,testID:`${l}-answer`,children:n?n(e,{streaming:e.streaming}):(0,_jsxRuntime.jsx)(_ChatMarkdown.ChatMarkdown,{text:e.answer,resolveLink:i,onLinkPress:s})}):null,e.error&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:e.error.message}),r&&!e.streaming&&e.actions.map(e=>(0,_jsxRuntime.jsx)(_ActionCard.ActionCard,{action:e,confirmAction:r,onViewTicket:a,labels:o},e.token)),t&&e.messageId&&!e.streaming&&(0,_jsxRuntime.jsx)(_ReplyRating.ReplyRating,{rating:e.rating,onRate:(i,s)=>t(e.id,i,s),labels:o})]})}const ChatMessage=exports.ChatMessage=(0,_react.memo)(ChatMessageView);
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatMessage=void 0;var _markdownCore=require("@webority/markdown-core"),_chat=require("@webority/markdown-core/chat"),_clipboard=require("@webority/mobile-core/clipboard"),_mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_ActionCard=require("./ActionCard.js"),_ChatMarkdown=require("./ChatMarkdown.js"),_ReplyRating=require("./ReplyRating.js"),_jsxRuntime=require("react/jsx-runtime");function ChatMessageView({turn:e,canRegenerate:t=!1,onRetry:i,onRegenerate:s,onEdit:n,onOpenAttachment:a,onRate:r,resolveLink:o,onLinkPress:l,isCitation:c,onOpenCitation:m,onAskSuggestion:u,confirmAction:x,onViewTicket:_,renderReply:p,labels:g,testID:d="chat-message"}){const b=(0,_chat.mergeLabels)(g),j=(0,_mobileUi.useTheme)(),[w,R]=(0,_react.useState)(!1),h=(0,_react.useRef)(null);(0,_react.useEffect)(()=>()=>{null!==h.current&&clearTimeout(h.current)},[]);const y=e.streaming&&!e.answer,k=(0,_react.useMemo)(()=>e.streaming?e.answer:(0,_markdownCore.markdownToPlainText)(e.answer),[e.streaming,e.answer]),C=(0,_react.useMemo)(()=>({you:b.you}),[b.you]),v=!e.streaming&&(e.stopped||null!==e.error),I=!e.streaming&&null!==e.questionId,T=e.attachments.length>0||e.stopped||i&&v||n&&I?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{gap:j.space.xs},children:[e.attachments.length>0?(0,_jsxRuntime.jsx)(_reactNative.View,{style:{flexDirection:"row",flexWrap:"wrap",gap:j.space.xs},children:e.attachments.map(e=>(0,_jsxRuntime.jsx)(_mobileUi.Chip,{label:e.fileName,onPress:a?()=>a(e):void 0,testID:`${d}-attachment-${e.publicId}`},e.publicId))}):null,e.stopped?(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"secondary",accessibilityLiveRegion:"polite",testID:`${d}-stopped`,children:b.stopped}):null,i&&v||n&&I?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flexDirection:"row",flexWrap:"wrap",gap:j.space.xs},children:[i&&v?(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:b.retry,variant:"link",size:"sm",onPress:()=>i(e.id),testID:`${d}-retry`}):null,n&&I?(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:b.edit,variant:"link",size:"sm",onPress:()=>n(e.id),testID:`${d}-edit`}):null]}):null]}):null;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{gap:j.space.sm},testID:d,children:[""!==e.question&&(0,_jsxRuntime.jsx)(_mobileUi.MessageBubble,{side:"mine",text:e.question,labels:C,footer:T,testID:`${d}-question`}),y?(0,_jsxRuntime.jsx)(_mobileUi.TypingIndicator,{label:b.thinking,testID:`${d}-thinking`}):null,""!==e.answer?(0,_jsxRuntime.jsx)(_mobileUi.MessageBubble,{side:"theirs",author:b.assistant,text:k,streaming:e.streaming,onCopy:()=>{(0,_clipboard.copyText)((0,_markdownCore.markdownToPlainText)(e.answer))},testID:`${d}-answer`,children:p?p(e,{streaming:e.streaming}):(0,_jsxRuntime.jsx)(_ChatMarkdown.ChatMarkdown,{text:e.answer,resolveLink:o,onLinkPress:l,isCitation:c,onOpenCitation:m})}):null,e.streaming&&e.step?(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:"secondary",accessibilityLiveRegion:"polite",testID:`${d}-step`,children:b.toolStep(e.step)}):null,e.streaming||""===e.answer?null:(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:w?b.copied:b.copy,variant:"link",size:"sm",onPress:()=>{(async()=>{await(0,_clipboard.copyText)((0,_markdownCore.markdownToPlainText)(e.answer))&&(R(!0),null!==h.current&&clearTimeout(h.current),h.current=setTimeout(()=>R(!1),2e3))})()},testID:`${d}-copy`}),u&&!e.streaming&&e.suggestions.length>0?(0,_jsxRuntime.jsx)(_reactNative.View,{accessibilityRole:"list",accessibilityLabel:b.suggestions,style:{flexDirection:"row",flexWrap:"wrap",gap:j.space.xs},children:e.suggestions.map((e,t)=>(0,_jsxRuntime.jsx)(_mobileUi.Chip,{label:e,onPress:()=>u(e),testID:`${d}-suggestion-${t}`},e))}):null,t&&s&&!e.streaming&&""!==e.answer?(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:b.regenerate,variant:"link",size:"sm",onPress:()=>s(e.id),testID:`${d}-regenerate`}):null,e.error&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:e.error.message}),x&&!e.streaming&&e.actions.map(e=>(0,_jsxRuntime.jsx)(_ActionCard.ActionCard,{action:e,confirmAction:x,onViewTicket:_,labels:g},e.token)),r&&e.messageId&&!e.streaming&&(0,_jsxRuntime.jsx)(_ReplyRating.ReplyRating,{rating:e.rating,onRate:(t,i)=>r(e.id,t,i),labels:g})]})}const ChatMessage=exports.ChatMessage=(0,_react.memo)(ChatMessageView);
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatScreen=ChatScreen;var _mobileUi=require("@webority/mobile-ui"),_reactNative=require("react-native"),_labels=require("../labels.js"),_ChatComposer=require("./ChatComposer.js"),_ChatThread=require("./ChatThread.js"),_jsxRuntime=require("react/jsx-runtime");function ChatScreen({chat:e,title:t,headerActions:s,empty:i,disclaimer:r,maxLength:a=4e3,allowanceThreshold:n=10,rating:l=!0,keyboardOffset:o,testID:m="chat-screen",...d}){const c=(0,_labels.mergeLabels)(d.labels),u=(0,_mobileUi.useTheme)(),x=e.messagesLeftToday,b=void 0===r?c.disclaimer:r;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flex:1,backgroundColor:u.colors.bg},testID:m,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flexDirection:"row",alignItems:"center",gap:u.space.sm,paddingHorizontal:u.space.md,paddingVertical:u.space.sm,borderBottomWidth:1,borderBottomColor:u.colors["border-subtle"]},children:[(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"title",accessibilityRole:"header",style:{flex:1},numberOfLines:1,children:t??c.panelTitle}),s,(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:c.newChat,size:"sm",variant:"soft",leftIcon:"add",disabled:0===e.turns.length&&!e.loading,onPress:e.newConversation,testID:`${m}-new`})]}),e.loading?(0,_jsxRuntime.jsx)(_reactNative.View,{style:{flex:1,alignItems:"center",justifyContent:"center"},children:(0,_jsxRuntime.jsx)(_mobileUi.Spinner,{message:c.loadingConversation,testID:`${m}-loading`})}):(0,_jsxRuntime.jsx)(_ChatThread.ChatThread,{turns:e.turns,style:{flex:1},keyboardOffset:o,onRate:l?e.rate:void 0,empty:i??(0,_jsxRuntime.jsx)(_mobileUi.EmptyState,{fill:!0,size:"sm",title:c.emptyTitle,description:c.emptyText,testID:`${m}-empty`}),testID:`${m}-thread`,...d}),(0,_jsxRuntime.jsx)(_ChatComposer.ChatComposer,{onSubmit:t=>{e.submit(t)},busy:e.streaming,disabled:0===x||e.loading,maxLength:a,keyboardOffset:o,labels:d.labels,testID:`${m}-composer`,above:(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[e.loadError&&(0,_jsxRuntime.jsx)(_mobileUi.Banner,{tone:"danger",message:e.loadError.message,testID:`${m}-load-error`}),null!==x&&x<=n&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:0===x?"danger":"secondary",accessibilityLiveRegion:"polite",testID:`${m}-allowance`,children:c.allowance(x)})]}),below:b?(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:"tertiary",testID:`${m}-disclaimer`,children:b}):null})]})}
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatScreen=ChatScreen;var _chat=require("@webority/markdown-core/chat"),_mobileUi=require("@webority/mobile-ui"),_reactNative=require("react-native"),_ChatComposer=require("./ChatComposer.js"),_ChatThread=require("./ChatThread.js"),_jsxRuntime=require("react/jsx-runtime");function ChatScreen({chat:e,pickAttachments:t,onOpenAttachment:s,title:i,headerActions:a,empty:n,disclaimer:r,maxLength:o=4e3,allowanceThreshold:l=10,rating:m=!0,keyboardOffset:c,testID:d="chat-screen",...h}){const u=(0,_chat.mergeLabels)(h.labels),x=(0,_mobileUi.useTheme)(),b=e.messagesLeftToday,g=void 0===r?u.disclaimer:r,_=t&&e.settings?.attachments?async()=>e.attach(await t()):void 0;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flex:1,backgroundColor:x.colors.bg},testID:d,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flexDirection:"row",alignItems:"center",gap:x.space.sm,paddingHorizontal:x.space.md,paddingVertical:x.space.sm,borderBottomWidth:1,borderBottomColor:x.colors["border-subtle"]},children:[(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"title",accessibilityRole:"header",style:{flex:1},numberOfLines:1,children:i??u.panelTitle}),a,(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:u.newChat,size:"sm",variant:"soft",leftIcon:"add",disabled:0===e.turns.length&&!e.loading,onPress:e.newConversation,testID:`${d}-new`})]}),e.loading?(0,_jsxRuntime.jsx)(_reactNative.View,{style:{flex:1,alignItems:"center",justifyContent:"center"},children:(0,_jsxRuntime.jsx)(_mobileUi.Spinner,{message:u.loadingConversation,testID:`${d}-loading`})}):(0,_jsxRuntime.jsx)(_ChatThread.ChatThread,{turns:e.turns,style:{flex:1},keyboardOffset:c,onRate:m?e.rate:void 0,onRetry:e.retry,onRegenerate:e.regenerate,onEdit:e.startEdit,onOpenAttachment:s,empty:n??(0,_jsxRuntime.jsx)(_mobileUi.EmptyState,{fill:!0,size:"sm",title:u.emptyTitle,description:u.emptyText,testID:`${d}-empty`}),testID:`${d}-thread`,...h,onAskSuggestion:e.submit}),(0,_jsxRuntime.jsx)(_ChatComposer.ChatComposer,{onSubmit:t=>{e.submit(t)},busy:e.streaming,onStop:e.stop,disabled:0===b||e.loading,maxLength:o,keyboardOffset:c,labels:h.labels,onAttach:_,attachments:e.attachments,onRemoveAttachment:t=>{e.removeAttachment(t)},editing:e.editing,onCancelEdit:e.cancelEdit,testID:`${d}-composer`,above:(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[e.loadError&&(0,_jsxRuntime.jsx)(_mobileUi.Banner,{tone:"danger",message:e.loadError.message,testID:`${d}-load-error`}),e.settingsError&&(0,_jsxRuntime.jsx)(_mobileUi.Banner,{tone:"danger",message:e.settingsError.message,testID:`${d}-settings-error`}),null!==b&&b<=l&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:0===b?"danger":"secondary",accessibilityLiveRegion:"polite",testID:`${d}-allowance`,children:u.allowance(b)})]}),below:g?(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:"tertiary",testID:`${d}-disclaimer`,children:g}):null})]})}
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatThread=ChatThread;var _mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_labels=require("../labels.js"),_ChatMessage=require("./ChatMessage.js"),_jsxRuntime=require("react/jsx-runtime");const turnKey=e=>e.id,followTurn=()=>!0,TurnGap=()=>{const e=(0,_mobileUi.useTheme)();return(0,_jsxRuntime.jsx)(_reactNative.View,{style:{height:e.space.lg}})};function ChatThread({turns:e,empty:t,keyboardAware:r,keyboardOffset:s,style:a,testID:i="chat-thread",...o}){const u=(0,_labels.mergeLabels)(o.labels),l=(0,_react.useMemo)(()=>[...e].reverse(),[e]);return(0,_jsxRuntime.jsx)(_mobileUi.MessageList,{messages:l,keyExtractor:turnKey,renderMessage:({item:e})=>(0,_jsxRuntime.jsx)(_ChatMessage.ChatMessage,{turn:e,testID:`${i}-${e.id}`,...o}),followNew:followTurn,empty:t,ItemSeparatorComponent:TurnGap,keyboardAware:r,keyboardOffset:s,accessibilityLabel:u.thread,style:a,testID:i})}
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatThread=ChatThread;var _chat=require("@webority/markdown-core/chat"),_mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_ChatMessage=require("./ChatMessage.js"),_jsxRuntime=require("react/jsx-runtime");const turnKey=e=>e.id,followTurn=()=>!0,TurnGap=()=>{const e=(0,_mobileUi.useTheme)();return(0,_jsxRuntime.jsx)(_reactNative.View,{style:{height:e.space.lg}})};function ChatThread({turns:e,empty:t,keyboardAware:r,keyboardOffset:a,onRetry:s,onRegenerate:n,onEdit:i,onOpenAttachment:o,onAskSuggestion:u,style:c,testID:l="chat-thread",...d}){const m=(0,_chat.mergeLabels)(d.labels),h=(0,_react.useMemo)(()=>[...e].reverse(),[e]),g=(0,_react.useMemo)(()=>{const t=e[e.length-1];return t&&null!==t.messageId&&!t.streaming?t.id:null},[e]),y=e[e.length-1]?.id;return(0,_jsxRuntime.jsx)(_mobileUi.MessageList,{messages:h,keyExtractor:turnKey,renderMessage:({item:e})=>(0,_jsxRuntime.jsx)(_ChatMessage.ChatMessage,{turn:e,onRetry:s,canRegenerate:e.id===g,onRegenerate:e.id===g?n:void 0,onEdit:i,onOpenAttachment:o,testID:`${l}-${e.id}`,...d,onAskSuggestion:e.id===y?u:void 0}),followNew:followTurn,empty:t,ItemSeparatorComponent:TurnGap,keyboardAware:r,keyboardOffset:a,accessibilityLabel:m.thread,style:c,testID:l})}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ComposerAttachments=void 0;var _chat=require("@webority/markdown-core/chat"),_mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_jsxRuntime=require("react/jsx-runtime");const ComposerAttachments=({attachments:e,onRemove:t,labels:r,testID:s="composer-attachments"})=>{const a=(0,_mobileUi.useTheme)(),i=(0,_react.useMemo)(()=>buildStyles(a),[a]),o=(0,_chat.mergeLabels)(r),m=(0,_react.useMemo)(()=>({remove:o.removeAttachment}),[o.removeAttachment]);return(0,_jsxRuntime.jsx)(_reactNative.View,{style:i.root,testID:s,children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:i.row,children:e.map(e=>(0,_jsxRuntime.jsxs)(_reactNative.View,{style:i.item,children:[(0,_jsxRuntime.jsx)(_mobileUi.Chip,{label:e.fileName,variant:"soft",onRemove:t?()=>t(e.key):void 0,labels:m,removeTestID:`chat-attachment-remove-${e.key}`,testID:`${s}-${e.key}`}),"Uploading"===e.status?(0,_jsxRuntime.jsx)(_mobileUi.ProgressBar,{progress:e.progress??void 0,label:o.attachmentUploading,height:4,containerStyle:i.progress}):null,"Failed"===e.status?(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:"danger",accessibilityLiveRegion:"polite",children:o.attachmentFailed}):null]},e.key))})})};exports.ComposerAttachments=ComposerAttachments;const buildStyles=e=>_reactNative.StyleSheet.create({root:{gap:e.space.xs},row:{flexDirection:"row",flexWrap:"wrap",gap:e.space.xs},item:{gap:e.space.xxs,maxWidth:"100%"},progress:{minWidth:120}});
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ReplyRating=void 0;var _mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_labels=require("../labels.js"),_jsxRuntime=require("react/jsx-runtime");const ReplyRating=({rating:e=null,onRate:t,noteMaxLength:i=1e3,labels:s,testID:a="chat-rating"})=>{const l=(0,_labels.mergeLabels)(s),n=(0,_mobileUi.useTheme)(),[r,o]=(0,_react.useState)(!1),[c,d]=(0,_react.useState)(!1),[u,x]=(0,_react.useState)(""),[m,_]=(0,_react.useState)(""),[b,p]=(0,_react.useState)(!1),save=async(e,i)=>{o(!0),_("");try{await t(e,i),d("Down"===e&&void 0===i),p("Up"===e||void 0!==i),void 0!==i&&x("")}catch{_(l.ratingFailed)}finally{o(!1)}};return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{gap:n.space.sm},testID:a,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flexDirection:"row",flexWrap:"wrap",alignItems:"center",gap:n.space.xs},children:[(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:l.rateUp,size:"sm",leftIcon:"like",variant:"Up"===e?"soft":"ghost",accessibilityState:{selected:"Up"===e,disabled:r},"aria-selected":"Up"===e,"aria-disabled":r,disabled:r,onPress:()=>{save("Up")},testID:`${a}-up`}),(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:l.rateDown,size:"sm",leftIcon:"dislike",variant:"Down"===e?"soft":"ghost",accessibilityState:{selected:"Down"===e,disabled:r},"aria-selected":"Down"===e,"aria-disabled":r,disabled:r,onPress:()=>{save("Down")},testID:`${a}-down`}),b&&!c&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:"secondary",accessibilityLiveRegion:"polite",children:l.rated})]}),""!==m&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:m}),c&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{gap:n.space.sm},children:[(0,_jsxRuntime.jsx)(_mobileUi.Input,{label:l.ratingNote,helperText:l.ratingNoteHint,multiline:!0,maxLength:i,value:u,onChangeText:x,testID:`${a}-note`}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flexDirection:"row",gap:n.space.sm},children:[(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:l.ratingNoteSend,size:"sm",loading:r,disabled:r,onPress:()=>{save("Down",u)},testID:`${a}-note-send`}),(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:l.ratingNoteSkip,size:"sm",variant:"outline",disabled:r,onPress:()=>{d(!1),p(!0)},testID:`${a}-note-skip`})]})]})]})};exports.ReplyRating=ReplyRating;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ReplyRating=void 0;var _chat=require("@webority/markdown-core/chat"),_mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_jsxRuntime=require("react/jsx-runtime");const ReplyRating=({rating:e=null,onRate:t,noteMaxLength:i=1e3,labels:a,testID:s="chat-rating"})=>{const n=(0,_chat.mergeLabels)(a),r=(0,_mobileUi.useTheme)(),[l,o]=(0,_react.useState)(!1),[c,d]=(0,_react.useState)(!1),[u,m]=(0,_react.useState)(""),[x,_]=(0,_react.useState)(""),[b,p]=(0,_react.useState)(!1),save=async(e,i)=>{o(!0),_("");try{await t(e,i),d("Down"===e&&void 0===i),p("Up"===e||void 0!==i),void 0!==i&&m("")}catch{_(n.ratingFailed)}finally{o(!1)}};return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{gap:r.space.sm},testID:s,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flexDirection:"row",flexWrap:"wrap",alignItems:"center",gap:r.space.xs},children:[(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:n.rateUp,size:"sm",leftIcon:"like",variant:"Up"===e?"soft":"ghost",accessibilityState:{selected:"Up"===e,disabled:l},"aria-selected":"Up"===e,"aria-disabled":l,disabled:l,onPress:()=>{save("Up")},testID:`${s}-up`}),(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:n.rateDown,size:"sm",leftIcon:"dislike",variant:"Down"===e?"soft":"ghost",accessibilityState:{selected:"Down"===e,disabled:l},"aria-selected":"Down"===e,"aria-disabled":l,disabled:l,onPress:()=>{save("Down")},testID:`${s}-down`}),b&&!c&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:"secondary",accessibilityLiveRegion:"polite",children:n.rated})]}),""!==x&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:x}),c&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{gap:r.space.sm},children:[(0,_jsxRuntime.jsx)(_mobileUi.Input,{label:n.ratingNote,helperText:n.ratingNoteHint,multiline:!0,maxLength:i,value:u,onChangeText:m,testID:`${s}-note`}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flexDirection:"row",gap:r.space.sm},children:[(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:n.ratingNoteSend,size:"sm",loading:l,disabled:l,onPress:()=>{save("Down",u)},testID:`${s}-note-send`}),(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:n.ratingNoteSkip,size:"sm",variant:"outline",disabled:l,onPress:()=>{d(!1),p(!0)},testID:`${s}-note-skip`})]})]})]})};exports.ReplyRating=ReplyRating;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"ActionCard",{enumerable:!0,get:function(){return _ActionCard.ActionCard}}),Object.defineProperty(exports,"ChatApiError",{enumerable:!0,get:function(){return _client.ChatApiError}}),Object.defineProperty(exports,"ChatComposer",{enumerable:!0,get:function(){return _ChatComposer.ChatComposer}}),Object.defineProperty(exports,"ChatConversationList",{enumerable:!0,get:function(){return _ChatConversationList.ChatConversationList}}),Object.defineProperty(exports,"ChatLauncher",{enumerable:!0,get:function(){return _ChatLauncher.ChatLauncher}}),Object.defineProperty(exports,"ChatMarkdown",{enumerable:!0,get:function(){return _ChatMarkdown.ChatMarkdown}}),Object.defineProperty(exports,"ChatMessage",{enumerable:!0,get:function(){return _ChatMessage.ChatMessage}}),Object.defineProperty(exports,"ChatScreen",{enumerable:!0,get:function(){return _ChatScreen.ChatScreen}}),Object.defineProperty(exports,"ChatThread",{enumerable:!0,get:function(){return _ChatThread.ChatThread}}),Object.defineProperty(exports,"DEFAULT_CHAT_LABELS",{enumerable:!0,get:function(){return _labels.DEFAULT_CHAT_LABELS}}),Object.defineProperty(exports,"ReplyRating",{enumerable:!0,get:function(){return _ReplyRating.ReplyRating}}),Object.defineProperty(exports,"createChatClient",{enumerable:!0,get:function(){return _client.createChatClient}}),Object.defineProperty(exports,"createSseParser",{enumerable:!0,get:function(){return _sse.createSseParser}}),Object.defineProperty(exports,"useChat",{enumerable:!0,get:function(){return _useChat.useChat}});var _client=require("./client.js"),_ActionCard=require("./components/ActionCard.js"),_ChatComposer=require("./components/ChatComposer.js"),_ChatConversationList=require("./components/ChatConversationList.js"),_ChatLauncher=require("./components/ChatLauncher.js"),_ChatMarkdown=require("./components/ChatMarkdown.js"),_ChatMessage=require("./components/ChatMessage.js"),_ChatScreen=require("./components/ChatScreen.js"),_ChatThread=require("./components/ChatThread.js"),_ReplyRating=require("./components/ReplyRating.js"),_labels=require("./labels.js"),_sse=require("./sse.js"),_useChat=require("./useChat.js");
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"ActionCard",{enumerable:!0,get:function(){return _ActionCard.ActionCard}}),Object.defineProperty(exports,"ChatApiError",{enumerable:!0,get:function(){return _chat.ChatApiError}}),Object.defineProperty(exports,"ChatComposer",{enumerable:!0,get:function(){return _ChatComposer.ChatComposer}}),Object.defineProperty(exports,"ChatConversationList",{enumerable:!0,get:function(){return _ChatConversationList.ChatConversationList}}),Object.defineProperty(exports,"ChatLauncher",{enumerable:!0,get:function(){return _ChatLauncher.ChatLauncher}}),Object.defineProperty(exports,"ChatMarkdown",{enumerable:!0,get:function(){return _ChatMarkdown.ChatMarkdown}}),Object.defineProperty(exports,"ChatMessage",{enumerable:!0,get:function(){return _ChatMessage.ChatMessage}}),Object.defineProperty(exports,"ChatScreen",{enumerable:!0,get:function(){return _ChatScreen.ChatScreen}}),Object.defineProperty(exports,"ChatThread",{enumerable:!0,get:function(){return _ChatThread.ChatThread}}),Object.defineProperty(exports,"DEFAULT_CHAT_LABELS",{enumerable:!0,get:function(){return _chat.DEFAULT_CHAT_LABELS}}),Object.defineProperty(exports,"ReplyRating",{enumerable:!0,get:function(){return _ReplyRating.ReplyRating}}),Object.defineProperty(exports,"createChatClient",{enumerable:!0,get:function(){return _chat.createChatClient}}),Object.defineProperty(exports,"createChatSession",{enumerable:!0,get:function(){return _chat.createChatSession}}),Object.defineProperty(exports,"createConversationList",{enumerable:!0,get:function(){return _chat.createConversationList}}),Object.defineProperty(exports,"createSseParser",{enumerable:!0,get:function(){return _chat.createSseParser}}),Object.defineProperty(exports,"useChat",{enumerable:!0,get:function(){return _useChat.useChat}});var _chat=require("@webority/markdown-core/chat"),_ActionCard=require("./components/ActionCard.js"),_ChatComposer=require("./components/ChatComposer.js"),_ChatConversationList=require("./components/ChatConversationList.js"),_ChatLauncher=require("./components/ChatLauncher.js"),_ChatMarkdown=require("./components/ChatMarkdown.js"),_ChatMessage=require("./components/ChatMessage.js"),_ChatScreen=require("./components/ChatScreen.js"),_ChatThread=require("./components/ChatThread.js"),_ReplyRating=require("./components/ReplyRating.js"),_useChat=require("./useChat.js");
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.useChat=void 0;var _react=require("react");const toError=e=>{const t=e;return{code:"string"==typeof t?.code&&t.code?t.code:"unknown",message:"string"==typeof t?.message&&t.message?t.message:"Something went wrong. Please try again.",resetsAtUtc:"string"==typeof t?.resetsAtUtc?t.resetsAtUtc:null}},parseActions=e=>{if(!e)return[];const t=JSON.parse(e);return Array.isArray(t)?t:[]},emptyTurn=(e,t)=>({id:e,question:t,answer:"",streaming:!1,error:null,actions:[],messageId:null,rating:null,ratingNote:null}),turnsFromConversation=e=>{const t=[];for(const r of e??[]){if("User"===r.role){t.push(emptyTurn(r.publicId,r.content));continue}const e=t[t.length-1],n={answer:r.content,actions:parseActions(r.actionsJson),messageId:r.publicId,rating:r.rating??null,ratingNote:r.ratingNote??null};e&&null===e.messageId&&""===e.answer?Object.assign(e,n):t.push({...emptyTurn(r.publicId,""),...n})}return t},useChat=({client:e,pageContext:t})=>{const[r,n]=(0,_react.useState)([]),[a,s]=(0,_react.useState)(null),[c,u]=(0,_react.useState)(null),[o,l]=(0,_react.useState)(!1),[i,g]=(0,_react.useState)(null),d=(0,_react.useRef)(null),m=(0,_react.useRef)(0),f=(0,_react.useRef)(0),p=(0,_react.useRef)(t);p.current=t;const y=(0,_react.useRef)(null);y.current=a;const _=(0,_react.useRef)(r);_.current=r;const w=(0,_react.useRef)(new Map),C=(0,_react.useRef)(0),b=(0,_react.useRef)(!1),h=(0,_react.useCallback)(()=>{const e=w.current;0!==e.size&&(w.current=new Map,n(t=>t.map(t=>e.has(t.id)?{...t,answer:t.answer+(e.get(t.id)??"")}:t)))},[]),I=(0,_react.useCallback)((e,t)=>{w.current.set(e,(w.current.get(e)??"")+t),b.current||(b.current=!0,C.current=requestAnimationFrame(()=>{b.current=!1,h()}))},[h]),v=(0,_react.useCallback)(()=>{cancelAnimationFrame(C.current),b.current=!1,w.current=new Map},[]),A=(0,_react.useCallback)(()=>{m.current+=1,d.current?.abort(),d.current=null,v()},[v]);(0,_react.useEffect)(()=>A,[A]);const k=(0,_react.useCallback)((e,t)=>{n(r=>r.map(r=>r.id===e?{...r,..."function"==typeof t?t(r):t}:r))},[]),R=(0,_react.useCallback)(async t=>{const r="string"==typeof t?t.trim():"";if(!r||d.current)return;const a=m.current,c=new AbortController;d.current=c,f.current+=1;const o=`turn-${f.current}`;n(e=>[...e,{...emptyTurn(o,r),streaming:!0}]);const live=()=>a===m.current&&!c.signal.aborted;try{const t=await e.sendMessage({message:r,conversationId:y.current,pageContext:p.current},{signal:c.signal,onEvent:(e,t)=>{if(!live())return;const r=t;"delta"===e?I(o,r?.text??""):"reset"===e?(w.current.delete(o),k(o,{answer:""})):(h(),"actions"===e&&k(o,{actions:Array.isArray(r?.actions)?r.actions:[]}))}});if(!live())return;h(),k(o,{answer:t.reply,messageId:t.messageId??null,streaming:!1}),y.current=t.conversationId,s(t.conversationId),u(t.messagesLeftToday??null)}catch(e){if(!live())return;const t=toError(e);w.current.delete(o),k(o,{answer:"",actions:[],streaming:!1,error:t}),"daily_limit"===t.code&&u(0),"conversation_not_found"===t.code&&(y.current=null,s(null))}finally{d.current===c&&(d.current=null)}},[e,k,h,I]),E=(0,_react.useCallback)(async t=>{A();const r=m.current;n([]),s(null),g(null),l(!0);try{const a=await e.getConversation(t);if(r!==m.current)return;n(turnsFromConversation(a.messages)),s(a.publicId)}catch(e){if(r!==m.current)return;g(toError(e))}finally{r===m.current&&l(!1)}},[A,e]),N=(0,_react.useCallback)(()=>{A(),n([]),s(null),g(null),l(!1)},[A]),S=(0,_react.useCallback)(()=>{A(),n([]),s(null),u(null),g(null),l(!1)},[A]),T=(0,_react.useCallback)(async()=>{const t=m.current,r=await e.getAllowance();t===m.current&&u(r?.messagesLeftToday??null)},[e]),x=(0,_react.useCallback)(async(t,r,n)=>{const a=_.current.find(e=>e.id===t),s=y.current;if(!a?.messageId||!s)throw new Error("Only a stored reply can be rated.");const c={rating:a.rating,ratingNote:a.ratingNote},u="string"==typeof n&&n.trim()?n.trim():null;k(t,{rating:r,ratingNote:u});try{await e.rateMessage(s,a.messageId,{rating:r,note:u})}catch(e){throw k(t,c),e}},[e,k]);return{turns:r,conversationId:a,messagesLeftToday:c,streaming:r.some(e=>e.streaming),loading:o,loadError:i,submit:R,openConversation:E,newConversation:N,rate:x,refreshAllowance:T,reset:S}};exports.useChat=useChat;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.useChat=void 0;var _chat=require("@webority/markdown-core/chat"),_react=require("react");const requestFrame=e=>{const t=requestAnimationFrame(e);return()=>cancelAnimationFrame(t)},useChat=({client:e,pageContext:t})=>{const r=(0,_react.useRef)(t);r.current=t;const a=(0,_react.useMemo)(()=>(0,_chat.createChatSession)({client:e,pageContext:()=>r.current,schedule:requestFrame}),[e]);(0,_react.useEffect)(()=>()=>a.dispose(),[a]);return{...(0,_react.useSyncExternalStore)(a.subscribe,a.getState),...(0,_react.useMemo)(()=>({submit:e=>a.submit(e),stop:()=>a.stop(),retry:e=>a.retry(e),regenerate:e=>a.regenerate(e),startEdit:e=>a.startEdit(e),cancelEdit:()=>a.cancelEdit(),attach:e=>a.attach(e),removeAttachment:e=>a.removeAttachment(e),openConversation:e=>a.openConversation(e),newConversation:()=>a.newConversation(),rate:(e,t,r)=>a.rate(e,t,r),refreshAllowance:()=>a.refreshAllowance(),reset:()=>a.reset()}),[a]),client:a.client}};exports.useChat=useChat;
@@ -1 +1 @@
1
- "use strict";import{Banner,Button,Card,Text,useTheme}from"@webority/mobile-ui";import{useState}from"react";import{View}from"react-native";import{mergeLabels}from"../labels.js";import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";const titleOf=(e,t)=>"Reply"===e.kind?t.actionReply(e.ticketNumber??""):"Reopen"===e.kind?t.actionReopen(e.ticketNumber??""):t.actionRaiseTicket,doneText=(e,t,i)=>"Reply"===e.kind?i.actionDoneReply(t):"Reopen"===e.kind?i.actionDoneReopen(t):i.actionDoneRaiseTicket(t);export const ActionCard=({action:e,confirmAction:t,onViewTicket:i,labels:n,testID:s="chat-action"})=>{const a=mergeLabels(n),o=useTheme(),[r,c]=useState("ready"),[l,d]=useState(null),[m,x]=useState("");if("dismissed"===r)return _jsx(Text,{variant:"bodySmall",color:"secondary",testID:s,children:a.actionDismissed});if("done"===r&&l)return _jsx(Banner,{tone:"success",message:doneText(e,l.number,a),actions:i?[{label:a.viewTicket,onPress:()=>i(l)}]:void 0,testID:s});const p="sending"===r,y=new Date(e.expiresDateTimeUtc).getTime()<=Date.now(),b="RaiseTicket"===e.kind?[e.category,e.subject].filter(Boolean).join(", "):"";return _jsx(Card,{variant:"outline",padding:"sm",testID:s,children:_jsxs(View,{style:{gap:o.space.sm},children:[_jsx(Text,{variant:"label",children:titleOf(e,a)}),""!==b&&_jsx(Text,{variant:"bodySmall",color:"secondary",children:b}),"Reopen"!==e.kind&&e.body?_jsx(Text,{variant:"bodySmall",children:e.body}):null,y?_jsx(Text,{variant:"bodySmall",color:"secondary",children:a.actionExpired}):_jsxs(_Fragment,{children:[_jsx(Text,{variant:"caption",color:"secondary",children:a.actionNote}),""!==m&&_jsx(Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:m}),_jsxs(View,{style:{flexDirection:"row",flexWrap:"wrap",gap:o.space.sm},children:[_jsx(Button,{label:a.actionConfirm,size:"sm",loading:p,disabled:p,onPress:()=>{(async()=>{c("sending"),x("");try{d(await t(e.token)),c("done")}catch(e){const t=e?.message;x("string"==typeof t&&t?t:a.actionFailed),c("ready")}})()},testID:`${s}-confirm`}),_jsx(Button,{label:a.actionDismiss,size:"sm",variant:"outline",disabled:p,onPress:()=>c("dismissed"),testID:`${s}-dismiss`})]})]})]})})};
1
+ "use strict";import{mergeLabels}from"@webority/markdown-core/chat";import{Banner,Button,Card,Text,useTheme}from"@webority/mobile-ui";import{useState}from"react";import{View}from"react-native";import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";const titleOf=(e,t)=>"Reply"===e.kind?t.actionReply(e.ticketNumber??""):"Reopen"===e.kind?t.actionReopen(e.ticketNumber??""):t.actionRaiseTicket,doneText=(e,t,i)=>"Reply"===e.kind?i.actionDoneReply(t):"Reopen"===e.kind?i.actionDoneReopen(t):i.actionDoneRaiseTicket(t);export const ActionCard=({action:e,confirmAction:t,onViewTicket:i,labels:n,testID:s="chat-action"})=>{const a=mergeLabels(n),o=useTheme(),[r,c]=useState("ready"),[l,d]=useState(null),[m,x]=useState("");if("dismissed"===r)return _jsx(Text,{variant:"bodySmall",color:"secondary",testID:s,children:a.actionDismissed});if("done"===r&&l)return _jsx(Banner,{tone:"success",message:doneText(e,l.number,a),actions:i?[{label:a.viewTicket,onPress:()=>i(l)}]:void 0,testID:s});const p="sending"===r,y=new Date(e.expiresDateTimeUtc).getTime()<=Date.now(),b="RaiseTicket"===e.kind?[e.category,e.subject].filter(Boolean).join(", "):"";return _jsx(Card,{variant:"outline",padding:"sm",testID:s,children:_jsxs(View,{style:{gap:o.space.sm},children:[_jsx(Text,{variant:"label",children:titleOf(e,a)}),""!==b&&_jsx(Text,{variant:"bodySmall",color:"secondary",children:b}),"Reopen"!==e.kind&&e.body?_jsx(Text,{variant:"bodySmall",children:e.body}):null,y?_jsx(Text,{variant:"bodySmall",color:"secondary",children:a.actionExpired}):_jsxs(_Fragment,{children:[_jsx(Text,{variant:"caption",color:"secondary",children:a.actionNote}),""!==m&&_jsx(Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:m}),_jsxs(View,{style:{flexDirection:"row",flexWrap:"wrap",gap:o.space.sm},children:[_jsx(Button,{label:a.actionConfirm,size:"sm",loading:p,disabled:p,onPress:()=>{(async()=>{c("sending"),x("");try{d(await t(e.token)),c("done")}catch(e){const t=e?.message;x("string"==typeof t&&t?t:a.actionFailed),c("ready")}})()},testID:`${s}-confirm`}),_jsx(Button,{label:a.actionDismiss,size:"sm",variant:"outline",disabled:p,onPress:()=>c("dismissed"),testID:`${s}-dismiss`})]})]})]})})};
@@ -1 +1 @@
1
- "use strict";import{Composer}from"@webority/mobile-ui";import{mergeLabels}from"../labels.js";import{jsx as _jsx}from"react/jsx-runtime";export const ChatComposer=({onSubmit:e,busy:o=!1,disabled:s=!1,maxLength:a=4e3,above:r,below:t,keyboardAware:b,keyboardOffset:l,safeArea:m,labels:i,testID:d="chat-composer"})=>{const n=mergeLabels(i);return _jsx(Composer,{onSend:e,loading:o,disabled:s,maxLength:a,placeholder:n.placeholder,accessibilityLabel:n.composer,labels:{send:n.send},above:r,below:t,keyboardAware:b,keyboardOffset:l,safeArea:m,testID:d})};
1
+ "use strict";import{mergeLabels}from"@webority/markdown-core/chat";import{Banner,Composer,IconButton}from"@webority/mobile-ui";import{useEffect,useState}from"react";import{ComposerAttachments}from"./ComposerAttachments.js";import{jsx as _jsx,Fragment as _Fragment,jsxs as _jsxs}from"react/jsx-runtime";export const ChatComposer=({onSubmit:e,busy:t=!1,onStop:s,disabled:a=!1,maxLength:o=4e3,above:n,below:r,keyboardAware:i,keyboardOffset:c,safeArea:m,attachments:l=[],onAttach:d,onRemoveAttachment:b,editing:p,onCancelEdit:h,labels:u,testID:g="chat-composer"})=>{const f=mergeLabels(u),x=l.some(e=>"Uploading"===e.status),y=l.some(e=>"Ready"===e.status),[j,v]=useState("");useEffect(()=>{v(p?p.text:"")},[p]);const A=p?_jsx(Banner,{message:f.editing,accessibilityRole:"summary",actions:h?[{label:f.cancel,onPress:h,testID:`${g}-cancel-edit`}]:void 0,testID:`${g}-editing`}):null,C=l.length>0?_jsx(ComposerAttachments,{attachments:l,onRemove:b,labels:u,testID:`${g}-attachments`}):null,_=A||C||n?_jsxs(_Fragment,{children:[A,C,n]}):void 0,I=d?_jsx(IconButton,{icon:"paperclip",accessibilityLabel:f.attach,variant:"ghost",tone:"neutral",disabled:a||t,onPress:d,testID:`${g}-attach`}):void 0;return _jsx(Composer,{onSend:e,value:j,onChangeText:v,loading:t,onStop:s,stopLabel:f.stop,disabled:a,maxLength:o,canSend:!x&&(!!y||void 0),placeholder:f.placeholder,accessibilityLabel:f.composer,labels:{send:f.send},leading:I,above:_,below:r,keyboardAware:i,keyboardOffset:c,safeArea:m,testID:g})};
@@ -1 +1 @@
1
- "use strict";import{formatDateTime}from"@webority/mobile-core";import{Banner,Button,Card,Dialog,EmptyState,IconButton,Skeleton,Text,useTheme}from"@webority/mobile-ui";import{useCallback,useEffect,useState}from"react";import{RefreshControl,ScrollView,View}from"react-native";import{mergeLabels}from"../labels.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const messageOf=(e,t)=>{const s=e?.message;return"string"==typeof s&&s?s:t};export const ChatConversationList=({client:e,onOpen:t,onDeleted:s,pageSize:n=20,labels:i,style:a,testID:l="chat-conversations"})=>{const o=mergeLabels(i),r=useTheme(),[c,m]=useState([]),[d,u]=useState(!0),[p,f]=useState(!1),[g,b]=useState(""),[h,x]=useState(!1),[y,j]=useState(null),[S,I]=useState(!1),[_,C]=useState(""),v=o.loadFailed,D=useCallback(async t=>{u(!0),b("");try{const s=await e.listConversations({skip:t,take:n});m(e=>0===t?s:[...e,...s]),x(s.length===n)}catch(e){b(messageOf(e,v))}finally{u(!1)}},[e,n,v]);useEffect(()=>{D(0)},[D]);const w=!d&&""===g&&0===c.length;return _jsxs(ScrollView,{style:a,contentContainerStyle:{padding:r.space.md,gap:r.space.sm,flexGrow:1},refreshControl:_jsx(RefreshControl,{refreshing:p,onRefresh:()=>{(async()=>{f(!0),await D(0),f(!1)})()}}),accessibilityLabel:o.conversations,testID:l,children:[""!==g&&_jsx(Banner,{tone:"danger",message:g,actions:[{label:o.retry,onPress:()=>{D(0)}}],testID:`${l}-error`}),w&&_jsx(EmptyState,{size:"sm",title:o.conversationsEmptyTitle,description:o.conversationsEmptyText,testID:`${l}-empty`}),c.map(e=>_jsx(Card,{variant:"outline",padding:"sm",onPress:()=>t(e),accessibilityLabel:e.title||o.untitled,testID:`${l}-item-${e.publicId}`,children:_jsxs(View,{style:{flexDirection:"row",alignItems:"center",gap:r.space.sm},children:[_jsxs(View,{style:{flex:1,minWidth:0},children:[_jsx(Text,{variant:"label",numberOfLines:1,children:e.title||o.untitled}),_jsx(Text,{variant:"caption",color:"secondary",children:formatDateTime(e.lastMessageDateTimeUtc)})]}),_jsx(IconButton,{icon:"trash",tone:"danger",variant:"ghost",accessibilityLabel:o.deleteConversation,onPress:()=>{C(""),j(e)},testID:`${l}-delete-${e.publicId}`})]})},e.publicId)),d&&!p&&_jsxs(View,{style:{gap:r.space.sm},accessibilityElementsHidden:!0,children:[_jsx(Skeleton,{height:56}),_jsx(Skeleton,{height:56}),_jsx(Skeleton,{height:56})]}),!d&&h&&_jsx(Button,{label:o.loadMore,variant:"outline",onPress:()=>{D(c.length)},testID:`${l}-more`}),_jsx(Dialog,{visible:null!==y,onClose:()=>{S||j(null)},tone:"warning",title:o.deleteConfirmTitle,message:_||o.deleteConfirmMessage,dismissOnAction:!1,actions:[{label:o.cancel,tone:"neutral",disabled:S,onPress:()=>j(null)},{label:o.deleteConfirm,tone:"danger",loading:S,onPress:()=>{(async()=>{if(y){I(!0),C("");try{await e.deleteConversation(y.publicId),m(e=>e.filter(e=>e.publicId!==y.publicId)),s?.(y.publicId),j(null)}catch(e){C(messageOf(e,o.deleteFailed))}finally{I(!1)}}})()}}],testID:`${l}-confirm`})]})};
1
+ "use strict";import{createConversationList,mergeLabels}from"@webority/markdown-core/chat";import{formatDateTime}from"@webority/mobile-core";import{Banner,Button,Card,Dialog,EmptyState,IconButton,Input,Skeleton,Text,useTheme}from"@webority/mobile-ui";import{useEffect,useState,useSyncExternalStore}from"react";import{RefreshControl,ScrollView,View}from"react-native";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const messageOf=(e,t)=>{const s=e?.message;return"string"==typeof s&&s?s:t},IDLE_STATE={items:[],totalCount:null,loading:!0,error:null,hasMore:!1},IDLE={getState:()=>IDLE_STATE,subscribe:()=>()=>{}};export const ChatConversationList=({client:e,onOpen:t,onDeleted:s,pageSize:n=20,labels:a,style:i,testID:l="chat-conversations"})=>{const r=mergeLabels(a),o=useTheme(),[c,m]=useState(null),d=c??IDLE,{items:u,loading:g,error:b,hasMore:p}=useSyncExternalStore(d.subscribe,d.getState),[x,h]=useState(!1),[f,S]=useState(null),[y,I]=useState(!1),[j,v]=useState(""),[D,_]=useState(null),[C,T]=useState(""),[E,w]=useState(!1),[L,$]=useState(""),[P,O]=useState(void 0),[B,M]=useState("");useEffect(()=>{const t=createConversationList({client:e,pageSize:n});return m(t),t.load(),()=>t.dispose()},[e,n]),useEffect(()=>{let t=!0;return e.getSettings().then(e=>{t&&O(e.titleMaxLength)},e=>{t&&M(messageOf(e,r.renameFailed))}),()=>{t=!1}},[e,r.renameFailed]);const V=C.trim(),save=async()=>{if(D&&""!==V){w(!0),$("");try{await(c?.rename(D.publicId,V)),_(null)}catch(e){$(messageOf(e,r.renameFailed))}finally{w(!1)}}},k=!g&&!b&&0===u.length;return _jsxs(ScrollView,{style:i,contentContainerStyle:{padding:o.space.md,gap:o.space.sm,flexGrow:1},refreshControl:_jsx(RefreshControl,{refreshing:x,onRefresh:()=>{(async()=>{h(!0),await(c?.load()),h(!1)})()}}),accessibilityLabel:r.conversations,testID:l,children:[b&&_jsx(Banner,{tone:"danger",message:b.message||r.loadFailed,actions:[{label:r.retry,onPress:()=>{c?.load()}}],testID:`${l}-error`}),k&&_jsx(EmptyState,{size:"sm",title:r.conversationsEmptyTitle,description:r.conversationsEmptyText,testID:`${l}-empty`}),u.map(e=>_jsx(Card,{variant:"outline",padding:"sm",onPress:()=>t(e),accessibilityLabel:e.title||r.untitled,testID:`${l}-item-${e.publicId}`,children:_jsxs(View,{style:{flexDirection:"row",alignItems:"center",gap:o.space.sm},children:[_jsxs(View,{style:{flex:1,minWidth:0},children:[_jsx(Text,{variant:"label",numberOfLines:1,children:e.title||r.untitled}),_jsx(Text,{variant:"caption",color:"secondary",children:formatDateTime(e.lastMessageDateTimeUtc)})]}),_jsx(IconButton,{icon:"edit",variant:"ghost",accessibilityLabel:r.renameConversation,onPress:()=>{$(""),T(e.title??""),_(e)},testID:`${l}-rename-${e.publicId}`}),_jsx(IconButton,{icon:"trash",tone:"danger",variant:"ghost",accessibilityLabel:r.deleteConversation,onPress:()=>{v(""),S(e)},testID:`${l}-delete-${e.publicId}`})]})},e.publicId)),g&&!x&&_jsxs(View,{style:{gap:o.space.sm},accessibilityElementsHidden:!0,children:[_jsx(Skeleton,{height:56}),_jsx(Skeleton,{height:56}),_jsx(Skeleton,{height:56})]}),!g&&p&&_jsx(Button,{label:r.loadMore,variant:"outline",onPress:()=>{c?.loadMore()},testID:`${l}-more`}),_jsxs(Dialog,{visible:null!==D,onClose:()=>{E||_(null)},title:r.renameConversation,dismissOnAction:!1,actions:[{label:r.cancel,tone:"neutral",disabled:E,onPress:()=>_(null)},{label:r.renameSave,disabled:""===V||E,loading:E,onPress:()=>{save()}}],testID:`${l}-rename`,children:[_jsx(Input,{label:r.conversationTitle,value:C,onChangeText:T,maxLength:P,returnKeyType:"done",onSubmitEditing:()=>{save()},testID:`${l}-rename-input`}),""!==(L||B)&&_jsx(Text,{variant:"caption",color:"danger",testID:`${l}-rename-error`,children:L||B})]}),_jsx(Dialog,{visible:null!==f,onClose:()=>{y||S(null)},tone:"warning",title:r.deleteConfirmTitle,message:j||r.deleteConfirmMessage,dismissOnAction:!1,actions:[{label:r.cancel,tone:"neutral",disabled:y,onPress:()=>S(null)},{label:r.deleteConfirm,tone:"danger",loading:y,onPress:()=>{(async()=>{if(f){I(!0),v("");try{await(c?.remove(f.publicId)),s?.(f.publicId),S(null)}catch(e){v(messageOf(e,r.deleteFailed))}finally{I(!1)}}})()}}],testID:`${l}-confirm`})]})};
@@ -1 +1 @@
1
- "use strict";import{FloatingActionButton}from"@webority/mobile-ui";import{mergeLabels}from"../labels.js";import{jsx as _jsx}from"react/jsx-runtime";export const ChatLauncher=({onPress:t,position:o="end",bottomOffset:e,compact:s=!1,labels:i,testID:n="chat-launcher"})=>{const r=mergeLabels(i);return _jsx(FloatingActionButton,{icon:"messages",label:s?void 0:r.launcher,accessibilityLabel:r.launcher,position:"end"===o?"bottomRight":"bottomLeft",bottomOffset:e,onPress:t,testID:n})};
1
+ "use strict";import{mergeLabels}from"@webority/markdown-core/chat";import{FloatingActionButton}from"@webority/mobile-ui";import{jsx as _jsx}from"react/jsx-runtime";export const ChatLauncher=({onPress:t,position:o="end",bottomOffset:e,compact:s=!1,labels:r,testID:i="chat-launcher"})=>{const n=mergeLabels(r);return _jsx(FloatingActionButton,{icon:"messages",label:s?void 0:n.launcher,accessibilityLabel:n.launcher,position:"end"===o?"bottomRight":"bottomLeft",bottomOffset:e,onPress:t,testID:i})};
@@ -1 +1 @@
1
- "use strict";import{Markdown}from"@webority/mobile-ui";import{jsx as _jsx}from"react/jsx-runtime";export function ChatMarkdown({text:e,resolveLink:r,onLinkPress:t,testID:s}){return _jsx(Markdown,{links:"app",headings:"text",resolveLink:r,onAppLinkPress:t,testID:s,children:e})}
1
+ "use strict";import{Markdown}from"@webority/mobile-ui";import{jsx as _jsx}from"react/jsx-runtime";export function ChatMarkdown({text:t,resolveLink:i,onLinkPress:n,isCitation:e,onOpenCitation:o,testID:r}){return _jsx(Markdown,{links:"app",headings:"text",resolveLink:i,onAppLinkPress:n,isCitation:e,onOpenCitation:o,testID:r,children:t})}
@@ -1 +1 @@
1
- "use strict";import{markdownToPlainText}from"@webority/markdown-core";import{MessageBubble,Text,TypingIndicator,useTheme}from"@webority/mobile-ui";import{memo,useMemo}from"react";import{View}from"react-native";import{mergeLabels}from"../labels.js";import{ActionCard}from"./ActionCard.js";import{ChatMarkdown}from"./ChatMarkdown.js";import{ReplyRating}from"./ReplyRating.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";function ChatMessageView({turn:e,onRate:s,resolveLink:t,onLinkPress:r,confirmAction:i,onViewTicket:a,renderReply:n,labels:o,testID:m="chat-message"}){const l=mergeLabels(o),g=useTheme(),c=e.streaming&&!e.answer,u=useMemo(()=>e.streaming?e.answer:markdownToPlainText(e.answer),[e.streaming,e.answer]),d=useMemo(()=>({you:l.you}),[l.you]);return _jsxs(View,{style:{gap:g.space.sm},testID:m,children:[""!==e.question&&_jsx(MessageBubble,{side:"mine",text:e.question,labels:d,testID:`${m}-question`}),c?_jsx(TypingIndicator,{label:l.thinking,testID:`${m}-thinking`}):null,""!==e.answer?_jsx(MessageBubble,{side:"theirs",author:l.assistant,text:u,streaming:e.streaming,testID:`${m}-answer`,children:n?n(e,{streaming:e.streaming}):_jsx(ChatMarkdown,{text:e.answer,resolveLink:t,onLinkPress:r})}):null,e.error&&_jsx(Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:e.error.message}),i&&!e.streaming&&e.actions.map(e=>_jsx(ActionCard,{action:e,confirmAction:i,onViewTicket:a,labels:o},e.token)),s&&e.messageId&&!e.streaming&&_jsx(ReplyRating,{rating:e.rating,onRate:(t,r)=>s(e.id,t,r),labels:o})]})}export const ChatMessage=memo(ChatMessageView);
1
+ "use strict";import{markdownToPlainText}from"@webority/markdown-core";import{mergeLabels}from"@webority/markdown-core/chat";import{copyText}from"@webority/mobile-core/clipboard";import{Button,Chip,MessageBubble,Text,TypingIndicator,useTheme}from"@webority/mobile-ui";import{memo,useEffect,useMemo,useRef,useState}from"react";import{View}from"react-native";import{ActionCard}from"./ActionCard.js";import{ChatMarkdown}from"./ChatMarkdown.js";import{ReplyRating}from"./ReplyRating.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";function ChatMessageView({turn:e,canRegenerate:t=!1,onRetry:s,onRegenerate:n,onEdit:i,onOpenAttachment:a,onRate:r,resolveLink:o,onLinkPress:l,isCitation:c,onOpenCitation:m,onAskSuggestion:p,confirmAction:u,onViewTicket:g,renderReply:d,labels:x,testID:w="chat-message"}){const y=mergeLabels(x),b=useTheme(),[h,j]=useState(!1),f=useRef(null);useEffect(()=>()=>{null!==f.current&&clearTimeout(f.current)},[]);const T=e.streaming&&!e.answer,k=useMemo(()=>e.streaming?e.answer:markdownToPlainText(e.answer),[e.streaming,e.answer]),_=useMemo(()=>({you:y.you}),[y.you]),I=!e.streaming&&(e.stopped||null!==e.error),R=!e.streaming&&null!==e.questionId,C=e.attachments.length>0||e.stopped||s&&I||i&&R?_jsxs(View,{style:{gap:b.space.xs},children:[e.attachments.length>0?_jsx(View,{style:{flexDirection:"row",flexWrap:"wrap",gap:b.space.xs},children:e.attachments.map(e=>_jsx(Chip,{label:e.fileName,onPress:a?()=>a(e):void 0,testID:`${w}-attachment-${e.publicId}`},e.publicId))}):null,e.stopped?_jsx(Text,{variant:"bodySmall",color:"secondary",accessibilityLiveRegion:"polite",testID:`${w}-stopped`,children:y.stopped}):null,s&&I||i&&R?_jsxs(View,{style:{flexDirection:"row",flexWrap:"wrap",gap:b.space.xs},children:[s&&I?_jsx(Button,{label:y.retry,variant:"link",size:"sm",onPress:()=>s(e.id),testID:`${w}-retry`}):null,i&&R?_jsx(Button,{label:y.edit,variant:"link",size:"sm",onPress:()=>i(e.id),testID:`${w}-edit`}):null]}):null]}):null;return _jsxs(View,{style:{gap:b.space.sm},testID:w,children:[""!==e.question&&_jsx(MessageBubble,{side:"mine",text:e.question,labels:_,footer:C,testID:`${w}-question`}),T?_jsx(TypingIndicator,{label:y.thinking,testID:`${w}-thinking`}):null,""!==e.answer?_jsx(MessageBubble,{side:"theirs",author:y.assistant,text:k,streaming:e.streaming,onCopy:()=>{copyText(markdownToPlainText(e.answer))},testID:`${w}-answer`,children:d?d(e,{streaming:e.streaming}):_jsx(ChatMarkdown,{text:e.answer,resolveLink:o,onLinkPress:l,isCitation:c,onOpenCitation:m})}):null,e.streaming&&e.step?_jsx(Text,{variant:"caption",color:"secondary",accessibilityLiveRegion:"polite",testID:`${w}-step`,children:y.toolStep(e.step)}):null,e.streaming||""===e.answer?null:_jsx(Button,{label:h?y.copied:y.copy,variant:"link",size:"sm",onPress:()=>{(async()=>{await copyText(markdownToPlainText(e.answer))&&(j(!0),null!==f.current&&clearTimeout(f.current),f.current=setTimeout(()=>j(!1),2e3))})()},testID:`${w}-copy`}),p&&!e.streaming&&e.suggestions.length>0?_jsx(View,{accessibilityRole:"list",accessibilityLabel:y.suggestions,style:{flexDirection:"row",flexWrap:"wrap",gap:b.space.xs},children:e.suggestions.map((e,t)=>_jsx(Chip,{label:e,onPress:()=>p(e),testID:`${w}-suggestion-${t}`},e))}):null,t&&n&&!e.streaming&&""!==e.answer?_jsx(Button,{label:y.regenerate,variant:"link",size:"sm",onPress:()=>n(e.id),testID:`${w}-regenerate`}):null,e.error&&_jsx(Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:e.error.message}),u&&!e.streaming&&e.actions.map(e=>_jsx(ActionCard,{action:e,confirmAction:u,onViewTicket:g,labels:x},e.token)),r&&e.messageId&&!e.streaming&&_jsx(ReplyRating,{rating:e.rating,onRate:(t,s)=>r(e.id,t,s),labels:x})]})}export const ChatMessage=memo(ChatMessageView);
@@ -1 +1 @@
1
- "use strict";import{Banner,Button,EmptyState,Spinner,Text,useTheme}from"@webority/mobile-ui";import{View}from"react-native";import{mergeLabels}from"../labels.js";import{ChatComposer}from"./ChatComposer.js";import{ChatThread}from"./ChatThread.js";import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";export function ChatScreen({chat:e,title:t,headerActions:s,empty:r,disclaimer:a,maxLength:o=4e3,allowanceThreshold:i=10,rating:n=!0,keyboardOffset:l,testID:m="chat-screen",...d}){const c=mergeLabels(d.labels),h=useTheme(),p=e.messagesLeftToday,x=void 0===a?c.disclaimer:a;return _jsxs(View,{style:{flex:1,backgroundColor:h.colors.bg},testID:m,children:[_jsxs(View,{style:{flexDirection:"row",alignItems:"center",gap:h.space.sm,paddingHorizontal:h.space.md,paddingVertical:h.space.sm,borderBottomWidth:1,borderBottomColor:h.colors["border-subtle"]},children:[_jsx(Text,{variant:"title",accessibilityRole:"header",style:{flex:1},numberOfLines:1,children:t??c.panelTitle}),s,_jsx(Button,{label:c.newChat,size:"sm",variant:"soft",leftIcon:"add",disabled:0===e.turns.length&&!e.loading,onPress:e.newConversation,testID:`${m}-new`})]}),e.loading?_jsx(View,{style:{flex:1,alignItems:"center",justifyContent:"center"},children:_jsx(Spinner,{message:c.loadingConversation,testID:`${m}-loading`})}):_jsx(ChatThread,{turns:e.turns,style:{flex:1},keyboardOffset:l,onRate:n?e.rate:void 0,empty:r??_jsx(EmptyState,{fill:!0,size:"sm",title:c.emptyTitle,description:c.emptyText,testID:`${m}-empty`}),testID:`${m}-thread`,...d}),_jsx(ChatComposer,{onSubmit:t=>{e.submit(t)},busy:e.streaming,disabled:0===p||e.loading,maxLength:o,keyboardOffset:l,labels:d.labels,testID:`${m}-composer`,above:_jsxs(_Fragment,{children:[e.loadError&&_jsx(Banner,{tone:"danger",message:e.loadError.message,testID:`${m}-load-error`}),null!==p&&p<=i&&_jsx(Text,{variant:"caption",color:0===p?"danger":"secondary",accessibilityLiveRegion:"polite",testID:`${m}-allowance`,children:c.allowance(p)})]}),below:x?_jsx(Text,{variant:"caption",color:"tertiary",testID:`${m}-disclaimer`,children:x}):null})]})}
1
+ "use strict";import{mergeLabels}from"@webority/markdown-core/chat";import{Banner,Button,EmptyState,Spinner,Text,useTheme}from"@webority/mobile-ui";import{View}from"react-native";import{ChatComposer}from"./ChatComposer.js";import{ChatThread}from"./ChatThread.js";import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";export function ChatScreen({chat:e,pickAttachments:t,onOpenAttachment:s,title:a,headerActions:r,empty:n,disclaimer:o,maxLength:i=4e3,allowanceThreshold:l=10,rating:m=!0,keyboardOffset:c,testID:d="chat-screen",...g}){const h=mergeLabels(g.labels),p=useTheme(),x=e.messagesLeftToday,b=void 0===o?h.disclaimer:o,y=t&&e.settings?.attachments?async()=>e.attach(await t()):void 0;return _jsxs(View,{style:{flex:1,backgroundColor:p.colors.bg},testID:d,children:[_jsxs(View,{style:{flexDirection:"row",alignItems:"center",gap:p.space.sm,paddingHorizontal:p.space.md,paddingVertical:p.space.sm,borderBottomWidth:1,borderBottomColor:p.colors["border-subtle"]},children:[_jsx(Text,{variant:"title",accessibilityRole:"header",style:{flex:1},numberOfLines:1,children:a??h.panelTitle}),r,_jsx(Button,{label:h.newChat,size:"sm",variant:"soft",leftIcon:"add",disabled:0===e.turns.length&&!e.loading,onPress:e.newConversation,testID:`${d}-new`})]}),e.loading?_jsx(View,{style:{flex:1,alignItems:"center",justifyContent:"center"},children:_jsx(Spinner,{message:h.loadingConversation,testID:`${d}-loading`})}):_jsx(ChatThread,{turns:e.turns,style:{flex:1},keyboardOffset:c,onRate:m?e.rate:void 0,onRetry:e.retry,onRegenerate:e.regenerate,onEdit:e.startEdit,onOpenAttachment:s,empty:n??_jsx(EmptyState,{fill:!0,size:"sm",title:h.emptyTitle,description:h.emptyText,testID:`${d}-empty`}),testID:`${d}-thread`,...g,onAskSuggestion:e.submit}),_jsx(ChatComposer,{onSubmit:t=>{e.submit(t)},busy:e.streaming,onStop:e.stop,disabled:0===x||e.loading,maxLength:i,keyboardOffset:c,labels:g.labels,onAttach:y,attachments:e.attachments,onRemoveAttachment:t=>{e.removeAttachment(t)},editing:e.editing,onCancelEdit:e.cancelEdit,testID:`${d}-composer`,above:_jsxs(_Fragment,{children:[e.loadError&&_jsx(Banner,{tone:"danger",message:e.loadError.message,testID:`${d}-load-error`}),e.settingsError&&_jsx(Banner,{tone:"danger",message:e.settingsError.message,testID:`${d}-settings-error`}),null!==x&&x<=l&&_jsx(Text,{variant:"caption",color:0===x?"danger":"secondary",accessibilityLiveRegion:"polite",testID:`${d}-allowance`,children:h.allowance(x)})]}),below:b?_jsx(Text,{variant:"caption",color:"tertiary",testID:`${d}-disclaimer`,children:b}):null})]})}
@@ -1 +1 @@
1
- "use strict";import{MessageList,useTheme}from"@webority/mobile-ui";import{useMemo}from"react";import{View}from"react-native";import{mergeLabels}from"../labels.js";import{ChatMessage}from"./ChatMessage.js";import{jsx as _jsx}from"react/jsx-runtime";const turnKey=e=>e.id,followTurn=()=>!0,TurnGap=()=>{const e=useTheme();return _jsx(View,{style:{height:e.space.lg}})};export function ChatThread({turns:e,empty:t,keyboardAware:s,keyboardOffset:r,style:a,testID:o="chat-thread",...m}){const i=mergeLabels(m.labels),n=useMemo(()=>[...e].reverse(),[e]);return _jsx(MessageList,{messages:n,keyExtractor:turnKey,renderMessage:({item:e})=>_jsx(ChatMessage,{turn:e,testID:`${o}-${e.id}`,...m}),followNew:followTurn,empty:t,ItemSeparatorComponent:TurnGap,keyboardAware:s,keyboardOffset:r,accessibilityLabel:i.thread,style:a,testID:o})}
1
+ "use strict";import{mergeLabels}from"@webority/markdown-core/chat";import{MessageList,useTheme}from"@webority/mobile-ui";import{useMemo}from"react";import{View}from"react-native";import{ChatMessage}from"./ChatMessage.js";import{jsx as _jsx}from"react/jsx-runtime";const turnKey=e=>e.id,followTurn=()=>!0,TurnGap=()=>{const e=useTheme();return _jsx(View,{style:{height:e.space.lg}})};export function ChatThread({turns:e,empty:t,keyboardAware:r,keyboardOffset:s,onRetry:o,onRegenerate:n,onEdit:a,onOpenAttachment:i,onAskSuggestion:m,style:u,testID:l="chat-thread",...g}){const d=mergeLabels(g.labels),c=useMemo(()=>[...e].reverse(),[e]),h=useMemo(()=>{const t=e[e.length-1];return t&&null!==t.messageId&&!t.streaming?t.id:null},[e]),y=e[e.length-1]?.id;return _jsx(MessageList,{messages:c,keyExtractor:turnKey,renderMessage:({item:e})=>_jsx(ChatMessage,{turn:e,onRetry:o,canRegenerate:e.id===h,onRegenerate:e.id===h?n:void 0,onEdit:a,onOpenAttachment:i,testID:`${l}-${e.id}`,...g,onAskSuggestion:e.id===y?m:void 0}),followNew:followTurn,empty:t,ItemSeparatorComponent:TurnGap,keyboardAware:r,keyboardOffset:s,accessibilityLabel:d.thread,style:u,testID:l})}
@@ -0,0 +1 @@
1
+ "use strict";import{mergeLabels}from"@webority/markdown-core/chat";import{Chip,ProgressBar,Text,useTheme}from"@webority/mobile-ui";import{useMemo}from"react";import{StyleSheet,View}from"react-native";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";export const ComposerAttachments=({attachments:e,onRemove:t,labels:s,testID:r="composer-attachments"})=>{const o=useTheme(),a=useMemo(()=>buildStyles(o),[o]),i=mergeLabels(s),m=useMemo(()=>({remove:i.removeAttachment}),[i.removeAttachment]);return _jsx(View,{style:a.root,testID:r,children:_jsx(View,{style:a.row,children:e.map(e=>_jsxs(View,{style:a.item,children:[_jsx(Chip,{label:e.fileName,variant:"soft",onRemove:t?()=>t(e.key):void 0,labels:m,removeTestID:`chat-attachment-remove-${e.key}`,testID:`${r}-${e.key}`}),"Uploading"===e.status?_jsx(ProgressBar,{progress:e.progress??void 0,label:i.attachmentUploading,height:4,containerStyle:a.progress}):null,"Failed"===e.status?_jsx(Text,{variant:"caption",color:"danger",accessibilityLiveRegion:"polite",children:i.attachmentFailed}):null]},e.key))})})};const buildStyles=e=>StyleSheet.create({root:{gap:e.space.xs},row:{flexDirection:"row",flexWrap:"wrap",gap:e.space.xs},item:{gap:e.space.xxs,maxWidth:"100%"},progress:{minWidth:120}});
@@ -1 +1 @@
1
- "use strict";import{Button,Input,Text,useTheme}from"@webority/mobile-ui";import{useState}from"react";import{View}from"react-native";import{mergeLabels}from"../labels.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";export const ReplyRating=({rating:e=null,onRate:t,noteMaxLength:s=1e3,labels:a,testID:i="chat-rating"})=>{const n=mergeLabels(a),l=useTheme(),[o,r]=useState(!1),[c,d]=useState(!1),[p,x]=useState(""),[m,b]=useState(""),[g,u]=useState(!1),save=async(e,s)=>{r(!0),b("");try{await t(e,s),d("Down"===e&&void 0===s),u("Up"===e||void 0!==s),void 0!==s&&x("")}catch{b(n.ratingFailed)}finally{r(!1)}};return _jsxs(View,{style:{gap:l.space.sm},testID:i,children:[_jsxs(View,{style:{flexDirection:"row",flexWrap:"wrap",alignItems:"center",gap:l.space.xs},children:[_jsx(Button,{label:n.rateUp,size:"sm",leftIcon:"like",variant:"Up"===e?"soft":"ghost",accessibilityState:{selected:"Up"===e,disabled:o},"aria-selected":"Up"===e,"aria-disabled":o,disabled:o,onPress:()=>{save("Up")},testID:`${i}-up`}),_jsx(Button,{label:n.rateDown,size:"sm",leftIcon:"dislike",variant:"Down"===e?"soft":"ghost",accessibilityState:{selected:"Down"===e,disabled:o},"aria-selected":"Down"===e,"aria-disabled":o,disabled:o,onPress:()=>{save("Down")},testID:`${i}-down`}),g&&!c&&_jsx(Text,{variant:"caption",color:"secondary",accessibilityLiveRegion:"polite",children:n.rated})]}),""!==m&&_jsx(Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:m}),c&&_jsxs(View,{style:{gap:l.space.sm},children:[_jsx(Input,{label:n.ratingNote,helperText:n.ratingNoteHint,multiline:!0,maxLength:s,value:p,onChangeText:x,testID:`${i}-note`}),_jsxs(View,{style:{flexDirection:"row",gap:l.space.sm},children:[_jsx(Button,{label:n.ratingNoteSend,size:"sm",loading:o,disabled:o,onPress:()=>{save("Down",p)},testID:`${i}-note-send`}),_jsx(Button,{label:n.ratingNoteSkip,size:"sm",variant:"outline",disabled:o,onPress:()=>{d(!1),u(!0)},testID:`${i}-note-skip`})]})]})]})};
1
+ "use strict";import{mergeLabels}from"@webority/markdown-core/chat";import{Button,Input,Text,useTheme}from"@webority/mobile-ui";import{useState}from"react";import{View}from"react-native";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";export const ReplyRating=({rating:e=null,onRate:t,noteMaxLength:s=1e3,labels:a,testID:i="chat-rating"})=>{const n=mergeLabels(a),o=useTheme(),[l,r]=useState(!1),[c,d]=useState(!1),[p,m]=useState(""),[x,b]=useState(""),[g,u]=useState(!1),save=async(e,s)=>{r(!0),b("");try{await t(e,s),d("Down"===e&&void 0===s),u("Up"===e||void 0!==s),void 0!==s&&m("")}catch{b(n.ratingFailed)}finally{r(!1)}};return _jsxs(View,{style:{gap:o.space.sm},testID:i,children:[_jsxs(View,{style:{flexDirection:"row",flexWrap:"wrap",alignItems:"center",gap:o.space.xs},children:[_jsx(Button,{label:n.rateUp,size:"sm",leftIcon:"like",variant:"Up"===e?"soft":"ghost",accessibilityState:{selected:"Up"===e,disabled:l},"aria-selected":"Up"===e,"aria-disabled":l,disabled:l,onPress:()=>{save("Up")},testID:`${i}-up`}),_jsx(Button,{label:n.rateDown,size:"sm",leftIcon:"dislike",variant:"Down"===e?"soft":"ghost",accessibilityState:{selected:"Down"===e,disabled:l},"aria-selected":"Down"===e,"aria-disabled":l,disabled:l,onPress:()=>{save("Down")},testID:`${i}-down`}),g&&!c&&_jsx(Text,{variant:"caption",color:"secondary",accessibilityLiveRegion:"polite",children:n.rated})]}),""!==x&&_jsx(Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:x}),c&&_jsxs(View,{style:{gap:o.space.sm},children:[_jsx(Input,{label:n.ratingNote,helperText:n.ratingNoteHint,multiline:!0,maxLength:s,value:p,onChangeText:m,testID:`${i}-note`}),_jsxs(View,{style:{flexDirection:"row",gap:o.space.sm},children:[_jsx(Button,{label:n.ratingNoteSend,size:"sm",loading:l,disabled:l,onPress:()=>{save("Down",p)},testID:`${i}-note-send`}),_jsx(Button,{label:n.ratingNoteSkip,size:"sm",variant:"outline",disabled:l,onPress:()=>{d(!1),u(!0)},testID:`${i}-note-skip`})]})]})]})};
@@ -1 +1 @@
1
- "use strict";export{ChatApiError,createChatClient}from"./client.js";export{ActionCard}from"./components/ActionCard.js";export{ChatComposer}from"./components/ChatComposer.js";export{ChatConversationList}from"./components/ChatConversationList.js";export{ChatLauncher}from"./components/ChatLauncher.js";export{ChatMarkdown}from"./components/ChatMarkdown.js";export{ChatMessage}from"./components/ChatMessage.js";export{ChatScreen}from"./components/ChatScreen.js";export{ChatThread}from"./components/ChatThread.js";export{ReplyRating}from"./components/ReplyRating.js";export{DEFAULT_CHAT_LABELS}from"./labels.js";export{createSseParser}from"./sse.js";export{useChat}from"./useChat.js";
1
+ "use strict";export{ChatApiError,createChatClient,createChatSession,createConversationList,createSseParser,DEFAULT_CHAT_LABELS}from"@webority/markdown-core/chat";export{ActionCard}from"./components/ActionCard.js";export{ChatComposer}from"./components/ChatComposer.js";export{ChatConversationList}from"./components/ChatConversationList.js";export{ChatLauncher}from"./components/ChatLauncher.js";export{ChatMarkdown}from"./components/ChatMarkdown.js";export{ChatMessage}from"./components/ChatMessage.js";export{ChatScreen}from"./components/ChatScreen.js";export{ChatThread}from"./components/ChatThread.js";export{ReplyRating}from"./components/ReplyRating.js";export{useChat}from"./useChat.js";
@@ -1 +1 @@
1
- "use strict";import{useCallback,useEffect,useRef,useState}from"react";const toError=e=>{const t=e;return{code:"string"==typeof t?.code&&t.code?t.code:"unknown",message:"string"==typeof t?.message&&t.message?t.message:"Something went wrong. Please try again.",resetsAtUtc:"string"==typeof t?.resetsAtUtc?t.resetsAtUtc:null}},parseActions=e=>{if(!e)return[];const t=JSON.parse(e);return Array.isArray(t)?t:[]},emptyTurn=(e,t)=>({id:e,question:t,answer:"",streaming:!1,error:null,actions:[],messageId:null,rating:null,ratingNote:null}),turnsFromConversation=e=>{const t=[];for(const n of e??[]){if("User"===n.role){t.push(emptyTurn(n.publicId,n.content));continue}const e=t[t.length-1],r={answer:n.content,actions:parseActions(n.actionsJson),messageId:n.publicId,rating:n.rating??null,ratingNote:n.ratingNote??null};e&&null===e.messageId&&""===e.answer?Object.assign(e,r):t.push({...emptyTurn(n.publicId,""),...r})}return t};export const useChat=({client:e,pageContext:t})=>{const[n,r]=useState([]),[s,a]=useState(null),[u,c]=useState(null),[o,l]=useState(!1),[i,g]=useState(null),m=useRef(null),d=useRef(0),f=useRef(0),p=useRef(t);p.current=t;const y=useRef(null);y.current=s;const w=useRef(n);w.current=n;const b=useRef(new Map),C=useRef(0),I=useRef(!1),A=useCallback(()=>{const e=b.current;0!==e.size&&(b.current=new Map,r(t=>t.map(t=>e.has(t.id)?{...t,answer:t.answer+(e.get(t.id)??"")}:t)))},[]),k=useCallback((e,t)=>{b.current.set(e,(b.current.get(e)??"")+t),I.current||(I.current=!0,C.current=requestAnimationFrame(()=>{I.current=!1,A()}))},[A]),h=useCallback(()=>{cancelAnimationFrame(C.current),I.current=!1,b.current=new Map},[]),v=useCallback(()=>{d.current+=1,m.current?.abort(),m.current=null,h()},[h]);useEffect(()=>v,[v]);const R=useCallback((e,t)=>{r(n=>n.map(n=>n.id===e?{...n,..."function"==typeof t?t(n):t}:n))},[]),E=useCallback(async t=>{const n="string"==typeof t?t.trim():"";if(!n||m.current)return;const s=d.current,u=new AbortController;m.current=u,f.current+=1;const o=`turn-${f.current}`;r(e=>[...e,{...emptyTurn(o,n),streaming:!0}]);const live=()=>s===d.current&&!u.signal.aborted;try{const t=await e.sendMessage({message:n,conversationId:y.current,pageContext:p.current},{signal:u.signal,onEvent:(e,t)=>{if(!live())return;const n=t;"delta"===e?k(o,n?.text??""):"reset"===e?(b.current.delete(o),R(o,{answer:""})):(A(),"actions"===e&&R(o,{actions:Array.isArray(n?.actions)?n.actions:[]}))}});if(!live())return;A(),R(o,{answer:t.reply,messageId:t.messageId??null,streaming:!1}),y.current=t.conversationId,a(t.conversationId),c(t.messagesLeftToday??null)}catch(e){if(!live())return;const t=toError(e);b.current.delete(o),R(o,{answer:"",actions:[],streaming:!1,error:t}),"daily_limit"===t.code&&c(0),"conversation_not_found"===t.code&&(y.current=null,a(null))}finally{m.current===u&&(m.current=null)}},[e,R,A,k]),S=useCallback(async t=>{v();const n=d.current;r([]),a(null),g(null),l(!0);try{const s=await e.getConversation(t);if(n!==d.current)return;r(turnsFromConversation(s.messages)),a(s.publicId)}catch(e){if(n!==d.current)return;g(toError(e))}finally{n===d.current&&l(!1)}},[v,e]),N=useCallback(()=>{v(),r([]),a(null),g(null),l(!1)},[v]),T=useCallback(()=>{v(),r([]),a(null),c(null),g(null),l(!1)},[v]),M=useCallback(async()=>{const t=d.current,n=await e.getAllowance();t===d.current&&c(n?.messagesLeftToday??null)},[e]),x=useCallback(async(t,n,r)=>{const s=w.current.find(e=>e.id===t),a=y.current;if(!s?.messageId||!a)throw new Error("Only a stored reply can be rated.");const u={rating:s.rating,ratingNote:s.ratingNote},c="string"==typeof r&&r.trim()?r.trim():null;R(t,{rating:n,ratingNote:c});try{await e.rateMessage(a,s.messageId,{rating:n,note:c})}catch(e){throw R(t,u),e}},[e,R]);return{turns:n,conversationId:s,messagesLeftToday:u,streaming:n.some(e=>e.streaming),loading:o,loadError:i,submit:E,openConversation:S,newConversation:N,rate:x,refreshAllowance:M,reset:T}};
1
+ "use strict";import{createChatSession}from"@webority/markdown-core/chat";import{useEffect,useMemo,useRef,useSyncExternalStore}from"react";const requestFrame=e=>{const t=requestAnimationFrame(e);return()=>cancelAnimationFrame(t)};export const useChat=({client:e,pageContext:t})=>{const r=useRef(t);r.current=t;const n=useMemo(()=>createChatSession({client:e,pageContext:()=>r.current,schedule:requestFrame}),[e]);useEffect(()=>()=>n.dispose(),[n]);return{...useSyncExternalStore(n.subscribe,n.getState),...useMemo(()=>({submit:e=>n.submit(e),stop:()=>n.stop(),retry:e=>n.retry(e),regenerate:e=>n.regenerate(e),startEdit:e=>n.startEdit(e),cancelEdit:()=>n.cancelEdit(),attach:e=>n.attach(e),removeAttachment:e=>n.removeAttachment(e),openConversation:e=>n.openConversation(e),newConversation:()=>n.newConversation(),rate:(e,t,r)=>n.rate(e,t,r),refreshAllowance:()=>n.refreshAllowance(),reset:()=>n.reset()}),[n]),client:n.client}};
@@ -1,6 +1,6 @@
1
+ import type { SupportAction, SupportActionTicket } from "@webority/markdown-core/chat";
2
+ import { type ChatLabels } from "@webority/markdown-core/chat";
1
3
  import type React from "react";
2
- import { type ChatLabels } from "../labels";
3
- import type { SupportAction, SupportActionTicket } from "../types";
4
4
  export interface ActionCardProps {
5
5
  action: SupportAction;
6
6
  /**
@@ -1,10 +1,12 @@
1
+ import { type ChatEditing, type ChatLabels, type ComposerAttachment } from "@webority/markdown-core/chat";
1
2
  import type React from "react";
2
- import { type ChatLabels } from "../labels";
3
3
  export interface ChatComposerProps {
4
4
  /** Called with the trimmed question; the box clears once it is handed over. */
5
5
  onSubmit: (message: string) => unknown;
6
6
  /** An answer is arriving: the question can be typed but not sent. */
7
7
  busy?: boolean;
8
+ /** While busy, the send button becomes a stop button that calls this. */
9
+ onStop?: () => void;
8
10
  /** No question can be asked, e.g. none left today. */
9
11
  disabled?: boolean;
10
12
  /** The server's message limit. Default 4000. */
@@ -19,6 +21,15 @@ export interface ChatComposerProps {
19
21
  keyboardOffset?: number;
20
22
  /** Pads for the bottom safe area. Default true. */
21
23
  safeArea?: boolean;
24
+ /** The files on the question being written. */
25
+ attachments?: ComposerAttachment[];
26
+ /** Opens the app's file picker. The attach button shows only when this is given. */
27
+ onAttach?: () => void;
28
+ /** Removes one file by its key. */
29
+ onRemoveAttachment?: (key: string) => void;
30
+ /** The question being edited; its banner's Cancel calls `onCancelEdit`. */
31
+ editing?: ChatEditing | null;
32
+ onCancelEdit?: () => void;
22
33
  labels?: Partial<ChatLabels>;
23
34
  testID?: string;
24
35
  }
@@ -1,8 +1,7 @@
1
+ import type { ConversationSummary } from "@webority/markdown-core/chat";
2
+ import { type ChatClient, type ChatLabels } from "@webority/markdown-core/chat";
1
3
  import type React from "react";
2
4
  import { type StyleProp, type ViewStyle } from "react-native";
3
- import type { ChatClient } from "../client";
4
- import { type ChatLabels } from "../labels";
5
- import type { ConversationSummary } from "../types";
6
5
  export interface ChatConversationListProps {
7
6
  client: ChatClient;
8
7
  /** E.g. go to the chat and call `chat.openConversation(conversation.publicId)`. */
@@ -17,7 +16,7 @@ export interface ChatConversationListProps {
17
16
  }
18
17
  /**
19
18
  * The person's past chats, newest first. It pages with Show more, refreshes on pull, opens one
20
- * through `onOpen`, and deletes one after a confirm.
19
+ * through `onOpen`, renames and deletes one after a confirm.
21
20
  */
22
21
  export declare const ChatConversationList: React.FC<ChatConversationListProps>;
23
22
  //# sourceMappingURL=ChatConversationList.d.ts.map
@@ -1,5 +1,5 @@
1
+ import { type ChatLabels } from "@webority/markdown-core/chat";
1
2
  import type React from "react";
2
- import { type ChatLabels } from "../labels";
3
3
  export interface ChatLauncherProps {
4
4
  onPress: () => void;
5
5
  /** `end` (the default) or `start`: the bottom corner it sits in. */
@@ -10,8 +10,15 @@ export interface ChatMarkdownProps<T = string> {
10
10
  resolveLink?: (href: string) => T | null | undefined;
11
11
  /** Opens what `resolveLink` returned. Without it, links show as plain text. */
12
12
  onLinkPress?: (target: T) => void;
13
+ /**
14
+ * Tells a citation marker (the bracketed inner text, e.g. `1` for `[1]`) from an ordinary link.
15
+ * A citation draws as a pressable marker and never as a link.
16
+ */
17
+ isCitation?: (inner: string) => boolean;
18
+ /** Opens the citation a reply marker names. Without it, citation markers show as plain text. */
19
+ onOpenCitation?: (citation: string) => void;
13
20
  testID?: string;
14
21
  }
15
22
  /** A reply never opens a web address, and its headings draw as bold lines, not large type. */
16
- export declare function ChatMarkdown<T = string>({ text, resolveLink, onLinkPress, testID }: ChatMarkdownProps<T>): React.ReactElement;
23
+ export declare function ChatMarkdown<T = string>({ text, resolveLink, onLinkPress, isCitation, onOpenCitation, testID, }: ChatMarkdownProps<T>): React.ReactElement;
17
24
  //# sourceMappingURL=ChatMarkdown.d.ts.map