@webority/chat-react 0.65.0 → 0.67.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -245,6 +245,39 @@ One support action under a reply: what will be sent, then Confirm or Not now. It
245
245
  sending to done (with View ticket when `onViewTicket` is given), and an expired action shows
246
246
  without a button. Takes `action`, `confirmAction(token)` and `onViewTicket(ticket)`.
247
247
 
248
+ ### `<ConfirmCard />`
249
+
250
+ One general card for an action the assistant prepared. Nothing happens until the person presses
251
+ Confirm. It moves through sending to done, showing the message `onConfirm` resolves to (or Done.),
252
+ and a failed confirm shows its message and stays ready to try again. Not now dismisses it without
253
+ sending. Takes `title`, `subtitle`, `lines` (strings, one paragraph each), `note` (replaces the
254
+ default "Nothing is sent until you confirm."), `onConfirm()` and `labels`.
255
+
256
+ ```jsx
257
+ <ConfirmCard
258
+ title="Archive project"
259
+ subtitle="Planning"
260
+ lines={["Moves the project to the archive."]}
261
+ onConfirm={() => archiveProject(projectId)}
262
+ />
263
+ ```
264
+
265
+ ### Citation chips
266
+
267
+ A reply can cite its sources as `[Clause 4.2]`. `splitCitations(text, isCitation)` splits the reply into text parts and citation parts, and `CitationChip` draws each citation as a chip that opens its source. Only the runs that `isCitation` accepts become chips: a markdown link such as `[text](url)` and an empty `[]` stay text. `CitationChip` takes `citation`, `onOpen(citation)`, and optionally `label` (the chip text, defaulting to the citation) and `ariaLabel`.
268
+
269
+ ```jsx
270
+ const parts = splitCitations(reply.text, (inner) => sources.has(inner));
271
+
272
+ {parts.map((part, i) =>
273
+ "citation" in part ? (
274
+ <CitationChip key={i} citation={part.citation} onOpen={openSource} />
275
+ ) : (
276
+ <span key={i}>{part.text}</span>
277
+ ),
278
+ )}
279
+ ```
280
+
248
281
  ## Replies
249
282
 
250
283
  `<ChatMarkdown text resolveLink linkComponent />` renders a reply from a small, safe subset of
@@ -1 +1 @@
1
- import{ChatApiError as e,DEFAULT_CHAT_LABELS as t,createChatClient as n,createSseParser as r,linkRoute as i,mergeLabels as a,parseBlocks as o,parseInline as s}from"@webority/ui-elements/chat-core";import{AppActionIcon as c,AppAlert as l,AppButton as u,AppCard as d,AppConfirmDialog as f,AppDataTable as p,AppEmptyState as m,AppIcon as h,AppLink as g,AppSidebarMenu as _,AppSkeleton as v,AppSpinner as y,AppTextarea as b,useFloatingStack as x}from"@webority/ui-react";import{Fragment as S,useCallback as C,useEffect as w,useId as T,useRef as E,useState as D}from"react";import{Fragment as O,jsx as k,jsxs as A}from"react/jsx-runtime";import{createPortal as j}from"react-dom";function M(e,t){return e.kind===`Reply`?t.actionReply(e.ticketNumber):e.kind===`Reopen`?t.actionReopen(e.ticketNumber):t.actionRaiseTicket}function N(e,t,n){return e===`Reply`?n.actionDoneReply(t):e===`Reopen`?n.actionDoneReopen(t):n.actionDoneRaiseTicket(t)}function P({action:e,confirmAction:t,onViewTicket:n,labels:r}){let i=a(r),[o,s]=D(`ready`),[c,f]=D(null),[p,m]=D(``);if(o===`dismissed`)return k(`p`,{className:`wui-text-sm text-body-secondary mb-0`,children:i.actionDismissed});if(o===`done`)return k(l,{variant:`success`,role:`status`,size:`sm`,action:n?k(u,{size:`sm`,variant:`ghost`,onClick:()=>n(c),children:i.viewTicket}):void 0,children:N(e.kind,c.number,i)});async function h(){s(`sending`),m(``);try{f(await t(e.token)),s(`done`)}catch(e){m(e?.message||i.actionFailed),s(`ready`)}}let g=o===`sending`,_=new Date(e.expiresDateTimeUtc).getTime()<=Date.now(),v=e.kind===`RaiseTicket`?[e.category,e.subject].filter(Boolean).join(` · `):``;return k(d,{padding:`sm`,className:`border`,title:M(e,i),subtitle:v||void 0,children:A(`div`,{className:`d-flex flex-column gap-2`,children:[e.kind!==`Reopen`&&e.body&&k(`p`,{className:`wui-text-sm mb-0`,style:{whiteSpace:`pre-wrap`,overflowWrap:`anywhere`},children:e.body}),_?k(`p`,{className:`wui-text-sm text-body-secondary mb-0`,children:i.actionExpired}):A(O,{children:[k(`p`,{className:`wui-text-xs text-body-secondary mb-0`,children:i.actionNote}),p&&k(l,{size:`sm`,variant:`danger`,children:p}),A(`div`,{className:`d-flex flex-wrap gap-2`,children:[k(u,{size:`sm`,loading:g,onClick:h,children:i.actionConfirm}),k(u,{size:`sm`,variant:`secondary`,disabled:g,onClick:()=>s(`dismissed`),children:i.actionDismiss})]})]})]})})}function F({onSubmit:e,busy:t=!1,disabled:n=!1,maxLength:r=4e3,inputRef:i,labels:o}){let s=a(o),c=T(),[l,d]=D(``),f=t||n||!l.trim();function p(){f||(e(l.trim()),d(``))}return A(`form`,{className:`d-flex align-items-end gap-2`,"aria-label":s.composer,onSubmit:e=>{e.preventDefault(),p()},children:[k(b,{id:`${c}-message`,"aria-label":s.composer,"aria-describedby":`${c}-hint`,placeholder:s.placeholder,rows:1,autoGrow:!0,maxLength:r,value:l,disabled:n,ref:i,fieldClassName:`flex-grow-1 mb-0`,onChange:e=>d(e.target.value),onKeyDown:e=>{e.key===`Enter`&&!e.shiftKey&&!e.nativeEvent.isComposing&&(e.preventDefault(),p())}}),k(`span`,{id:`${c}-hint`,className:`visually-hidden`,children:s.composerHint}),k(u,{type:`submit`,leftIcon:`send`,disabled:f,children:k(`span`,{className:`visually-hidden`,children:s.send})})]})}var I=new Intl.DateTimeFormat(`en-IN`,{day:`2-digit`,month:`numeric`,year:`numeric`,hour:`numeric`,minute:`2-digit`,hour12:!0,timeZoneName:`short`}),L=[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`];function R(e){if(!e)return`-`;let t=new Date(e);if(Number.isNaN(t.getTime()))return`-`;let n=Object.fromEntries(I.formatToParts(t).map(e=>[e.type,e.value]));return`${n.day} ${L[Number(n.month)-1]} ${n.year}, ${n.hour}:${n.minute} ${n.dayPeriod.toLowerCase()} ${n.timeZoneName}`}function z({client:e,onOpen:t,onDeleted:n,pageSize:r=20,labels:i}){let o=a(i),[s,p]=D([]),[h,g]=D(!0),[_,y]=D(``),[b,x]=D(!1),[S,T]=D(0),[E,O]=D(null),[j,M]=D(!1),[N,P]=D(``),F=C(async t=>{g(!0),y(``);try{let n=await e.listConversations({skip:t,take:r});p(e=>t===0?n:[...e,...n]),x(n.length===r)}catch(e){y(e?.message||o.loadFailed)}finally{g(!1)}},[e,r,o.loadFailed]);w(()=>{F(0)},[F,S]);async function I(){M(!0),P(``);try{await e.deleteConversation(E.publicId),p(e=>e.filter(e=>e.publicId!==E.publicId)),n?.(E.publicId),O(null)}catch(e){P(e?.message||o.deleteFailed)}finally{M(!1)}}return!h&&!_&&s.length===0?k(m,{icon:`chat`,size:`sm`,title:o.conversationsEmptyTitle,text:o.conversationsEmptyText}):A(`div`,{className:`d-flex flex-column gap-3`,children:[_&&k(l,{variant:`danger`,action:k(u,{size:`sm`,variant:`secondary`,onClick:()=>T(e=>e+1),children:o.retry}),children:_}),s.length>0&&k(`ul`,{className:`list-unstyled d-flex flex-column gap-2 mb-0`,"aria-label":o.conversations,children:s.map(e=>k(`li`,{children:A(d,{padding:`sm`,className:`border`,bodyClassName:`d-flex align-items-center gap-2`,children:[k(u,{variant:`ghost`,className:`flex-grow-1 text-start`,style:{minWidth:0},onClick:()=>t(e),children:A(`span`,{className:`d-flex flex-column`,style:{minWidth:0},children:[k(`span`,{className:`text-truncate fw-semibold`,children:e.title||o.untitled}),k(`time`,{dateTime:e.lastMessageDateTimeUtc,className:`wui-text-xs text-body-secondary`,children:R(e.lastMessageDateTimeUtc)})]})}),k(c,{icon:`trash-2`,danger:!0,label:o.deleteConversation,onClick:()=>{P(``),O(e)}})]})},e.publicId))}),h&&A(`div`,{className:`d-flex flex-column gap-2`,"aria-hidden":`true`,children:[k(v,{height:44}),k(v,{height:44}),k(v,{height:44})]}),!h&&b&&k(u,{variant:`secondary`,className:`align-self-center`,onClick:()=>F(s.length),children:o.loadMore}),k(f,{open:E!==null,title:o.deleteConfirmTitle,message:N?k(l,{variant:`danger`,children:N}):o.deleteConfirmMessage,confirmLabel:o.deleteConfirm,cancelLabel:o.cancel,danger:!0,loading:j,onConfirm:I,onClose:()=>{j||O(null)}})]})}var B={zIndex:`var(--wui-z-fixed)`,bottom:0},V={end:{insetInlineEnd:0},start:{insetInlineStart:0}};function H({onClick:e,open:t=!1,position:n=`end`,icon:r=`sparkles`,compact:i=!1,className:o,style:s,labels:c}){let l=a(c);return i?k(U,{onClick:e,open:t,position:n,icon:r,className:o,style:s,label:l.launcher}):k(`span`,{"data-support-capture":`exclude`,className:[`position-fixed m-3`,o].filter(Boolean).join(` `),style:{...B,...V[n],...s},children:k(u,{leftIcon:r,className:`rounded-pill`,onClick:e,"aria-haspopup":`dialog`,"aria-expanded":t,children:l.launcher})})}function U({onClick:e,open:t,position:n,icon:r,className:i,style:a,label:o}){let s=x(n);return s?j(k(`span`,{className:[`wui-floating-stack-item wui-floating-stack-item--primary`,i].filter(Boolean).join(` `),style:a,children:k(u,{className:`wui-floating-btn`,onClick:e,"aria-label":o,"aria-haspopup":`dialog`,"aria-expanded":t,tooltip:o,tooltipPlacement:n===`start`?`end`:`start`,children:k(h,{name:r,size:24})})}),s):null}function W({tokens:e,resolveLink:t,linkComponent:n}){return e.map(e=>{switch(e.type){case`code`:return k(`code`,{children:e.text},e.key);case`strong`:return k(`strong`,{children:k(W,{tokens:e.children,resolveLink:t,linkComponent:n})},e.key);case`em`:return k(`em`,{children:k(W,{tokens:e.children,resolveLink:t,linkComponent:n})},e.key);case`link`:{let r=k(W,{tokens:e.children,resolveLink:t,linkComponent:n}),a=i(e.href,t);return a?k(g,{href:a,linkComponent:n,animation:`static`,children:r},e.key):k(`span`,{children:r},e.key)}default:return k(S,{children:e.text},e.key)}})}function G({text:e,resolveLink:t,linkComponent:n}){return k(W,{tokens:s(e),resolveLink:t,linkComponent:n})}function K({block:e,resolveLink:t,linkComponent:n}){let r=e=>k(G,{text:e,resolveLink:t,linkComponent:n});switch(e.type){case`heading`:return k(`p`,{className:`fw-semibold mb-2`,children:r(e.text)});case`rule`:return k(`hr`,{className:`my-2`});case`code`:return k(`pre`,{className:`wui-text-sm mb-2`,children:k(`code`,{children:e.text})});case`list`:{let t=e.items.map((e,t)=>k(`li`,{children:r(e)},t));return e.ordered?k(`ol`,{className:`mb-2 ps-4`,start:e.start===1?void 0:e.start,children:t}):k(`ul`,{className:`mb-2 ps-4`,children:t})}case`table`:return k(p,{columns:e.header.map((e,t)=>({key:`c${t}`,label:r(e),render:e=>r(e.cells[t]??``)})),rows:e.rows.map((e,t)=>({id:t,cells:e})),density:`compact`,empty:null,wrapperClassName:`mb-2`});default:return k(`p`,{className:`mb-2`,children:e.lines.map((e,t)=>A(`span`,{children:[t>0&&k(`br`,{}),r(e)]},t))})}}function q({text:e,resolveLink:t,linkComponent:n,className:r}){let i=o(e);return k(`div`,{className:[`wui-text-sm text-break`,r].filter(Boolean).join(` `),children:i.map(e=>k(K,{block:e,resolveLink:t,linkComponent:n},e.key))})}function J({rating:e=null,onRate:t,noteMaxLength:n=1e3,labels:r}){let i=a(r),o=T(),[s,c]=D(!1),[d,f]=D(!1),[p,m]=D(``),[h,g]=D(``),[_,v]=D(!1);async function y(e,n){c(!0),g(``);try{await t(e,n),f(e===`Down`&&n===void 0),v(e===`Up`||n!==void 0),n!==void 0&&m(``)}catch{g(i.ratingFailed)}finally{c(!1)}}return A(`div`,{className:`d-flex flex-column gap-2`,children:[A(`div`,{className:`d-flex flex-wrap align-items-center gap-1`,children:[k(u,{size:`sm`,variant:e===`Up`?`subtle`:`ghost`,leftIcon:`check`,"aria-pressed":e===`Up`,disabled:s,onClick:()=>y(`Up`),children:i.rateUp}),k(u,{size:`sm`,variant:e===`Down`?`subtle`:`ghost`,leftIcon:`x`,"aria-pressed":e===`Down`,disabled:s,onClick:()=>y(`Down`),children:i.rateDown}),_&&!d&&k(`span`,{className:`wui-text-xs text-body-secondary`,role:`status`,children:i.rated})]}),h&&k(l,{size:`sm`,variant:`danger`,children:h}),d&&A(`form`,{className:`d-flex flex-column gap-2`,onSubmit:e=>{e.preventDefault(),y(`Down`,p)},children:[k(b,{id:`${o}-note`,label:i.ratingNote,hint:i.ratingNoteHint,rows:2,maxLength:n,value:p,onChange:e=>m(e.target.value)}),A(`div`,{className:`d-flex gap-2`,children:[k(u,{type:`submit`,size:`sm`,loading:s,children:i.ratingNoteSend}),k(u,{size:`sm`,variant:`secondary`,disabled:s,onClick:()=>{f(!1),v(!0)},children:i.ratingNoteSkip})]})]})]})}var Y={maxWidth:`85%`,whiteSpace:`pre-wrap`,overflowWrap:`anywhere`};function X({turn:e,onRate:t,resolveLink:n,linkComponent:r,confirmAction:i,onViewTicket:o,renderReply:s,labels:c}){let u=a(c),f=e.streaming&&!e.answer;return A(`li`,{className:`d-flex flex-column gap-2`,children:[e.question&&A(`div`,{className:`align-self-end`,style:Y,children:[A(`span`,{className:`visually-hidden`,children:[u.you,`: `]}),k(d,{padding:`sm`,variant:`muted`,className:`wui-text-sm`,children:e.question})]}),A(`div`,{className:`d-flex flex-column gap-2`,style:{minWidth:0},children:[A(`span`,{className:`visually-hidden`,children:[u.assistant,`: `]}),k(`div`,{"aria-live":`polite`,"aria-busy":e.streaming,children:f?A(`span`,{className:`d-inline-flex align-items-center gap-2 wui-text-sm text-body-secondary`,children:[k(y,{size:`sm`,label:u.thinking}),k(`span`,{"aria-hidden":`true`,children:u.thinking})]}):e.answer&&(s?s(e,{streaming:!!e.streaming}):k(q,{text:e.answer,resolveLink:n,linkComponent:r}))}),e.error&&k(l,{size:`sm`,variant:`danger`,children:e.error.message}),i&&!e.streaming&&e.actions.map(e=>k(P,{action:e,confirmAction:i,onViewTicket:o,labels:c},e.token)),t&&e.messageId&&!e.streaming&&k(J,{rating:e.rating,onRate:(n,r)=>t(e.id,n,r),labels:c})]})]})}function Z({turns:e,empty:t,onRate:n,resolveLink:r,linkComponent:i,confirmAction:o,onViewTicket:s,renderReply:c,labels:l}){let u=a(l),d=E(null),f=e[e.length-1];return w(()=>{d.current?.scrollIntoView({block:`end`})},[e.length,f?.answer,f?.error,f?.actions]),e.length===0?t??k(m,{icon:`sparkles`,size:`sm`,title:u.emptyTitle,text:u.emptyText}):A(O,{children:[k(`ol`,{className:`list-unstyled d-flex flex-column gap-3 mb-0`,"aria-label":u.thread,children:e.map(e=>k(X,{turn:e,onRate:n,resolveLink:r,linkComponent:i,confirmAction:o,onViewTicket:s,renderReply:c,labels:l},e.id))}),k(`div`,{ref:d})]})}function Q({chat:e,open:t,onClose:n,title:r,titleIcon:i=`sparkles`,headerActions:o,empty:s,disclaimer:u,maxLength:d=4e3,allowanceThreshold:f=10,width:p=`440px`,resolveLink:m,linkComponent:g,confirmAction:v,onViewTicket:b,rating:x=!0,renderReply:S,labels:C}){let T=a(C),D=E(null),{refreshAllowance:O}=e;w(()=>{t&&O().catch(()=>{})},[t,O]);let j=e.messagesLeftToday,M=r??T.panelTitle;return k(_,{show:t,onHide:n,side:`right`,width:p,header:A(`div`,{className:`drawer-header`,children:[A(`div`,{className:`drawer-title`,children:[i&&k(`span`,{className:`drawer-title-ic`,children:k(h,{name:i,size:18})}),M]}),A(`div`,{className:`d-flex align-items-center gap-1`,children:[o,k(c,{icon:`plus`,label:T.newChat,onClick:e.newConversation,disabled:e.turns.length===0&&!e.loading}),k(c,{icon:`x`,label:T.close,onClick:n})]})]}),footer:A(`div`,{className:`d-flex flex-column gap-2`,children:[j!==null&&j<=f&&k(`p`,{className:`wui-text-xs text-body-secondary mb-0`,role:`status`,children:T.allowance(j)}),k(F,{onSubmit:e.submit,busy:e.streaming||e.loading,disabled:j===0,maxLength:d,inputRef:D,labels:C}),k(`p`,{className:`wui-text-xs text-body-secondary mb-0`,children:u??T.disclaimer})]}),ariaLabel:typeof M==`string`?M:T.panelTitle,onEntered:()=>D.current?.focus(),children:e.loading?k(`div`,{className:`d-flex justify-content-center py-4`,children:k(y,{label:T.loadingConversation})}):e.loadError?k(l,{variant:`danger`,children:e.loadError.message}):k(Z,{turns:e.turns,empty:s,onRate:x?e.rate:void 0,resolveLink:m,linkComponent:g,confirmAction:v,onViewTicket:b,renderReply:S,labels:C})})}function $(e){return{code:e?.code||`unknown`,message:e?.message||`Something went wrong. Please try again.`,resetsAtUtc:e?.resetsAtUtc??null}}function ee(e){if(!e)return[];let t=JSON.parse(e);return Array.isArray(t)?t:[]}function te(e){let t=[];for(let n of e??[]){if(n.role===`User`){t.push({id:n.publicId,question:n.content,answer:``,streaming:!1,step:null,error:null,actions:[],messageId:null,rating:null,ratingNote:null});continue}let e=t[t.length-1],r={answer:n.content,actions:ee(n.actionsJson),messageId:n.publicId,rating:n.rating??null,ratingNote:n.ratingNote??null};e&&e.messageId===null&&e.answer===``?Object.assign(e,r):t.push({id:n.publicId,question:``,streaming:!1,step:null,error:null,...r})}return t}function ne({client:e,pageContext:t}){let[n,r]=D([]),[i,a]=D(null),[o,s]=D(null),[c,l]=D(!1),[u,d]=D(null),f=E(null),p=E(0),m=E(0),h=E(t);h.current=t;let g=E(null);g.current=i;let _=E(n);_.current=n;let v=C(()=>{p.current+=1,f.current?.abort(),f.current=null},[]);w(()=>v,[v]);let y=C((e,t)=>{r(n=>n.map(n=>n.id===e?{...n,...typeof t==`function`?t(n):t}:n))},[]),b=C(async t=>{let n=typeof t==`string`?t.trim():``;if(!n||f.current)return;let i=p.current,o=new AbortController;f.current=o,m.current+=1;let c=`turn-${m.current}`;r(e=>[...e,{id:c,question:n,answer:``,streaming:!0,step:null,error:null,actions:[],messageId:null,rating:null,ratingNote:null}]);let l=()=>i===p.current&&!o.signal.aborted;try{let t=await e.sendMessage({message:n,conversationId:g.current,pageContext:h.current},{signal:o.signal,onEvent:(e,t)=>{l()&&(e===`delta`?y(c,e=>({answer:e.answer+(t?.text??``),step:null})):e===`reset`?y(c,{answer:``,step:null}):e===`tool`?y(c,{step:typeof t?.toolName==`string`&&t.toolName?t.toolName:null}):e===`actions`&&y(c,{actions:Array.isArray(t?.actions)?t.actions:[]}))}});if(!l())return;y(c,{answer:t.reply,messageId:t.messageId??null,streaming:!1,step:null}),g.current=t.conversationId,a(t.conversationId),s(t.messagesLeftToday??null)}catch(e){if(!l())return;y(c,{answer:``,actions:[],streaming:!1,step:null,error:$(e)}),e?.code===`daily-limit`&&s(0),e?.code===`conversation-not-found`&&(g.current=null,a(null))}finally{f.current===o&&(f.current=null)}},[e,y]),x=C(async t=>{v();let n=p.current;r([]),a(null),d(null),l(!0);try{let i=await e.getConversation(t);if(n!==p.current)return;r(te(i.messages)),a(i.publicId)}catch(e){if(n!==p.current)return;d($(e))}finally{n===p.current&&l(!1)}},[v,e]),S=C(()=>{v(),r([]),a(null),d(null),l(!1)},[v]),T=C(()=>{v(),r([]),a(null),s(null),d(null),l(!1)},[v]),O=C(async()=>{let t=p.current,n=await e.getAllowance();t===p.current&&s(n?.messagesLeftToday??null)},[e]),k=C(async(t,n,r)=>{let i=_.current.find(e=>e.id===t),a=g.current;if(!i?.messageId||!a)throw Error(`Only a stored reply can be rated.`);let o={rating:i.rating,ratingNote:i.ratingNote},s=typeof r==`string`&&r.trim()?r.trim():null;y(t,{rating:n,ratingNote:s});try{await e.rateMessage(a,i.messageId,{rating:n,note:s})}catch(e){throw y(t,o),e}},[e,y]);return{turns:n,conversationId:i,messagesLeftToday:o,streaming:n.some(e=>e.streaming),loading:c,loadError:u,submit:b,openConversation:x,newConversation:S,rate:k,refreshAllowance:O,reset:T}}export{P as ActionCard,e as ChatApiError,F as ChatComposer,z as ChatConversationList,H as ChatLauncher,q as ChatMarkdown,X as ChatMessage,Q as ChatPanel,Z as ChatThread,t as DEFAULT_CHAT_LABELS,J as ReplyRating,n as createChatClient,r as createSseParser,ne as useChat};
1
+ import{ChatApiError as e,DEFAULT_CHAT_LABELS as t,createChatClient as n,createSseParser as r,linkRoute as i,mergeLabels as a,parseBlocks as o,parseInline as s}from"@webority/ui-elements/chat-core";import{AppActionIcon as c,AppAlert as l,AppButton as u,AppCard as d,AppChip as f,AppConfirmDialog as p,AppDataTable as m,AppEmptyState as h,AppIcon as g,AppLink as _,AppSidebarMenu as v,AppSkeleton as y,AppSpinner as b,AppTextarea as x,useFloatingStack as S}from"@webority/ui-react";import{Fragment as C,useCallback as w,useEffect as T,useId as E,useRef as D,useState as O}from"react";import{Fragment as k,jsx as A,jsxs as j}from"react/jsx-runtime";import{createPortal as M}from"react-dom";function N(e,t){return e.kind===`Reply`?t.actionReply(e.ticketNumber):e.kind===`Reopen`?t.actionReopen(e.ticketNumber):t.actionRaiseTicket}function P(e,t,n){return e===`Reply`?n.actionDoneReply(t):e===`Reopen`?n.actionDoneReopen(t):n.actionDoneRaiseTicket(t)}function F({action:e,confirmAction:t,onViewTicket:n,labels:r}){let i=a(r),[o,s]=O(`ready`),[c,f]=O(null),[p,m]=O(``);if(o===`dismissed`)return A(`p`,{className:`wui-text-sm text-body-secondary mb-0`,children:i.actionDismissed});if(o===`done`)return A(l,{variant:`success`,role:`status`,size:`sm`,action:n?A(u,{size:`sm`,variant:`ghost`,onClick:()=>n(c),children:i.viewTicket}):void 0,children:P(e.kind,c.number,i)});async function h(){s(`sending`),m(``);try{f(await t(e.token)),s(`done`)}catch(e){m(e?.message||i.actionFailed),s(`ready`)}}let g=o===`sending`,_=new Date(e.expiresDateTimeUtc).getTime()<=Date.now(),v=e.kind===`RaiseTicket`?[e.category,e.subject].filter(Boolean).join(` · `):``;return A(d,{padding:`sm`,className:`border`,title:N(e,i),subtitle:v||void 0,children:j(`div`,{className:`d-flex flex-column gap-2`,children:[e.kind!==`Reopen`&&e.body&&A(`p`,{className:`wui-text-sm mb-0`,style:{whiteSpace:`pre-wrap`,overflowWrap:`anywhere`},children:e.body}),_?A(`p`,{className:`wui-text-sm text-body-secondary mb-0`,children:i.actionExpired}):j(k,{children:[A(`p`,{className:`wui-text-xs text-body-secondary mb-0`,children:i.actionNote}),p&&A(l,{size:`sm`,variant:`danger`,children:p}),j(`div`,{className:`d-flex flex-wrap gap-2`,children:[A(u,{size:`sm`,loading:g,onClick:h,children:i.actionConfirm}),A(u,{size:`sm`,variant:`secondary`,disabled:g,onClick:()=>s(`dismissed`),children:i.actionDismiss})]})]})]})})}function I({onSubmit:e,busy:t=!1,disabled:n=!1,maxLength:r=4e3,inputRef:i,labels:o}){let s=a(o),c=E(),[l,d]=O(``),f=t||n||!l.trim();function p(){f||(e(l.trim()),d(``))}return j(`form`,{className:`d-flex align-items-end gap-2`,"aria-label":s.composer,onSubmit:e=>{e.preventDefault(),p()},children:[A(x,{id:`${c}-message`,"aria-label":s.composer,"aria-describedby":`${c}-hint`,placeholder:s.placeholder,rows:1,autoGrow:!0,maxLength:r,value:l,disabled:n,ref:i,fieldClassName:`flex-grow-1 mb-0`,onChange:e=>d(e.target.value),onKeyDown:e=>{e.key===`Enter`&&!e.shiftKey&&!e.nativeEvent.isComposing&&(e.preventDefault(),p())}}),A(`span`,{id:`${c}-hint`,className:`visually-hidden`,children:s.composerHint}),A(u,{type:`submit`,leftIcon:`send`,disabled:f,children:A(`span`,{className:`visually-hidden`,children:s.send})})]})}var L=new Intl.DateTimeFormat(`en-IN`,{day:`2-digit`,month:`numeric`,year:`numeric`,hour:`numeric`,minute:`2-digit`,hour12:!0,timeZoneName:`short`}),R=[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`];function z(e){if(!e)return`-`;let t=new Date(e);if(Number.isNaN(t.getTime()))return`-`;let n=Object.fromEntries(L.formatToParts(t).map(e=>[e.type,e.value]));return`${n.day} ${R[Number(n.month)-1]} ${n.year}, ${n.hour}:${n.minute} ${n.dayPeriod.toLowerCase()} ${n.timeZoneName}`}function B({client:e,onOpen:t,onDeleted:n,pageSize:r=20,labels:i}){let o=a(i),[s,f]=O([]),[m,g]=O(!0),[_,v]=O(``),[b,x]=O(!1),[S,C]=O(0),[E,D]=O(null),[k,M]=O(!1),[N,P]=O(``),F=w(async t=>{g(!0),v(``);try{let n=await e.listConversations({skip:t,take:r});f(e=>t===0?n:[...e,...n]),x(n.length===r)}catch(e){v(e?.message||o.loadFailed)}finally{g(!1)}},[e,r,o.loadFailed]);T(()=>{F(0)},[F,S]);async function I(){M(!0),P(``);try{await e.deleteConversation(E.publicId),f(e=>e.filter(e=>e.publicId!==E.publicId)),n?.(E.publicId),D(null)}catch(e){P(e?.message||o.deleteFailed)}finally{M(!1)}}return!m&&!_&&s.length===0?A(h,{icon:`chat`,size:`sm`,title:o.conversationsEmptyTitle,text:o.conversationsEmptyText}):j(`div`,{className:`d-flex flex-column gap-3`,children:[_&&A(l,{variant:`danger`,action:A(u,{size:`sm`,variant:`secondary`,onClick:()=>C(e=>e+1),children:o.retry}),children:_}),s.length>0&&A(`ul`,{className:`list-unstyled d-flex flex-column gap-2 mb-0`,"aria-label":o.conversations,children:s.map(e=>A(`li`,{children:j(d,{padding:`sm`,className:`border`,bodyClassName:`d-flex align-items-center gap-2`,children:[A(u,{variant:`ghost`,className:`flex-grow-1 text-start`,style:{minWidth:0},onClick:()=>t(e),children:j(`span`,{className:`d-flex flex-column`,style:{minWidth:0},children:[A(`span`,{className:`text-truncate fw-semibold`,children:e.title||o.untitled}),A(`time`,{dateTime:e.lastMessageDateTimeUtc,className:`wui-text-xs text-body-secondary`,children:z(e.lastMessageDateTimeUtc)})]})}),A(c,{icon:`trash-2`,danger:!0,label:o.deleteConversation,onClick:()=>{P(``),D(e)}})]})},e.publicId))}),m&&j(`div`,{className:`d-flex flex-column gap-2`,"aria-hidden":`true`,children:[A(y,{height:44}),A(y,{height:44}),A(y,{height:44})]}),!m&&b&&A(u,{variant:`secondary`,className:`align-self-center`,onClick:()=>F(s.length),children:o.loadMore}),A(p,{open:E!==null,title:o.deleteConfirmTitle,message:N?A(l,{variant:`danger`,children:N}):o.deleteConfirmMessage,confirmLabel:o.deleteConfirm,cancelLabel:o.cancel,danger:!0,loading:k,onConfirm:I,onClose:()=>{k||D(null)}})]})}var V={zIndex:`var(--wui-z-fixed)`,bottom:0},H={end:{insetInlineEnd:0},start:{insetInlineStart:0}};function U({onClick:e,open:t=!1,position:n=`end`,icon:r=`sparkles`,compact:i=!1,className:o,style:s,labels:c}){let l=a(c);return i?A(W,{onClick:e,open:t,position:n,icon:r,className:o,style:s,label:l.launcher}):A(`span`,{"data-support-capture":`exclude`,className:[`position-fixed m-3`,o].filter(Boolean).join(` `),style:{...V,...H[n],...s},children:A(u,{leftIcon:r,className:`rounded-pill`,onClick:e,"aria-haspopup":`dialog`,"aria-expanded":t,children:l.launcher})})}function W({onClick:e,open:t,position:n,icon:r,className:i,style:a,label:o}){let s=S(n);return s?M(A(`span`,{className:[`wui-floating-stack-item wui-floating-stack-item--primary`,i].filter(Boolean).join(` `),style:a,children:A(u,{className:`wui-floating-btn`,onClick:e,"aria-label":o,"aria-haspopup":`dialog`,"aria-expanded":t,tooltip:o,tooltipPlacement:n===`start`?`end`:`start`,children:A(g,{name:r,size:24})})}),s):null}function G({tokens:e,resolveLink:t,linkComponent:n}){return e.map(e=>{switch(e.type){case`code`:return A(`code`,{children:e.text},e.key);case`strong`:return A(`strong`,{children:A(G,{tokens:e.children,resolveLink:t,linkComponent:n})},e.key);case`em`:return A(`em`,{children:A(G,{tokens:e.children,resolveLink:t,linkComponent:n})},e.key);case`link`:{let r=A(G,{tokens:e.children,resolveLink:t,linkComponent:n}),a=i(e.href,t);return a?A(_,{href:a,linkComponent:n,animation:`static`,children:r},e.key):A(`span`,{children:r},e.key)}default:return A(C,{children:e.text},e.key)}})}function K({text:e,resolveLink:t,linkComponent:n}){return A(G,{tokens:s(e),resolveLink:t,linkComponent:n})}function q({block:e,resolveLink:t,linkComponent:n}){let r=e=>A(K,{text:e,resolveLink:t,linkComponent:n});switch(e.type){case`heading`:return A(`p`,{className:`fw-semibold mb-2`,children:r(e.text)});case`rule`:return A(`hr`,{className:`my-2`});case`code`:return A(`pre`,{className:`wui-text-sm mb-2`,children:A(`code`,{children:e.text})});case`list`:{let t=e.items.map((e,t)=>A(`li`,{children:r(e)},t));return e.ordered?A(`ol`,{className:`mb-2 ps-4`,start:e.start===1?void 0:e.start,children:t}):A(`ul`,{className:`mb-2 ps-4`,children:t})}case`table`:return A(m,{columns:e.header.map((e,t)=>({key:`c${t}`,label:r(e),render:e=>r(e.cells[t]??``)})),rows:e.rows.map((e,t)=>({id:t,cells:e})),density:`compact`,empty:null,wrapperClassName:`mb-2`});default:return A(`p`,{className:`mb-2`,children:e.lines.map((e,t)=>j(`span`,{children:[t>0&&A(`br`,{}),r(e)]},t))})}}function J({text:e,resolveLink:t,linkComponent:n,className:r}){let i=o(e);return A(`div`,{className:[`wui-text-sm text-break`,r].filter(Boolean).join(` `),children:i.map(e=>A(q,{block:e,resolveLink:t,linkComponent:n},e.key))})}function Y({rating:e=null,onRate:t,noteMaxLength:n=1e3,labels:r}){let i=a(r),o=E(),[s,c]=O(!1),[d,f]=O(!1),[p,m]=O(``),[h,g]=O(``),[_,v]=O(!1);async function y(e,n){c(!0),g(``);try{await t(e,n),f(e===`Down`&&n===void 0),v(e===`Up`||n!==void 0),n!==void 0&&m(``)}catch{g(i.ratingFailed)}finally{c(!1)}}return j(`div`,{className:`d-flex flex-column gap-2`,children:[j(`div`,{className:`d-flex flex-wrap align-items-center gap-1`,children:[A(u,{size:`sm`,variant:e===`Up`?`subtle`:`ghost`,leftIcon:`check`,"aria-pressed":e===`Up`,disabled:s,onClick:()=>y(`Up`),children:i.rateUp}),A(u,{size:`sm`,variant:e===`Down`?`subtle`:`ghost`,leftIcon:`x`,"aria-pressed":e===`Down`,disabled:s,onClick:()=>y(`Down`),children:i.rateDown}),_&&!d&&A(`span`,{className:`wui-text-xs text-body-secondary`,role:`status`,children:i.rated})]}),h&&A(l,{size:`sm`,variant:`danger`,children:h}),d&&j(`form`,{className:`d-flex flex-column gap-2`,onSubmit:e=>{e.preventDefault(),y(`Down`,p)},children:[A(x,{id:`${o}-note`,label:i.ratingNote,hint:i.ratingNoteHint,rows:2,maxLength:n,value:p,onChange:e=>m(e.target.value)}),j(`div`,{className:`d-flex gap-2`,children:[A(u,{type:`submit`,size:`sm`,loading:s,children:i.ratingNoteSend}),A(u,{size:`sm`,variant:`secondary`,disabled:s,onClick:()=>{f(!1),v(!0)},children:i.ratingNoteSkip})]})]})]})}var X={maxWidth:`85%`,whiteSpace:`pre-wrap`,overflowWrap:`anywhere`};function Z({turn:e,onRate:t,resolveLink:n,linkComponent:r,confirmAction:i,onViewTicket:o,renderReply:s,labels:c}){let u=a(c),f=e.streaming&&!e.answer;return j(`li`,{className:`d-flex flex-column gap-2`,children:[e.question&&j(`div`,{className:`align-self-end`,style:X,children:[j(`span`,{className:`visually-hidden`,children:[u.you,`: `]}),A(d,{padding:`sm`,variant:`muted`,className:`wui-text-sm`,children:e.question})]}),j(`div`,{className:`d-flex flex-column gap-2`,style:{minWidth:0},children:[j(`span`,{className:`visually-hidden`,children:[u.assistant,`: `]}),A(`div`,{"aria-live":`polite`,"aria-busy":e.streaming,children:f?j(`span`,{className:`d-inline-flex align-items-center gap-2 wui-text-sm text-body-secondary`,children:[A(b,{size:`sm`,label:u.thinking}),A(`span`,{"aria-hidden":`true`,children:u.thinking})]}):e.answer&&(s?s(e,{streaming:!!e.streaming}):A(J,{text:e.answer,resolveLink:n,linkComponent:r}))}),e.error&&A(l,{size:`sm`,variant:`danger`,children:e.error.message}),i&&!e.streaming&&e.actions.map(e=>A(F,{action:e,confirmAction:i,onViewTicket:o,labels:c},e.token)),t&&e.messageId&&!e.streaming&&A(Y,{rating:e.rating,onRate:(n,r)=>t(e.id,n,r),labels:c})]})]})}function Q({turns:e,empty:t,onRate:n,resolveLink:r,linkComponent:i,confirmAction:o,onViewTicket:s,renderReply:c,labels:l}){let u=a(l),d=D(null),f=e[e.length-1];return T(()=>{d.current?.scrollIntoView({block:`end`})},[e.length,f?.answer,f?.error,f?.actions]),e.length===0?t??A(h,{icon:`sparkles`,size:`sm`,title:u.emptyTitle,text:u.emptyText}):j(k,{children:[A(`ol`,{className:`list-unstyled d-flex flex-column gap-3 mb-0`,"aria-label":u.thread,children:e.map(e=>A(Z,{turn:e,onRate:n,resolveLink:r,linkComponent:i,confirmAction:o,onViewTicket:s,renderReply:c,labels:l},e.id))}),A(`div`,{ref:d})]})}function ee({chat:e,open:t,onClose:n,title:r,titleIcon:i=`sparkles`,headerActions:o,empty:s,disclaimer:u,maxLength:d=4e3,allowanceThreshold:f=10,width:p=`440px`,resolveLink:m,linkComponent:h,confirmAction:_,onViewTicket:y,rating:x=!0,renderReply:S,labels:C}){let w=a(C),E=D(null),{refreshAllowance:O}=e;T(()=>{t&&O().catch(()=>{})},[t,O]);let k=e.messagesLeftToday,M=r??w.panelTitle;return A(v,{show:t,onHide:n,side:`right`,width:p,header:j(`div`,{className:`drawer-header`,children:[j(`div`,{className:`drawer-title`,children:[i&&A(`span`,{className:`drawer-title-ic`,children:A(g,{name:i,size:18})}),M]}),j(`div`,{className:`d-flex align-items-center gap-1`,children:[o,A(c,{icon:`plus`,label:w.newChat,onClick:e.newConversation,disabled:e.turns.length===0&&!e.loading}),A(c,{icon:`x`,label:w.close,onClick:n})]})]}),footer:j(`div`,{className:`d-flex flex-column gap-2`,children:[k!==null&&k<=f&&A(`p`,{className:`wui-text-xs text-body-secondary mb-0`,role:`status`,children:w.allowance(k)}),A(I,{onSubmit:e.submit,busy:e.streaming||e.loading,disabled:k===0,maxLength:d,inputRef:E,labels:C}),A(`p`,{className:`wui-text-xs text-body-secondary mb-0`,children:u??w.disclaimer})]}),ariaLabel:typeof M==`string`?M:w.panelTitle,onEntered:()=>E.current?.focus(),children:e.loading?A(`div`,{className:`d-flex justify-content-center py-4`,children:A(b,{label:w.loadingConversation})}):e.loadError?A(l,{variant:`danger`,children:e.loadError.message}):A(Q,{turns:e.turns,empty:s,onRate:x?e.rate:void 0,resolveLink:m,linkComponent:h,confirmAction:_,onViewTicket:y,renderReply:S,labels:C})})}var te=/\[([^[\]]*)\](?!\()/g;function ne(e,t){let n=[],r=0;for(let i of e.matchAll(te)){let a=i[1];a===``||!t(a)||(i.index>r&&n.push({text:e.slice(r,i.index)}),n.push({citation:a}),r=i.index+i[0].length)}return r<e.length&&n.push({text:e.slice(r)}),n}function re({citation:e,label:t,ariaLabel:n,onOpen:r}){return A(f,{label:t??e,size:`sm`,tone:`primary`,variant:`outline`,leadingIcon:`book-1`,"aria-label":n??e,onClick:()=>r(e)})}function ie({title:e,subtitle:t,lines:n,note:r,onConfirm:i,labels:o}){let s=a(o),[c,f]=O(`ready`),[p,m]=O(null),[h,g]=O(``);if(c===`dismissed`)return A(`p`,{className:`wui-text-sm text-body-secondary mb-0`,children:s.actionDismissed});if(c===`done`)return A(l,{variant:`success`,role:`status`,size:`sm`,children:p?.message||s.actionDone});async function _(){f(`sending`),g(``);try{let e=await i();m(e??null),f(`done`)}catch(e){g(e?.message||s.actionFailed),f(`ready`)}}let v=c===`sending`;return A(d,{padding:`sm`,className:`border`,title:e,subtitle:t||void 0,children:j(`div`,{className:`d-flex flex-column gap-2`,children:[(n??[]).map((e,t)=>A(`p`,{className:`wui-text-sm mb-0`,style:{whiteSpace:`pre-wrap`,overflowWrap:`anywhere`},children:e},t)),A(`p`,{className:`wui-text-xs text-body-secondary mb-0`,children:r??s.actionNote}),h&&A(l,{size:`sm`,variant:`danger`,children:h}),j(`div`,{className:`d-flex flex-wrap gap-2`,children:[A(u,{size:`sm`,loading:v,onClick:_,children:s.actionConfirm}),A(u,{size:`sm`,variant:`secondary`,disabled:v,onClick:()=>f(`dismissed`),children:s.actionDismiss})]})]})})}function $(e){return{code:e?.code||`unknown`,message:e?.message||`Something went wrong. Please try again.`,resetsAtUtc:e?.resetsAtUtc??null}}function ae(e){if(!e)return[];let t=JSON.parse(e);return Array.isArray(t)?t:[]}function oe(e){let t=[];for(let n of e??[]){if(n.role===`User`){t.push({id:n.publicId,question:n.content,answer:``,streaming:!1,step:null,error:null,actions:[],messageId:null,rating:null,ratingNote:null});continue}let e=t[t.length-1],r={answer:n.content,actions:ae(n.actionsJson),messageId:n.publicId,rating:n.rating??null,ratingNote:n.ratingNote??null};e&&e.messageId===null&&e.answer===``?Object.assign(e,r):t.push({id:n.publicId,question:``,streaming:!1,step:null,error:null,...r})}return t}function se({client:e,pageContext:t}){let[n,r]=O([]),[i,a]=O(null),[o,s]=O(null),[c,l]=O(!1),[u,d]=O(null),f=D(null),p=D(0),m=D(0),h=D(t);h.current=t;let g=D(null);g.current=i;let _=D(n);_.current=n;let v=w(()=>{p.current+=1,f.current?.abort(),f.current=null},[]);T(()=>v,[v]);let y=w((e,t)=>{r(n=>n.map(n=>n.id===e?{...n,...typeof t==`function`?t(n):t}:n))},[]),b=w(async t=>{let n=typeof t==`string`?t.trim():``;if(!n||f.current)return;let i=p.current,o=new AbortController;f.current=o,m.current+=1;let c=`turn-${m.current}`;r(e=>[...e,{id:c,question:n,answer:``,streaming:!0,step:null,error:null,actions:[],messageId:null,rating:null,ratingNote:null}]);let l=()=>i===p.current&&!o.signal.aborted;try{let t=await e.sendMessage({message:n,conversationId:g.current,pageContext:h.current},{signal:o.signal,onEvent:(e,t)=>{l()&&(e===`delta`?y(c,e=>({answer:e.answer+(t?.text??``),step:null})):e===`reset`?y(c,{answer:``,step:null}):e===`tool`?y(c,{step:typeof t?.toolName==`string`&&t.toolName?t.toolName:null}):e===`actions`&&y(c,{actions:Array.isArray(t?.actions)?t.actions:[]}))}});if(!l())return;y(c,{answer:t.reply,messageId:t.messageId??null,streaming:!1,step:null}),g.current=t.conversationId,a(t.conversationId),s(t.messagesLeftToday??null)}catch(e){if(!l())return;y(c,{answer:``,actions:[],streaming:!1,step:null,error:$(e)}),e?.code===`daily-limit`&&s(0),e?.code===`conversation-not-found`&&(g.current=null,a(null))}finally{f.current===o&&(f.current=null)}},[e,y]),x=w(async t=>{v();let n=p.current;r([]),a(null),d(null),l(!0);try{let i=await e.getConversation(t);if(n!==p.current)return;r(oe(i.messages)),a(i.publicId)}catch(e){if(n!==p.current)return;d($(e))}finally{n===p.current&&l(!1)}},[v,e]),S=w(()=>{v(),r([]),a(null),d(null),l(!1)},[v]),C=w(()=>{v(),r([]),a(null),s(null),d(null),l(!1)},[v]),E=w(async()=>{let t=p.current,n=await e.getAllowance();t===p.current&&s(n?.messagesLeftToday??null)},[e]),k=w(async(t,n,r)=>{let i=_.current.find(e=>e.id===t),a=g.current;if(!i?.messageId||!a)throw Error(`Only a stored reply can be rated.`);let o={rating:i.rating,ratingNote:i.ratingNote},s=typeof r==`string`&&r.trim()?r.trim():null;y(t,{rating:n,ratingNote:s});try{await e.rateMessage(a,i.messageId,{rating:n,note:s})}catch(e){throw y(t,o),e}},[e,y]);return{turns:n,conversationId:i,messagesLeftToday:o,streaming:n.some(e=>e.streaming),loading:c,loadError:u,submit:b,openConversation:x,newConversation:S,rate:k,refreshAllowance:E,reset:C}}export{F as ActionCard,e as ChatApiError,I as ChatComposer,B as ChatConversationList,U as ChatLauncher,J as ChatMarkdown,Z as ChatMessage,ee as ChatPanel,Q as ChatThread,re as CitationChip,ie as ConfirmCard,t as DEFAULT_CHAT_LABELS,Y as ReplyRating,n as createChatClient,r as createSseParser,ne as splitCitations,se as useChat};
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Splits reply text at its `[inner]` runs. A run whose inner text `isCitation` accepts becomes
3
+ * `{ citation }`; everything else stays text: a markdown link `[text](url)`, an empty `[]`, and a
4
+ * run the check rejects.
5
+ *
6
+ * @param {string} text
7
+ * @param {(inner: string) => boolean} isCitation
8
+ * @returns {Array<{ text: string } | { citation: string }>}
9
+ */
10
+ export declare function splitCitations(text: string, isCitation: (inner: string) => boolean): Array<{
11
+ text: string;
12
+ } | {
13
+ citation: string;
14
+ }>;
15
+ /**
16
+ * A citation the assistant wrote as `[inner]`: a chip that opens the source it names.
17
+ *
18
+ * @param {object} props
19
+ * @param {string} props.citation
20
+ * @param {string} [props.label] Text on the chip; defaults to the citation.
21
+ * @param {string} [props.ariaLabel] Accessible label; defaults to the citation.
22
+ * @param {(citation: string) => void} props.onOpen
23
+ */
24
+ export default function CitationChip({ citation, label, ariaLabel, onOpen }: {
25
+ citation: string;
26
+ label?: string;
27
+ ariaLabel?: string;
28
+ onOpen: (citation: string) => void;
29
+ }): import("react").JSX.Element;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * One general card for an action the assistant prepared. Nothing happens until the person confirms.
3
+ * The card moves from ready to sending to done, or to dismissed when the person says not now. A
4
+ * failed confirm shows its message and returns to ready, so the person can try again.
5
+ *
6
+ * @param {object} props
7
+ * @param {string} props.title
8
+ * @param {string} [props.subtitle]
9
+ * @param {string[]} [props.lines] One paragraph per entry, shown above the note.
10
+ * @param {string} [props.note] Replaces the default line saying nothing is sent until the person confirms.
11
+ * @param {() => Promise<{ message?: string } | void>} props.onConfirm Sends the person's yes; resolves to
12
+ * an optional message for the done state. A rejection's `message` is shown when present.
13
+ * @param {Partial<typeof import('@webority/ui-elements/chat-core').DEFAULT_CHAT_LABELS>} [props.labels]
14
+ */
15
+ export default function ConfirmCard({ title, subtitle, lines, note, onConfirm, labels: labelsProp }: {
16
+ title: string;
17
+ subtitle?: string;
18
+ lines?: string[];
19
+ note?: string;
20
+ onConfirm: () => Promise<{
21
+ message?: string;
22
+ } | void>;
23
+ labels?: Partial<typeof import('@webority/ui-elements/chat-core').DEFAULT_CHAT_LABELS>;
24
+ }): import("react").JSX.Element;
@@ -6,6 +6,8 @@ export { default as ChatLauncher } from "./components/ChatLauncher.jsx";
6
6
  export { default as ChatMessage } from "./components/ChatMessage.jsx";
7
7
  export { default as ChatPanel } from "./components/ChatPanel.jsx";
8
8
  export { default as ChatThread } from "./components/ChatThread.jsx";
9
+ export { default as CitationChip, splitCitations } from "./components/CitationChip.jsx";
10
+ export { default as ConfirmCard } from "./components/ConfirmCard.jsx";
9
11
  export { default as ReplyRating } from "./components/ReplyRating.jsx";
10
12
  export { ChatMarkdown } from "./markdown.jsx";
11
13
  export { useChat } from "./useChat.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webority/chat-react",
3
- "version": "0.65.0",
3
+ "version": "0.67.0",
4
4
  "description": "Webority AI assistant for React portals: a streaming chat client, a store-agnostic chat hook, and the launcher, panel, thread, rating and support action card, built on @webority/ui-react.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",
@@ -30,8 +30,8 @@
30
30
  "react": "^19.0.0",
31
31
  "react-bootstrap": "^2.10.0",
32
32
  "react-dom": "^19.0.0",
33
- "@webority/ui-elements": "0.65.0",
34
- "@webority/ui-react": "0.65.0"
33
+ "@webority/ui-elements": "0.67.0",
34
+ "@webority/ui-react": "0.67.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@testing-library/dom": "10.4.2",
@@ -49,8 +49,8 @@
49
49
  "typescript": "^7.0.2",
50
50
  "vite": "^8.0.12",
51
51
  "vitest": "5.0.1",
52
- "@webority/ui-elements": "0.65.0",
53
- "@webority/ui-react": "0.65.0"
52
+ "@webority/ui-elements": "0.67.0",
53
+ "@webority/ui-react": "0.67.0"
54
54
  },
55
55
  "scripts": {
56
56
  "build": "vite build && tsc -p tsconfig.json",