@vjdesigns/vjdesigns-ui 1.5.0 → 2.1.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 +781 -723
- package/dist/ai/llms-full.txt +1003 -923
- package/dist/ai/llms.txt +2 -1
- package/dist/ai/registry.json +340 -121
- package/dist/components/data-display/Chat/Chat.cjs.js +1 -0
- package/dist/components/data-display/Chat/Chat.d.ts +114 -0
- package/dist/components/data-display/Chat/Chat.mjs +301 -0
- package/dist/components/data-display/Chat/Chat.module.css.cjs.js +1 -0
- package/dist/components/data-display/Chat/Chat.module.css.mjs +32 -0
- package/dist/components/data-display/Chat/index.d.ts +2 -0
- package/dist/components/data-display/Chat/streams.cjs.js +4 -0
- package/dist/components/data-display/Chat/streams.d.ts +32 -0
- package/dist/components/data-display/Chat/streams.mjs +35 -0
- package/dist/components/data-display/DataGrid/DataGrid.module.css.cjs.js +1 -1
- package/dist/components/data-display/DataGrid/DataGrid.module.css.mjs +1 -1
- package/dist/components/data-display/VirtualList/VirtualList.module.css.cjs.js +1 -1
- package/dist/components/data-display/VirtualList/VirtualList.module.css.mjs +1 -1
- package/dist/components/feedback/ErrorSummary/ErrorSummary.module.css.cjs.js +1 -1
- package/dist/components/feedback/ErrorSummary/ErrorSummary.module.css.mjs +1 -1
- package/dist/components/forms/Combobox/Combobox.cjs.js +1 -1
- package/dist/components/forms/Combobox/Combobox.mjs +5 -5
- package/dist/components/forms/DateTimePicker/DateTimePicker.module.css.cjs.js +1 -1
- package/dist/components/forms/DateTimePicker/DateTimePicker.module.css.mjs +1 -1
- package/dist/components/forms/Rating/Rating.module.css.cjs.js +1 -1
- package/dist/components/forms/Rating/Rating.module.css.mjs +1 -1
- package/dist/components/forms/TagInput/TagInput.cjs.js +1 -1
- package/dist/components/forms/TagInput/TagInput.mjs +5 -5
- package/dist/components/forms/TimePicker/TimePicker.module.css.cjs.js +1 -1
- package/dist/components/forms/TimePicker/TimePicker.module.css.mjs +1 -1
- package/dist/components/layout/ResizablePanels/ResizablePanels.cjs.js +1 -1
- package/dist/components/layout/ResizablePanels/ResizablePanels.mjs +1 -0
- package/dist/components/layout/ResizablePanels/ResizablePanels.module.css.cjs.js +1 -1
- package/dist/components/layout/ResizablePanels/ResizablePanels.module.css.mjs +1 -1
- package/dist/components/layout/ScrollArea/ScrollArea.module.css.cjs.js +1 -1
- package/dist/components/layout/ScrollArea/ScrollArea.module.css.mjs +1 -1
- package/dist/components/navigation/ContextMenu/ContextMenu.module.css.cjs.js +1 -1
- package/dist/components/navigation/ContextMenu/ContextMenu.module.css.mjs +1 -1
- package/dist/components/overlays/HoverCard/HoverCard.module.css.cjs.js +1 -1
- package/dist/components/overlays/HoverCard/HoverCard.module.css.mjs +2 -2
- package/dist/components/primitives/Button/Button.cjs.js +1 -1
- package/dist/components/primitives/Button/Button.mjs +37 -37
- package/dist/components/utilities/LocaleProvider/LocaleProvider.module.css.cjs.js +1 -1
- package/dist/components/utilities/LocaleProvider/LocaleProvider.module.css.mjs +1 -1
- package/dist/components/utilities/Theme/Theme.cjs.js +1 -1
- package/dist/components/utilities/Theme/Theme.d.ts +6 -6
- package/dist/components/utilities/Theme/Theme.mjs +49 -45
- package/dist/hooks/useFormValidation.cjs.js +1 -1
- package/dist/hooks/useFormValidation.mjs +1 -1
- package/dist/i18n/en.cjs.js +1 -1
- package/dist/i18n/en.mjs +71 -0
- package/dist/i18n/types.d.ts +91 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +108 -106
- package/dist/locales/ar.cjs.js +1 -1
- package/dist/locales/ar.mjs +71 -0
- package/dist/locales/bn.cjs.js +1 -1
- package/dist/locales/bn.mjs +71 -0
- package/dist/locales/cs.cjs.js +1 -1
- package/dist/locales/cs.mjs +71 -0
- package/dist/locales/da.cjs.js +1 -1
- package/dist/locales/da.mjs +71 -0
- package/dist/locales/de.cjs.js +1 -1
- package/dist/locales/de.mjs +71 -0
- package/dist/locales/el.cjs.js +1 -1
- package/dist/locales/el.mjs +71 -0
- package/dist/locales/es.cjs.js +1 -1
- package/dist/locales/es.mjs +71 -0
- package/dist/locales/fa.cjs.js +1 -1
- package/dist/locales/fa.mjs +71 -0
- package/dist/locales/fi.cjs.js +1 -1
- package/dist/locales/fi.mjs +71 -0
- package/dist/locales/fr.cjs.js +1 -1
- package/dist/locales/fr.mjs +71 -0
- package/dist/locales/he.cjs.js +1 -1
- package/dist/locales/he.mjs +71 -0
- package/dist/locales/hi.cjs.js +1 -1
- package/dist/locales/hi.mjs +71 -0
- package/dist/locales/hu.cjs.js +1 -1
- package/dist/locales/hu.mjs +71 -0
- package/dist/locales/id.cjs.js +1 -1
- package/dist/locales/id.mjs +71 -0
- package/dist/locales/it.cjs.js +1 -1
- package/dist/locales/it.mjs +71 -0
- package/dist/locales/ja.cjs.js +1 -1
- package/dist/locales/ja.mjs +71 -0
- package/dist/locales/ko.cjs.js +1 -1
- package/dist/locales/ko.mjs +71 -0
- package/dist/locales/nb.cjs.js +1 -1
- package/dist/locales/nb.mjs +71 -0
- package/dist/locales/nl.cjs.js +1 -1
- package/dist/locales/nl.mjs +71 -0
- package/dist/locales/pl.cjs.js +1 -1
- package/dist/locales/pl.mjs +71 -0
- package/dist/locales/pt-BR.cjs.js +1 -1
- package/dist/locales/pt-BR.mjs +71 -0
- package/dist/locales/ro.cjs.js +1 -1
- package/dist/locales/ro.mjs +71 -0
- package/dist/locales/ru.cjs.js +1 -1
- package/dist/locales/ru.mjs +71 -0
- package/dist/locales/sv.cjs.js +1 -1
- package/dist/locales/sv.mjs +71 -0
- package/dist/locales/th.cjs.js +1 -1
- package/dist/locales/th.mjs +71 -0
- package/dist/locales/tr.cjs.js +1 -1
- package/dist/locales/tr.mjs +71 -0
- package/dist/locales/uk.cjs.js +1 -1
- package/dist/locales/uk.mjs +71 -0
- package/dist/locales/ur.cjs.js +1 -1
- package/dist/locales/ur.mjs +71 -0
- package/dist/locales/vi.cjs.js +1 -1
- package/dist/locales/vi.mjs +71 -0
- package/dist/locales/zh-Hans.cjs.js +1 -1
- package/dist/locales/zh-Hans.mjs +71 -0
- package/dist/locales/zh-Hant.cjs.js +1 -1
- package/dist/locales/zh-Hant.mjs +71 -0
- package/dist/utils/brandPalette.cjs.js +3 -3
- package/dist/utils/brandPalette.d.ts +4 -2
- package/dist/utils/brandPalette.mjs +20 -20
- package/dist/vjdesigns-ui.css +1 -1
- package/package.json +90 -88
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=require("../../../hooks/useControllableState.cjs.js"),t=require("../../utilities/LocaleProvider/LocaleProvider.cjs.js"),n=require("../../../hooks/useClipboard.cjs.js"),r=require("../../../hooks/useEnvironment.cjs.js"),i=require("../../../utils/cx.cjs.js"),a=require("../../../utils/announce.cjs.js"),o=require("../../utilities/VisuallyHidden/VisuallyHidden.cjs.js"),s=require("../../primitives/Button/Button.cjs.js"),c=require("../../primitives/Icon/Icon.cjs.js"),l=require("../../layout/ScrollArea/ScrollArea.cjs.js"),ee=require("../../forms/Textarea/Textarea.cjs.js"),u=require("./Chat.module.css.cjs.js");let d=require("react"),f=require("react/jsx-runtime");var te=48,ne=typeof window<`u`?d.useLayoutEffect:d.useEffect;function re(e){return e!=null&&typeof e[Symbol.asyncIterator]==`function`}var ie=()=>(0,f.jsx)(c.Icon,{children:(0,f.jsx)(`rect`,{x:`7`,y:`7`,width:`10`,height:`10`,rx:`2`,fill:`currentColor`,stroke:`none`})}),p=({messages:p,defaultMessages:ae,onMessagesChange:oe,onSend:m,onStop:se,onError:h,draft:ce,defaultDraft:le,onDraftChange:ue,suggestions:g,emptyState:de,renderContent:_,assistantName:fe,assistantAvatar:pe,userAvatar:v,copyable:y=!0,disclaimer:b,placeholder:me,maxLength:x,disabled:S=!1,labels:he,className:ge,"aria-label":_e,...C})=>{let w={...t.useMessages().chat,...he},T=fe??w.assistant,ve=r.useReducedMotion(),E=(0,d.useId)(),D=`${E}-hint`,[O,k]=e.useControllableState({value:p,defaultValue:ae??[],onChange:oe}),A=(0,d.useRef)(O),j=(0,d.useRef)(O);O!==j.current&&(j.current=O,A.current=O);let M=(0,d.useCallback)(e=>{let t=e(A.current);A.current=t,k(t)},[k]),N=(0,d.useCallback)((e,t)=>M(n=>n.map(n=>n.id===e?{...n,...t}:n)),[M]),P=(0,d.useRef)(0),F=()=>`${E}-${++P.current}`,[I,L]=e.useControllableState({value:ce,defaultValue:le??``,onChange:ue}),[R,z]=(0,d.useState)(!1),B=(0,d.useRef)(null),V=(0,d.useRef)(null),H=(0,d.useRef)(m);H.current=m;let U=(0,d.useRef)(h);U.current=h,(0,d.useEffect)(()=>()=>B.current?.abort(),[]);let W=(0,d.useRef)(null),G=(0,d.useRef)(!0),[ye,K]=(0,d.useState)(!0),be=()=>{let e=W.current;if(!e)return;let t=e.scrollHeight-e.scrollTop-e.clientHeight<=te;G.current=t,K(t)};ne(()=>{let e=W.current;e&&G.current&&(e.scrollTop=e.scrollHeight)},[O]);let xe=()=>{let e=W.current;e&&(G.current=!0,K(!0),e.scrollTo({top:e.scrollHeight,behavior:ve?`auto`:`smooth`}),V.current?.focus())},q=async(e,t)=>{let n=F();M(()=>[...e,{id:n,role:`assistant`,content:``,status:`streaming`}]),G.current=!0,K(!0),z(!0),a.announce(w.typing(T));let r=new AbortController;B.current=r;let i=``;try{let o=await H.current?.(t,{messages:e,signal:r.signal});if(typeof o==`string`)i=o;else if(re(o))for await(let e of o){if(r.signal.aborted)break;i+=e,N(n,{content:i})}else if(!r.signal.aborted){M(e=>e.filter(e=>e.id!==n));return}if(r.signal.aborted)throw r.signal.reason;N(n,{content:i,status:`done`}),a.announce(`${w.assistantSaid(T)} ${i}`)}catch(e){r.signal.aborted?(N(n,{content:i,status:`stopped`}),a.announce(w.stopped)):(U.current?.(e),N(n,{content:i,status:`error`}),a.announce(w.error))}finally{B.current===r&&(B.current=null),z(!1)}},J=e=>{let t=e.trim();!t||R||S||(L(``),q([...A.current,{id:F(),role:`user`,content:t,status:`done`}],t))},Y=()=>{B.current&&(B.current.abort(),se?.(),V.current?.focus())},Se=e=>{let t=A.current,n=t.findIndex(t=>t.id===e)-1;for(;n>=0&&t[n].role!==`user`;)n--;n<0||R||(q(t.slice(0,n+1),t[n].content),V.current?.focus())},X=e=>{e.preventDefault(),R?Y():J(I)},Ce=e=>{if(e.key===`Escape`&&R){e.preventDefault(),Y();return}e.key===`Enter`&&!e.shiftKey&&!e.nativeEvent.isComposing&&(e.preventDefault(),J(e.currentTarget.value))},{copy:we}=n.useClipboard(),[Z,Q]=(0,d.useState)(null);(0,d.useEffect)(()=>{if(Z===null)return;let e=window.setTimeout(()=>Q(null),2e3);return()=>window.clearTimeout(e)},[Z]);let Te=async e=>{await we(e.content)&&(Q(e.id),a.announce(w.copied))},$=O.filter(e=>e.role!==`system`).length===0,Ee=O[O.length-1],De=e=>{if(e.role===`system`)return(0,f.jsx)(`p`,{className:u.default.system,children:e.content},e.id);let t=e.role===`user`,n=e.status??`done`,r=n===`streaming`&&e.content===``,a=t?v:pe,l=!t&&!R&&e===Ee&&(n===`error`||n===`stopped`);return(0,f.jsxs)(`article`,{className:i.cx(u.default.message,t?u.default.user:u.default.assistant),"data-role":e.role,"data-status":n,"aria-busy":n===`streaming`||void 0,children:[a!=null&&(0,f.jsx)(`div`,{className:u.default.avatar,"aria-hidden":`true`,children:a}),(0,f.jsxs)(`div`,{className:u.default.body,children:[r?(0,f.jsxs)(`div`,{className:u.default.bubble,children:[(0,f.jsxs)(`span`,{className:u.default.dots,"aria-hidden":`true`,children:[(0,f.jsx)(`span`,{}),(0,f.jsx)(`span`,{}),(0,f.jsx)(`span`,{})]}),(0,f.jsx)(o.VisuallyHidden,{children:w.typing(T)})]}):e.content!==``&&(0,f.jsxs)(`div`,{className:u.default.bubble,children:[(0,f.jsxs)(o.VisuallyHidden,{children:[t?w.youSaid:w.assistantSaid(T),` `]}),_?_(e):(0,f.jsx)(`p`,{className:u.default.text,children:e.content})]}),n===`error`&&(0,f.jsxs)(`p`,{className:u.default.error,children:[(0,f.jsx)(c.Icon,{name:`error`,size:`sm`}),(0,f.jsx)(`span`,{children:e.error??w.error})]}),n===`stopped`&&(0,f.jsx)(`p`,{className:u.default.note,children:w.stopped}),!t&&(l||y&&n===`done`&&e.content!==``)&&(0,f.jsxs)(`div`,{className:u.default.actions,children:[y&&n===`done`&&e.content!==``&&(0,f.jsx)(s.IconButton,{variant:`ghost`,tone:`neutral`,size:`sm`,"aria-label":Z===e.id?w.copied:w.copy,onClick:()=>void Te(e),children:(0,f.jsx)(c.Icon,{name:Z===e.id?`check`:`copy`})}),l&&(0,f.jsx)(s.Button,{variant:`ghost`,tone:`neutral`,size:`sm`,startIcon:(0,f.jsx)(c.Icon,{name:`refresh`}),onClick:()=>Se(e.id),children:w.retry})]})]})]},e.id)};return(0,f.jsxs)(`section`,{...C,"aria-label":_e??(C[`aria-labelledby`]?void 0:w.region),className:i.cx(u.default.root,ge),children:[(0,f.jsxs)(`div`,{className:u.default.logWrap,children:[(0,f.jsx)(l.ScrollArea,{className:u.default.log,viewportRef:W,onViewportScroll:be,"aria-label":w.log,"aria-busy":R||void 0,tabIndex:0,children:(0,f.jsxs)(`div`,{className:u.default.messages,children:[$&&(0,f.jsxs)(`div`,{className:u.default.empty,children:[de??(0,f.jsx)(`p`,{className:u.default.emptyTitle,children:w.emptyTitle}),g&&g.length>0&&(0,f.jsx)(`div`,{role:`group`,"aria-label":w.suggestions,className:u.default.suggestions,children:g.map(e=>(0,f.jsx)(s.Button,{variant:`outline`,tone:`neutral`,size:`sm`,disabled:S,className:u.default.suggestion,onClick:()=>J(e),children:e},e))})]}),O.map(De)]})}),!ye&&!$&&(0,f.jsx)(s.IconButton,{variant:`soft`,tone:`neutral`,size:`sm`,className:u.default.jump,"aria-label":w.scrollToLatest,onClick:xe,children:(0,f.jsx)(c.Icon,{name:`arrow-down`})})]}),(0,f.jsxs)(`form`,{className:u.default.composer,onSubmit:X,children:[(0,f.jsxs)(`div`,{className:u.default.inputRow,children:[(0,f.jsx)(ee.Textarea,{ref:V,className:u.default.input,"aria-label":w.input,"aria-describedby":D,placeholder:me??w.placeholder,value:I,onValueChange:L,onKeyDown:Ce,autoResize:!0,rows:1,maxRows:6,maxLength:x,showCount:x!==void 0,disabled:S,enterKeyHint:`send`}),R?(0,f.jsx)(s.IconButton,{type:`submit`,variant:`soft`,tone:`neutral`,"aria-label":w.stop,children:(0,f.jsx)(ie,{})}):(0,f.jsx)(s.IconButton,{type:`submit`,"aria-label":w.send,disabled:S||I.trim()===``,children:(0,f.jsx)(c.Icon,{name:`arrow-up`})})]}),(0,f.jsx)(o.VisuallyHidden,{id:D,children:w.hint}),b!=null&&(0,f.jsx)(`p`,{className:u.default.disclaimer,children:b})]})]})};exports.Chat=p;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { ComponentPropsWithRef, ReactNode } from 'react';
|
|
2
|
+
import { Messages } from '../../../i18n/types';
|
|
3
|
+
/** Who wrote a message. `system` messages are shown as centered notes. */
|
|
4
|
+
export type ChatRole = "user" | "assistant" | "system";
|
|
5
|
+
/**
|
|
6
|
+
* Where a message is in its life. `streaming` shows a typing indicator while
|
|
7
|
+
* the content is empty; `error` shows the error and a Retry button;
|
|
8
|
+
* `stopped` marks a reply the user interrupted.
|
|
9
|
+
*/
|
|
10
|
+
export type ChatMessageStatus = "streaming" | "done" | "stopped" | "error";
|
|
11
|
+
/** One message in the conversation. Plain data, so it can be stored or sent to a backend as is. */
|
|
12
|
+
export interface ChatMessage {
|
|
13
|
+
/** Unique, stable id. */
|
|
14
|
+
id: string;
|
|
15
|
+
/** Who wrote it. */
|
|
16
|
+
role: ChatRole;
|
|
17
|
+
/** The text. Shown with line breaks kept, or through `renderContent`. */
|
|
18
|
+
content: string;
|
|
19
|
+
/** Message state. Treated as `done` when omitted. */
|
|
20
|
+
status?: ChatMessageStatus;
|
|
21
|
+
/** Error text for an `error` message. Defaults to the built-in error message. */
|
|
22
|
+
error?: string;
|
|
23
|
+
}
|
|
24
|
+
/** Passed to `onSend` along with the text. */
|
|
25
|
+
export interface ChatSendContext {
|
|
26
|
+
/** The conversation so far, ending with the new user message. */
|
|
27
|
+
messages: ChatMessage[];
|
|
28
|
+
/** Aborted when the user presses Stop or the Chat unmounts. Pass it to `fetch`. */
|
|
29
|
+
signal: AbortSignal;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* What `onSend` returns: the whole reply as a string, an async iterable of
|
|
33
|
+
* text chunks to stream it in (an `async function*`, or `readTextStream`),
|
|
34
|
+
* or nothing when you add the reply yourself through controlled `messages`.
|
|
35
|
+
*/
|
|
36
|
+
export type ChatSendResult = string | AsyncIterable<string> | void;
|
|
37
|
+
/** Built-in text of a Chat. Every key can be overridden with the `labels` prop. */
|
|
38
|
+
export type ChatLabels = Messages["chat"];
|
|
39
|
+
export interface ChatProps extends Omit<ComponentPropsWithRef<"section">, "children" | "onError"> {
|
|
40
|
+
/** Controlled conversation. */
|
|
41
|
+
messages?: ChatMessage[];
|
|
42
|
+
/** Initial conversation when uncontrolled. */
|
|
43
|
+
defaultMessages?: ChatMessage[];
|
|
44
|
+
/** Called with the whole conversation whenever it changes (new messages, every streamed chunk, status changes). */
|
|
45
|
+
onMessagesChange?: (messages: ChatMessage[]) => void;
|
|
46
|
+
/**
|
|
47
|
+
* Connects the Chat to your backend. Called with the user's text when they
|
|
48
|
+
* send a message (or retry). Return the reply as a string, stream it as an
|
|
49
|
+
* `AsyncIterable<string>`, or return nothing and add it yourself through
|
|
50
|
+
* controlled `messages`. Throwing (or rejecting) turns the reply into an
|
|
51
|
+
* error with a Retry button.
|
|
52
|
+
*/
|
|
53
|
+
onSend?: (text: string, context: ChatSendContext) => ChatSendResult | Promise<ChatSendResult>;
|
|
54
|
+
/** Called when the user stops a reply, after its `signal` is aborted. */
|
|
55
|
+
onStop?: () => void;
|
|
56
|
+
/** Called with whatever `onSend` threw, for logging. The user sees `labels.error` (or the message's `error`). */
|
|
57
|
+
onError?: (error: unknown) => void;
|
|
58
|
+
/** Controlled text of the message box. */
|
|
59
|
+
draft?: string;
|
|
60
|
+
/** Initial text of the message box when uncontrolled. */
|
|
61
|
+
defaultDraft?: string;
|
|
62
|
+
/** Called with the message box text on every edit. */
|
|
63
|
+
onDraftChange?: (draft: string) => void;
|
|
64
|
+
/** Prompts offered as buttons while the conversation is empty. Pressing one sends it. */
|
|
65
|
+
suggestions?: string[];
|
|
66
|
+
/** Shown while the conversation is empty, above the suggestions. Defaults to a short greeting (`labels.emptyTitle`). */
|
|
67
|
+
emptyState?: ReactNode;
|
|
68
|
+
/**
|
|
69
|
+
* Renders a message's content, e.g. through your Markdown renderer.
|
|
70
|
+
* Defaults to plain text with line breaks kept. Never render
|
|
71
|
+
* unsanitized HTML from a model or a user.
|
|
72
|
+
*/
|
|
73
|
+
renderContent?: (message: ChatMessage) => ReactNode;
|
|
74
|
+
/** Name of the assistant, read to screen readers ("Coach said:"). Defaults to `labels.assistant`. */
|
|
75
|
+
assistantName?: string;
|
|
76
|
+
/** Shown beside assistant messages (e.g. an `Avatar` or `Icon`). Decorative: hidden from assistive technology. */
|
|
77
|
+
assistantAvatar?: ReactNode;
|
|
78
|
+
/** Shown beside user messages. Decorative: hidden from assistive technology. */
|
|
79
|
+
userAvatar?: ReactNode;
|
|
80
|
+
/** Show a Copy button under finished assistant messages. @default true */
|
|
81
|
+
copyable?: boolean;
|
|
82
|
+
/** Small print under the message box, e.g. "AI can make mistakes." */
|
|
83
|
+
disclaimer?: ReactNode;
|
|
84
|
+
/** Placeholder of the message box. Defaults to `labels.placeholder`. */
|
|
85
|
+
placeholder?: string;
|
|
86
|
+
/** Maximum length of a message, in characters. Shows a counter near the limit. */
|
|
87
|
+
maxLength?: number;
|
|
88
|
+
/** Disables the message box and the suggestions. */
|
|
89
|
+
disabled?: boolean;
|
|
90
|
+
/** Overrides for the built-in text. */
|
|
91
|
+
labels?: Partial<ChatLabels>;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* A chat interface for an AI assistant (or a person), with no backend of its
|
|
95
|
+
* own: `onSend` connects it to any API and can stream the reply. Includes a
|
|
96
|
+
* scrolling conversation that follows new messages, an auto-growing message
|
|
97
|
+
* box (Enter sends, Shift+Enter adds a line), Stop and Retry, copy buttons,
|
|
98
|
+
* suggested prompts, and screen reader announcements of each reply.
|
|
99
|
+
*
|
|
100
|
+
* ```tsx
|
|
101
|
+
* <Chat
|
|
102
|
+
* style={{ blockSize: 560 }}
|
|
103
|
+
* onSend={async function* (text, { messages, signal }) {
|
|
104
|
+
* const res = await fetch("/api/chat", {
|
|
105
|
+
* method: "POST",
|
|
106
|
+
* body: JSON.stringify({ messages }),
|
|
107
|
+
* signal,
|
|
108
|
+
* });
|
|
109
|
+
* yield* readTextStream(res);
|
|
110
|
+
* }}
|
|
111
|
+
* />
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export declare const Chat: ({ messages: messagesProp, defaultMessages, onMessagesChange, onSend, onStop, onError, draft: draftProp, defaultDraft, onDraftChange, suggestions, emptyState, renderContent, assistantName: assistantNameProp, assistantAvatar, userAvatar, copyable, disclaimer, placeholder, maxLength, disabled, labels: labelsProp, className, "aria-label": ariaLabel, ...rest }: ChatProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import { useControllableState as e } from "../../../hooks/useControllableState.mjs";
|
|
2
|
+
import { useMessages as t } from "../../utilities/LocaleProvider/LocaleProvider.mjs";
|
|
3
|
+
import { useClipboard as n } from "../../../hooks/useClipboard.mjs";
|
|
4
|
+
import { useReducedMotion as r } from "../../../hooks/useEnvironment.mjs";
|
|
5
|
+
import { cx as i } from "../../../utils/cx.mjs";
|
|
6
|
+
import { announce as a } from "../../../utils/announce.mjs";
|
|
7
|
+
import { VisuallyHidden as o } from "../../utilities/VisuallyHidden/VisuallyHidden.mjs";
|
|
8
|
+
import { Button as s, IconButton as c } from "../../primitives/Button/Button.mjs";
|
|
9
|
+
import { Icon as l } from "../../primitives/Icon/Icon.mjs";
|
|
10
|
+
import { ScrollArea as u } from "../../layout/ScrollArea/ScrollArea.mjs";
|
|
11
|
+
import { Textarea as ee } from "../../forms/Textarea/Textarea.mjs";
|
|
12
|
+
import d from "./Chat.module.css.mjs";
|
|
13
|
+
import { useCallback as f, useEffect as p, useId as te, useLayoutEffect as ne, useRef as m, useState as h } from "react";
|
|
14
|
+
import { jsx as g, jsxs as _ } from "react/jsx-runtime";
|
|
15
|
+
//#region src/components/data-display/Chat/Chat.tsx
|
|
16
|
+
var re = 48, ie = typeof window < "u" ? ne : p;
|
|
17
|
+
function ae(e) {
|
|
18
|
+
return e != null && typeof e[Symbol.asyncIterator] == "function";
|
|
19
|
+
}
|
|
20
|
+
var oe = () => /* @__PURE__ */ g(l, { children: /* @__PURE__ */ g("rect", {
|
|
21
|
+
x: "7",
|
|
22
|
+
y: "7",
|
|
23
|
+
width: "10",
|
|
24
|
+
height: "10",
|
|
25
|
+
rx: "2",
|
|
26
|
+
fill: "currentColor",
|
|
27
|
+
stroke: "none"
|
|
28
|
+
}) }), v = ({ messages: ne, defaultMessages: v, onMessagesChange: se, onSend: y, onStop: ce, onError: b, draft: le, defaultDraft: ue, onDraftChange: de, suggestions: x, emptyState: fe, renderContent: S, assistantName: pe, assistantAvatar: me, userAvatar: he, copyable: C = !0, disclaimer: w, placeholder: ge, maxLength: T, disabled: E = !1, labels: _e, className: ve, "aria-label": ye, ...D }) => {
|
|
29
|
+
let O = {
|
|
30
|
+
...t().chat,
|
|
31
|
+
..._e
|
|
32
|
+
}, k = pe ?? O.assistant, be = r(), A = te(), j = `${A}-hint`, [M, N] = e({
|
|
33
|
+
value: ne,
|
|
34
|
+
defaultValue: v ?? [],
|
|
35
|
+
onChange: se
|
|
36
|
+
}), P = m(M), F = m(M);
|
|
37
|
+
M !== F.current && (F.current = M, P.current = M);
|
|
38
|
+
let I = f((e) => {
|
|
39
|
+
let t = e(P.current);
|
|
40
|
+
P.current = t, N(t);
|
|
41
|
+
}, [N]), L = f((e, t) => I((n) => n.map((n) => n.id === e ? {
|
|
42
|
+
...n,
|
|
43
|
+
...t
|
|
44
|
+
} : n)), [I]), xe = m(0), R = () => `${A}-${++xe.current}`, [z, B] = e({
|
|
45
|
+
value: le,
|
|
46
|
+
defaultValue: ue ?? "",
|
|
47
|
+
onChange: de
|
|
48
|
+
}), [V, H] = h(!1), U = m(null), W = m(null), G = m(y);
|
|
49
|
+
G.current = y;
|
|
50
|
+
let K = m(b);
|
|
51
|
+
K.current = b, p(() => () => U.current?.abort(), []);
|
|
52
|
+
let q = m(null), J = m(!0), [Se, Y] = h(!0), Ce = () => {
|
|
53
|
+
let e = q.current;
|
|
54
|
+
if (!e) return;
|
|
55
|
+
let t = e.scrollHeight - e.scrollTop - e.clientHeight <= re;
|
|
56
|
+
J.current = t, Y(t);
|
|
57
|
+
};
|
|
58
|
+
ie(() => {
|
|
59
|
+
let e = q.current;
|
|
60
|
+
e && J.current && (e.scrollTop = e.scrollHeight);
|
|
61
|
+
}, [M]);
|
|
62
|
+
let we = () => {
|
|
63
|
+
let e = q.current;
|
|
64
|
+
e && (J.current = !0, Y(!0), e.scrollTo({
|
|
65
|
+
top: e.scrollHeight,
|
|
66
|
+
behavior: be ? "auto" : "smooth"
|
|
67
|
+
}), W.current?.focus());
|
|
68
|
+
}, X = async (e, t) => {
|
|
69
|
+
let n = R();
|
|
70
|
+
I(() => [...e, {
|
|
71
|
+
id: n,
|
|
72
|
+
role: "assistant",
|
|
73
|
+
content: "",
|
|
74
|
+
status: "streaming"
|
|
75
|
+
}]), J.current = !0, Y(!0), H(!0), a(O.typing(k));
|
|
76
|
+
let r = new AbortController();
|
|
77
|
+
U.current = r;
|
|
78
|
+
let i = "";
|
|
79
|
+
try {
|
|
80
|
+
let o = await G.current?.(t, {
|
|
81
|
+
messages: e,
|
|
82
|
+
signal: r.signal
|
|
83
|
+
});
|
|
84
|
+
if (typeof o == "string") i = o;
|
|
85
|
+
else if (ae(o)) for await (let e of o) {
|
|
86
|
+
if (r.signal.aborted) break;
|
|
87
|
+
i += e, L(n, { content: i });
|
|
88
|
+
}
|
|
89
|
+
else if (!r.signal.aborted) {
|
|
90
|
+
I((e) => e.filter((e) => e.id !== n));
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (r.signal.aborted) throw r.signal.reason;
|
|
94
|
+
L(n, {
|
|
95
|
+
content: i,
|
|
96
|
+
status: "done"
|
|
97
|
+
}), a(`${O.assistantSaid(k)} ${i}`);
|
|
98
|
+
} catch (e) {
|
|
99
|
+
r.signal.aborted ? (L(n, {
|
|
100
|
+
content: i,
|
|
101
|
+
status: "stopped"
|
|
102
|
+
}), a(O.stopped)) : (K.current?.(e), L(n, {
|
|
103
|
+
content: i,
|
|
104
|
+
status: "error"
|
|
105
|
+
}), a(O.error));
|
|
106
|
+
} finally {
|
|
107
|
+
U.current === r && (U.current = null), H(!1);
|
|
108
|
+
}
|
|
109
|
+
}, Z = (e) => {
|
|
110
|
+
let t = e.trim();
|
|
111
|
+
!t || V || E || (B(""), X([...P.current, {
|
|
112
|
+
id: R(),
|
|
113
|
+
role: "user",
|
|
114
|
+
content: t,
|
|
115
|
+
status: "done"
|
|
116
|
+
}], t));
|
|
117
|
+
}, Q = () => {
|
|
118
|
+
U.current && (U.current.abort(), ce?.(), W.current?.focus());
|
|
119
|
+
}, Te = (e) => {
|
|
120
|
+
let t = P.current, n = t.findIndex((t) => t.id === e) - 1;
|
|
121
|
+
for (; n >= 0 && t[n].role !== "user";) n--;
|
|
122
|
+
n < 0 || V || (X(t.slice(0, n + 1), t[n].content), W.current?.focus());
|
|
123
|
+
}, Ee = (e) => {
|
|
124
|
+
e.preventDefault(), V ? Q() : Z(z);
|
|
125
|
+
}, De = (e) => {
|
|
126
|
+
if (e.key === "Escape" && V) {
|
|
127
|
+
e.preventDefault(), Q();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing && (e.preventDefault(), Z(e.currentTarget.value));
|
|
131
|
+
}, { copy: Oe } = n(), [$, ke] = h(null);
|
|
132
|
+
p(() => {
|
|
133
|
+
if ($ === null) return;
|
|
134
|
+
let e = window.setTimeout(() => ke(null), 2e3);
|
|
135
|
+
return () => window.clearTimeout(e);
|
|
136
|
+
}, [$]);
|
|
137
|
+
let Ae = async (e) => {
|
|
138
|
+
await Oe(e.content) && (ke(e.id), a(O.copied));
|
|
139
|
+
}, je = M.filter((e) => e.role !== "system").length === 0, Me = M[M.length - 1], Ne = (e) => {
|
|
140
|
+
if (e.role === "system") return /* @__PURE__ */ g("p", {
|
|
141
|
+
className: d.system,
|
|
142
|
+
children: e.content
|
|
143
|
+
}, e.id);
|
|
144
|
+
let t = e.role === "user", n = e.status ?? "done", r = n === "streaming" && e.content === "", a = t ? he : me, u = !t && !V && e === Me && (n === "error" || n === "stopped");
|
|
145
|
+
return /* @__PURE__ */ _("article", {
|
|
146
|
+
className: i(d.message, t ? d.user : d.assistant),
|
|
147
|
+
"data-role": e.role,
|
|
148
|
+
"data-status": n,
|
|
149
|
+
"aria-busy": n === "streaming" || void 0,
|
|
150
|
+
children: [a != null && /* @__PURE__ */ g("div", {
|
|
151
|
+
className: d.avatar,
|
|
152
|
+
"aria-hidden": "true",
|
|
153
|
+
children: a
|
|
154
|
+
}), /* @__PURE__ */ _("div", {
|
|
155
|
+
className: d.body,
|
|
156
|
+
children: [
|
|
157
|
+
r ? /* @__PURE__ */ _("div", {
|
|
158
|
+
className: d.bubble,
|
|
159
|
+
children: [/* @__PURE__ */ _("span", {
|
|
160
|
+
className: d.dots,
|
|
161
|
+
"aria-hidden": "true",
|
|
162
|
+
children: [
|
|
163
|
+
/* @__PURE__ */ g("span", {}),
|
|
164
|
+
/* @__PURE__ */ g("span", {}),
|
|
165
|
+
/* @__PURE__ */ g("span", {})
|
|
166
|
+
]
|
|
167
|
+
}), /* @__PURE__ */ g(o, { children: O.typing(k) })]
|
|
168
|
+
}) : e.content !== "" && /* @__PURE__ */ _("div", {
|
|
169
|
+
className: d.bubble,
|
|
170
|
+
children: [/* @__PURE__ */ _(o, { children: [t ? O.youSaid : O.assistantSaid(k), " "] }), S ? S(e) : /* @__PURE__ */ g("p", {
|
|
171
|
+
className: d.text,
|
|
172
|
+
children: e.content
|
|
173
|
+
})]
|
|
174
|
+
}),
|
|
175
|
+
n === "error" && /* @__PURE__ */ _("p", {
|
|
176
|
+
className: d.error,
|
|
177
|
+
children: [/* @__PURE__ */ g(l, {
|
|
178
|
+
name: "error",
|
|
179
|
+
size: "sm"
|
|
180
|
+
}), /* @__PURE__ */ g("span", { children: e.error ?? O.error })]
|
|
181
|
+
}),
|
|
182
|
+
n === "stopped" && /* @__PURE__ */ g("p", {
|
|
183
|
+
className: d.note,
|
|
184
|
+
children: O.stopped
|
|
185
|
+
}),
|
|
186
|
+
!t && (u || C && n === "done" && e.content !== "") && /* @__PURE__ */ _("div", {
|
|
187
|
+
className: d.actions,
|
|
188
|
+
children: [C && n === "done" && e.content !== "" && /* @__PURE__ */ g(c, {
|
|
189
|
+
variant: "ghost",
|
|
190
|
+
tone: "neutral",
|
|
191
|
+
size: "sm",
|
|
192
|
+
"aria-label": $ === e.id ? O.copied : O.copy,
|
|
193
|
+
onClick: () => void Ae(e),
|
|
194
|
+
children: /* @__PURE__ */ g(l, { name: $ === e.id ? "check" : "copy" })
|
|
195
|
+
}), u && /* @__PURE__ */ g(s, {
|
|
196
|
+
variant: "ghost",
|
|
197
|
+
tone: "neutral",
|
|
198
|
+
size: "sm",
|
|
199
|
+
startIcon: /* @__PURE__ */ g(l, { name: "refresh" }),
|
|
200
|
+
onClick: () => Te(e.id),
|
|
201
|
+
children: O.retry
|
|
202
|
+
})]
|
|
203
|
+
})
|
|
204
|
+
]
|
|
205
|
+
})]
|
|
206
|
+
}, e.id);
|
|
207
|
+
};
|
|
208
|
+
return /* @__PURE__ */ _("section", {
|
|
209
|
+
...D,
|
|
210
|
+
"aria-label": ye ?? (D["aria-labelledby"] ? void 0 : O.region),
|
|
211
|
+
className: i(d.root, ve),
|
|
212
|
+
children: [/* @__PURE__ */ _("div", {
|
|
213
|
+
className: d.logWrap,
|
|
214
|
+
children: [/* @__PURE__ */ g(u, {
|
|
215
|
+
className: d.log,
|
|
216
|
+
viewportRef: q,
|
|
217
|
+
onViewportScroll: Ce,
|
|
218
|
+
"aria-label": O.log,
|
|
219
|
+
"aria-busy": V || void 0,
|
|
220
|
+
tabIndex: 0,
|
|
221
|
+
children: /* @__PURE__ */ _("div", {
|
|
222
|
+
className: d.messages,
|
|
223
|
+
children: [je && /* @__PURE__ */ _("div", {
|
|
224
|
+
className: d.empty,
|
|
225
|
+
children: [fe ?? /* @__PURE__ */ g("p", {
|
|
226
|
+
className: d.emptyTitle,
|
|
227
|
+
children: O.emptyTitle
|
|
228
|
+
}), x && x.length > 0 && /* @__PURE__ */ g("div", {
|
|
229
|
+
role: "group",
|
|
230
|
+
"aria-label": O.suggestions,
|
|
231
|
+
className: d.suggestions,
|
|
232
|
+
children: x.map((e) => /* @__PURE__ */ g(s, {
|
|
233
|
+
variant: "outline",
|
|
234
|
+
tone: "neutral",
|
|
235
|
+
size: "sm",
|
|
236
|
+
disabled: E,
|
|
237
|
+
className: d.suggestion,
|
|
238
|
+
onClick: () => Z(e),
|
|
239
|
+
children: e
|
|
240
|
+
}, e))
|
|
241
|
+
})]
|
|
242
|
+
}), M.map(Ne)]
|
|
243
|
+
})
|
|
244
|
+
}), !Se && !je && /* @__PURE__ */ g(c, {
|
|
245
|
+
variant: "soft",
|
|
246
|
+
tone: "neutral",
|
|
247
|
+
size: "sm",
|
|
248
|
+
className: d.jump,
|
|
249
|
+
"aria-label": O.scrollToLatest,
|
|
250
|
+
onClick: we,
|
|
251
|
+
children: /* @__PURE__ */ g(l, { name: "arrow-down" })
|
|
252
|
+
})]
|
|
253
|
+
}), /* @__PURE__ */ _("form", {
|
|
254
|
+
className: d.composer,
|
|
255
|
+
onSubmit: Ee,
|
|
256
|
+
children: [
|
|
257
|
+
/* @__PURE__ */ _("div", {
|
|
258
|
+
className: d.inputRow,
|
|
259
|
+
children: [/* @__PURE__ */ g(ee, {
|
|
260
|
+
ref: W,
|
|
261
|
+
className: d.input,
|
|
262
|
+
"aria-label": O.input,
|
|
263
|
+
"aria-describedby": j,
|
|
264
|
+
placeholder: ge ?? O.placeholder,
|
|
265
|
+
value: z,
|
|
266
|
+
onValueChange: B,
|
|
267
|
+
onKeyDown: De,
|
|
268
|
+
autoResize: !0,
|
|
269
|
+
rows: 1,
|
|
270
|
+
maxRows: 6,
|
|
271
|
+
maxLength: T,
|
|
272
|
+
showCount: T !== void 0,
|
|
273
|
+
disabled: E,
|
|
274
|
+
enterKeyHint: "send"
|
|
275
|
+
}), V ? /* @__PURE__ */ g(c, {
|
|
276
|
+
type: "submit",
|
|
277
|
+
variant: "soft",
|
|
278
|
+
tone: "neutral",
|
|
279
|
+
"aria-label": O.stop,
|
|
280
|
+
children: /* @__PURE__ */ g(oe, {})
|
|
281
|
+
}) : /* @__PURE__ */ g(c, {
|
|
282
|
+
type: "submit",
|
|
283
|
+
"aria-label": O.send,
|
|
284
|
+
disabled: E || z.trim() === "",
|
|
285
|
+
children: /* @__PURE__ */ g(l, { name: "arrow-up" })
|
|
286
|
+
})]
|
|
287
|
+
}),
|
|
288
|
+
/* @__PURE__ */ g(o, {
|
|
289
|
+
id: j,
|
|
290
|
+
children: O.hint
|
|
291
|
+
}),
|
|
292
|
+
w != null && /* @__PURE__ */ g("p", {
|
|
293
|
+
className: d.disclaimer,
|
|
294
|
+
children: w
|
|
295
|
+
})
|
|
296
|
+
]
|
|
297
|
+
})]
|
|
298
|
+
});
|
|
299
|
+
};
|
|
300
|
+
//#endregion
|
|
301
|
+
export { v as Chat };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e=`_root_1vnqg_8`,t=`_logWrap_1vnqg_18`,n=`_log_1vnqg_18`,r=`_messages_1vnqg_30`,i=`_empty_1vnqg_39`,a=`_emptyTitle_1vnqg_48`,o=`_suggestions_1vnqg_56`,s=`_suggestion_1vnqg_56`,c=`_message_1vnqg_30`,l=`_enter_1vnqg_1`,u=`_user_1vnqg_80`,d=`_assistant_1vnqg_85`,f=`_avatar_1vnqg_89`,p=`_body_1vnqg_94`,m=`_bubble_1vnqg_105`,h=`_text_1vnqg_128`,g=`_dots_1vnqg_134`,_=`_bounce_1vnqg_1`,v=`_error_1vnqg_185`,y=`_note_1vnqg_194`,b=`_actions_1vnqg_201`,x=`_system_1vnqg_207`,S=`_jump_1vnqg_217`,C=`_composer_1vnqg_230`,w=`_inputRow_1vnqg_238`,T=`_input_1vnqg_238`,E=`_disclaimer_1vnqg_248`,D={root:e,logWrap:t,log:n,messages:r,empty:i,emptyTitle:a,suggestions:o,suggestion:s,message:c,enter:l,user:u,assistant:d,avatar:f,body:p,bubble:m,text:h,dots:g,bounce:_,error:v,note:y,actions:b,system:x,jump:S,composer:C,inputRow:w,input:T,disclaimer:E};exports.actions=b,exports.assistant=d,exports.avatar=f,exports.body=p,exports.bounce=_,exports.bubble=m,exports.composer=C,exports.default=D,exports.disclaimer=E,exports.dots=g,exports.empty=i,exports.emptyTitle=a,exports.enter=l,exports.error=v,exports.input=T,exports.inputRow=w,exports.jump=S,exports.log=n,exports.logWrap=t,exports.message=c,exports.messages=r,exports.note=y,exports.root=e,exports.suggestion=s,exports.suggestions=o,exports.system=x,exports.text=h,exports.user=u;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/components/data-display/Chat/Chat.module.css
|
|
2
|
+
var e = "_root_1vnqg_8", t = "_logWrap_1vnqg_18", n = "_log_1vnqg_18", r = "_messages_1vnqg_30", i = "_empty_1vnqg_39", a = "_emptyTitle_1vnqg_48", o = "_suggestions_1vnqg_56", s = "_suggestion_1vnqg_56", c = "_message_1vnqg_30", l = "_enter_1vnqg_1", u = "_user_1vnqg_80", d = "_assistant_1vnqg_85", f = "_avatar_1vnqg_89", p = "_body_1vnqg_94", m = "_bubble_1vnqg_105", h = "_text_1vnqg_128", g = "_dots_1vnqg_134", _ = "_bounce_1vnqg_1", v = "_error_1vnqg_185", y = "_note_1vnqg_194", b = "_actions_1vnqg_201", x = "_system_1vnqg_207", S = "_jump_1vnqg_217", C = "_composer_1vnqg_230", w = "_inputRow_1vnqg_238", T = "_input_1vnqg_238", E = "_disclaimer_1vnqg_248", D = {
|
|
3
|
+
root: e,
|
|
4
|
+
logWrap: t,
|
|
5
|
+
log: n,
|
|
6
|
+
messages: r,
|
|
7
|
+
empty: i,
|
|
8
|
+
emptyTitle: a,
|
|
9
|
+
suggestions: o,
|
|
10
|
+
suggestion: s,
|
|
11
|
+
message: c,
|
|
12
|
+
enter: l,
|
|
13
|
+
user: u,
|
|
14
|
+
assistant: d,
|
|
15
|
+
avatar: f,
|
|
16
|
+
body: p,
|
|
17
|
+
bubble: m,
|
|
18
|
+
text: h,
|
|
19
|
+
dots: g,
|
|
20
|
+
bounce: _,
|
|
21
|
+
error: v,
|
|
22
|
+
note: y,
|
|
23
|
+
actions: b,
|
|
24
|
+
system: x,
|
|
25
|
+
jump: S,
|
|
26
|
+
composer: C,
|
|
27
|
+
inputRow: w,
|
|
28
|
+
input: T,
|
|
29
|
+
disclaimer: E
|
|
30
|
+
};
|
|
31
|
+
//#endregion
|
|
32
|
+
export { b as actions, d as assistant, f as avatar, p as body, _ as bounce, m as bubble, C as composer, D as default, E as disclaimer, g as dots, i as empty, a as emptyTitle, l as enter, v as error, T as input, w as inputRow, S as jump, n as log, t as logWrap, c as message, r as messages, y as note, e as root, s as suggestion, o as suggestions, x as system, h as text, u as user };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
function e(e){let t=e instanceof Response?e.body:e;if(!t)throw Error(`readTextStream: the response has no body to read.`);return t}async function*t(t){let n=e(t).getReader(),r=new TextDecoder;try{for(;;){let{done:e,value:t}=await n.read();if(e)break;let i=r.decode(t,{stream:!0});i&&(yield i)}let e=r.decode();e&&(yield e)}finally{n.releaseLock()}}async function*n(e){let n=``,r=function*(e){let t=n.split(/\r?\n\r?\n/);n=e?``:t.pop()??``;for(let e of t){let t=e.split(/\r?\n/).filter(e=>e.startsWith(`data:`)).map(e=>e.slice(5).replace(/^ /,``));t.length>0&&(yield t.join(`
|
|
2
|
+
`))}};for await(let i of t(e))n+=i,yield*r(!1);n+=`
|
|
3
|
+
|
|
4
|
+
`,yield*r(!0)}exports.readEventStream=n,exports.readTextStream=t;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helpers for turning a streaming HTTP response into the `AsyncIterable<string>`
|
|
3
|
+
* that `Chat`'s `onSend` can return. They read with `getReader()`, so they
|
|
4
|
+
* work in browsers without async iteration of `ReadableStream`.
|
|
5
|
+
*/
|
|
6
|
+
type ByteSource = Response | ReadableStream<Uint8Array> | null | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* Yields decoded text chunks from a plain streaming response (a body that is
|
|
9
|
+
* just the reply text, sent in pieces).
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* onSend={async function* (text, { signal }) {
|
|
13
|
+
* const res = await fetch("/api/chat", { method: "POST", body: text, signal });
|
|
14
|
+
* yield* readTextStream(res);
|
|
15
|
+
* }}
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function readTextStream(source: ByteSource): AsyncGenerator<string>;
|
|
19
|
+
/**
|
|
20
|
+
* Yields the `data` of each server-sent event (`text/event-stream`), the
|
|
21
|
+
* format most LLM APIs stream in. Multi-line data is joined with `\n`. Parse
|
|
22
|
+
* each payload yourself, since every API shapes it differently.
|
|
23
|
+
*
|
|
24
|
+
* ```ts
|
|
25
|
+
* for await (const data of readEventStream(res)) {
|
|
26
|
+
* if (data === "[DONE]") break;
|
|
27
|
+
* yield JSON.parse(data).delta ?? "";
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function readEventStream(source: ByteSource): AsyncGenerator<string>;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
//#region src/components/data-display/Chat/streams.ts
|
|
2
|
+
function e(e) {
|
|
3
|
+
let t = e instanceof Response ? e.body : e;
|
|
4
|
+
if (!t) throw Error("readTextStream: the response has no body to read.");
|
|
5
|
+
return t;
|
|
6
|
+
}
|
|
7
|
+
async function* t(t) {
|
|
8
|
+
let n = e(t).getReader(), r = new TextDecoder();
|
|
9
|
+
try {
|
|
10
|
+
for (;;) {
|
|
11
|
+
let { done: e, value: t } = await n.read();
|
|
12
|
+
if (e) break;
|
|
13
|
+
let i = r.decode(t, { stream: !0 });
|
|
14
|
+
i && (yield i);
|
|
15
|
+
}
|
|
16
|
+
let e = r.decode();
|
|
17
|
+
e && (yield e);
|
|
18
|
+
} finally {
|
|
19
|
+
n.releaseLock();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async function* n(e) {
|
|
23
|
+
let n = "", r = function* (e) {
|
|
24
|
+
let t = n.split(/\r?\n\r?\n/);
|
|
25
|
+
n = e ? "" : t.pop() ?? "";
|
|
26
|
+
for (let e of t) {
|
|
27
|
+
let t = e.split(/\r?\n/).filter((e) => e.startsWith("data:")).map((e) => e.slice(5).replace(/^ /, ""));
|
|
28
|
+
t.length > 0 && (yield t.join("\n"));
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
for await (let i of t(e)) n += i, yield* r(!1);
|
|
32
|
+
n += "\n\n", yield* r(!0);
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
export { n as readEventStream, t as readTextStream };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=`
|
|
1
|
+
var e=`_frame_uic8v_19`,t=`_plain_uic8v_36`,n=`_striped_uic8v_40`,r=`_body_uic8v_40`,i=`_row_uic8v_40`,a=`_outline_uic8v_44`,o=`_compact_uic8v_52`,s=`_comfortable_uic8v_58`,c=`_spacious_uic8v_64`,l=`_scroll_uic8v_70`,u=`_table_uic8v_75`,d=`_cell_uic8v_87`,f=`_hoverable_uic8v_114`,p=`_clickable_uic8v_118`,m=`_head_uic8v_140`,h=`_sticky_uic8v_153`,g=`_rowHeader_uic8v_159`,_=`_alignStart_uic8v_166`,v=`_alignCenter_uic8v_170`,y=`_alignEnd_uic8v_174`,b=`_numeric_uic8v_178`,x=`_selectCell_uic8v_186`,S=`_sortableCell_uic8v_192`,C=`_sortButton_uic8v_196`,w=`_sortLabel_uic8v_238`,T=`_sortIcon_uic8v_239`,E=`_sortPriority_uic8v_265`,D=`_emptyCell_uic8v_273`,O=`_loadingInline_uic8v_279`,k=`_loadingOverlay_uic8v_285`,A=`_footer_uic8v_295`,j=`_status_uic8v_307`,M=`_paging_uic8v_313`,N=`_range_uic8v_321`,P=`_fixed_uic8v_348`,F=`_hasHeaderEnd_uic8v_353`,I={frame:e,plain:t,striped:n,body:r,row:i,outline:a,compact:o,comfortable:s,spacious:c,scroll:l,table:u,cell:d,hoverable:f,clickable:p,head:m,sticky:h,rowHeader:g,alignStart:_,alignCenter:v,alignEnd:y,numeric:b,selectCell:x,sortableCell:S,sortButton:C,sortLabel:w,sortIcon:T,sortPriority:E,emptyCell:D,loadingInline:O,loadingOverlay:k,footer:A,status:j,paging:M,range:N,fixed:P,hasHeaderEnd:F};exports.alignCenter=v,exports.alignEnd=y,exports.alignStart=_,exports.body=r,exports.cell=d,exports.clickable=p,exports.comfortable=s,exports.compact=o,exports.default=I,exports.emptyCell=D,exports.fixed=P,exports.footer=A,exports.frame=e,exports.hasHeaderEnd=F,exports.head=m,exports.hoverable=f,exports.loadingInline=O,exports.loadingOverlay=k,exports.numeric=b,exports.outline=a,exports.paging=M,exports.plain=t,exports.range=N,exports.row=i,exports.rowHeader=g,exports.scroll=l,exports.selectCell=x,exports.sortButton=C,exports.sortIcon=T,exports.sortLabel=w,exports.sortPriority=E,exports.sortableCell=S,exports.spacious=c,exports.status=j,exports.sticky=h,exports.striped=n,exports.table=u;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/components/data-display/DataGrid/DataGrid.module.css
|
|
2
|
-
var e = "
|
|
2
|
+
var e = "_frame_uic8v_19", t = "_plain_uic8v_36", n = "_striped_uic8v_40", r = "_body_uic8v_40", i = "_row_uic8v_40", a = "_outline_uic8v_44", o = "_compact_uic8v_52", s = "_comfortable_uic8v_58", c = "_spacious_uic8v_64", l = "_scroll_uic8v_70", u = "_table_uic8v_75", d = "_cell_uic8v_87", f = "_hoverable_uic8v_114", p = "_clickable_uic8v_118", m = "_head_uic8v_140", h = "_sticky_uic8v_153", g = "_rowHeader_uic8v_159", _ = "_alignStart_uic8v_166", v = "_alignCenter_uic8v_170", y = "_alignEnd_uic8v_174", b = "_numeric_uic8v_178", x = "_selectCell_uic8v_186", S = "_sortableCell_uic8v_192", C = "_sortButton_uic8v_196", w = "_sortLabel_uic8v_238", T = "_sortIcon_uic8v_239", E = "_sortPriority_uic8v_265", D = "_emptyCell_uic8v_273", O = "_loadingInline_uic8v_279", k = "_loadingOverlay_uic8v_285", A = "_footer_uic8v_295", j = "_status_uic8v_307", M = "_paging_uic8v_313", N = "_range_uic8v_321", P = "_fixed_uic8v_348", F = "_hasHeaderEnd_uic8v_353", I = {
|
|
3
3
|
frame: e,
|
|
4
4
|
plain: t,
|
|
5
5
|
striped: n,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=`
|
|
1
|
+
var e=`_root_boa19_7`,t=`_list_boa19_12`,n=`_item_boa19_17`,r=`_empty_boa19_24`,i={root:e,list:t,item:n,empty:r};exports.default=i,exports.empty=r,exports.item=n,exports.list=t,exports.root=e;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/components/data-display/VirtualList/VirtualList.module.css
|
|
2
|
-
var e = "
|
|
2
|
+
var e = "_root_boa19_7", t = "_list_boa19_12", n = "_item_boa19_17", r = "_empty_boa19_24", i = {
|
|
3
3
|
root: e,
|
|
4
4
|
list: t,
|
|
5
5
|
item: n,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=`
|
|
1
|
+
var e=`_root_e770i_4`,t=`_list_e770i_9`,n={root:e,list:t};exports.default=n,exports.list=t,exports.root=e;
|