whisper-design
Version:
A React component library for building AI chat room UIs.
24 lines (23 loc) • 16.2 kB
JavaScript
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const v=require("react"),K=require("uuid"),pe=require("dayjs");var k={exports:{}},C={};/**
* @license React
* react-jsx-runtime.production.js
*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var q;function he(){if(q)return C;q=1;var t=Symbol.for("react.transitional.element"),a=Symbol.for("react.fragment");function o(i,r,c){var l=null;if(c!==void 0&&(l=""+c),r.key!==void 0&&(l=""+r.key),"key"in r){c={};for(var u in r)u!=="key"&&(c[u]=r[u])}else c=r;return r=c.ref,{$$typeof:t,type:i,key:l,ref:r!==void 0?r:null,props:c}}return C.Fragment=a,C.jsx=o,C.jsxs=o,C}var y={};/**
* @license React
* react-jsx-runtime.development.js
*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var X;function ve(){return X||(X=1,process.env.NODE_ENV!=="production"&&function(){function t(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===de?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case j:return"Fragment";case g:return"Profiler";case w:return"StrictMode";case ce:return"Suspense";case le:return"SuspenseList";case ue:return"Activity"}if(typeof e=="object")switch(typeof e.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case b:return"Portal";case z:return(e.displayName||"Context")+".Provider";case M:return(e._context.displayName||"Context")+".Consumer";case N:var n=e.render;return e=e.displayName,e||(e=n.displayName||n.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case oe:return n=e.displayName||null,n!==null?n:t(e.type)||"Memo";case Y:n=e._payload,e=e._init;try{return t(e(n))}catch{}}return null}function a(e){return""+e}function o(e){try{a(e);var n=!1}catch{n=!0}if(n){n=console;var m=n.error,p=typeof Symbol=="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return m.call(n,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",p),a(e)}}function i(e){if(e===j)return"<>";if(typeof e=="object"&&e!==null&&e.$$typeof===Y)return"<...>";try{var n=t(e);return n?"<"+n+">":"<...>"}catch{return"<...>"}}function r(){var e=P.A;return e===null?null:e.getOwner()}function c(){return Error("react-stack-top-frame")}function l(e){if(U.call(e,"key")){var n=Object.getOwnPropertyDescriptor(e,"key").get;if(n&&n.isReactWarning)return!1}return e.key!==void 0}function u(e,n){function m(){W||(W=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",n))}m.isReactWarning=!0,Object.defineProperty(e,"key",{get:m,configurable:!0})}function x(){var e=t(this.type);return B[e]||(B[e]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),e=this.props.ref,e!==void 0?e:null}function E(e,n,m,p,_,R,F,L){return m=R.ref,e={$$typeof:f,type:e,key:n,props:R,_owner:_},(m!==void 0?m:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:x}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:F}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:L}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function T(e,n,m,p,_,R,F,L){var h=n.children;if(h!==void 0)if(p)if(fe(h)){for(p=0;p<h.length;p++)S(h[p]);Object.freeze&&Object.freeze(h)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else S(h);if(U.call(n,"key")){h=t(e);var A=Object.keys(n).filter(function(me){return me!=="key"});p=0<A.length?"{key: someKey, "+A.join(": ..., ")+": ...}":"{key: someKey}",V[h+p]||(A=0<A.length?"{"+A.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
let props = %s;
<%s {...props} />
React keys must be passed directly to JSX without using spread:
let props = %s;
<%s key={someKey} {...props} />`,p,h,A,h),V[h+p]=!0)}if(h=null,m!==void 0&&(o(m),h=""+m),l(n)&&(o(n.key),h=""+n.key),"key"in n){m={};for(var $ in n)$!=="key"&&(m[$]=n[$])}else m=n;return h&&u(m,typeof e=="function"?e.displayName||e.name||"Unknown":e),E(e,h,R,_,r(),m,F,L)}function S(e){typeof e=="object"&&e!==null&&e.$$typeof===f&&e._store&&(e._store.validated=1)}var d=v,f=Symbol.for("react.transitional.element"),b=Symbol.for("react.portal"),j=Symbol.for("react.fragment"),w=Symbol.for("react.strict_mode"),g=Symbol.for("react.profiler"),M=Symbol.for("react.consumer"),z=Symbol.for("react.context"),N=Symbol.for("react.forward_ref"),ce=Symbol.for("react.suspense"),le=Symbol.for("react.suspense_list"),oe=Symbol.for("react.memo"),Y=Symbol.for("react.lazy"),ue=Symbol.for("react.activity"),de=Symbol.for("react.client.reference"),P=d.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,U=Object.prototype.hasOwnProperty,fe=Array.isArray,I=console.createTask?console.createTask:function(){return null};d={"react-stack-bottom-frame":function(e){return e()}};var W,B={},D=d["react-stack-bottom-frame"].bind(d,c)(),G=I(i(c)),V={};y.Fragment=j,y.jsx=function(e,n,m,p,_){var R=1e4>P.recentlyCreatedOwnerStacks++;return T(e,n,m,!1,p,_,R?Error("react-stack-top-frame"):D,R?I(i(e)):G)},y.jsxs=function(e,n,m,p,_){var R=1e4>P.recentlyCreatedOwnerStacks++;return T(e,n,m,!0,p,_,R?Error("react-stack-top-frame"):D,R?I(i(e)):G)}}()),y}var H;function xe(){return H||(H=1,process.env.NODE_ENV==="production"?k.exports=he():k.exports=ve()),k.exports}var s=xe();const Z=v.memo(({src:t,alt:a,size:o="medium",shape:i="circle",gradient:r,children:c})=>{const l=r?`avatar--${r}-gradient`:"";return s.jsx("div",{className:`avatar avatar--${o} avatar--${i} ${l}`,role:"img","aria-label":a,children:t?s.jsx("img",{src:t,alt:a}):c})}),O=({onClick:t,children:a,variant:o="primary",disabled:i=!1,type:r="button",isCircle:c=!1,className:l=""})=>{const x=`button ${c?"button--circle":`button--${o}`} ${l}`.trim();return s.jsx("button",{type:r,className:x,onClick:t,disabled:i,children:a})},ee=t=>{switch(t.split(".").pop()?.toLowerCase()){case"pdf":return"fas fa-file-pdf";case"xlsx":case"xls":return"fas fa-file-excel";case"docx":case"doc":return"fas fa-file-word";case"pptx":case"ppt":return"fas fa-file-powerpoint";case"jpg":case"jpeg":case"png":case"gif":case"bmp":case"svg":case"webp":return"fas fa-file-image";case"mp4":case"avi":case"mov":case"wmv":case"flv":return"fas fa-file-video";case"mp3":case"wav":case"flac":case"aac":return"fas fa-file-audio";case"zip":case"rar":case"7z":case"tar":case"gz":return"fas fa-file-archive";case"txt":case"md":return"fas fa-file-alt";case"js":case"ts":case"jsx":case"tsx":case"html":case"css":case"scss":case"json":case"xml":case"py":case"java":case"cpp":case"c":return"fas fa-file-code";default:return"fas fa-file"}},se=t=>{if(t===0)return"0 B";const a=1024,o=["B","KB","MB","GB"],i=Math.floor(Math.log(t)/Math.log(a));return`${parseFloat((t/Math.pow(a,i)).toFixed(2))} ${o[i]}`},te=v.memo(({id:t,content:a,sender:o,type:i="text",isLoading:r,files:c})=>{const l=()=>{switch(i){case"image":return s.jsx("img",{src:a,alt:""});case"code":return s.jsx("pre",{children:s.jsx("code",{children:a})});case"text":default:return s.jsx("p",{children:a})}};return s.jsxs("div",{className:`message-bubble ${o} message-bubble--${i}`,children:[l(),c&&c.length>0&&s.jsx("div",{className:"file-attachments",children:c.map(u=>s.jsxs("div",{className:"file-attachment",children:[s.jsx("div",{className:"file-icon",children:s.jsx("i",{className:ee(u.name)})}),s.jsxs("div",{className:"file-info",children:[s.jsx("div",{className:"file-name",children:u.name}),s.jsx("div",{className:"file-size",children:se(u.size)})]})]},u.id))}),r&&s.jsx("span",{className:"loading-indicator",children:"..."})," "]},t)}),ae=({onSendMessage:t,isSending:a=!1,placeholder:o="输入消息...",onFilesChange:i})=>{const[r,c]=v.useState(""),[l,u]=v.useState([]),x=v.useRef(null),E=d=>{u(d),i&&i(d)},T=d=>{d.preventDefault(),(r.trim()||l.length>0)&&(t(r.trim(),l),c(""),u([]))},S=d=>{d.key==="Enter"&&!d.shiftKey&&(d.preventDefault(),T(d))};return s.jsx("form",{className:"chat-input-area",onSubmit:T,children:s.jsxs("div",{className:"input-container",children:[s.jsx("div",{className:"input-toolbar",children:s.jsx(O,{isCircle:!0,onClick:()=>x.current?.click(),disabled:a,children:s.jsx("i",{className:"fas fa-paperclip"})})}),s.jsx("input",{type:"file",ref:x,multiple:!0,accept:"image/*,.pdf,.xlsx,.docx",onChange:d=>{const b=Array.from(d.target.files||[]).map(j=>Object.assign(j,{id:K.v4()}));E([...l,...b]),d.target.value=""},style:{display:"none"}}),l.length>0&&s.jsxs("div",{className:"file-list",children:[" ",l.map(d=>s.jsxs("div",{className:"file-card",children:[s.jsx("span",{className:"file-icon",children:s.jsx("i",{className:ee(d.name)})}),s.jsxs("div",{className:"file-info",children:[s.jsx("span",{className:"file-name",children:d.name}),s.jsx("span",{className:"file-size",children:se(d.size)})]}),s.jsx("button",{type:"button",className:"file-remove-button",onClick:()=>E(l.filter(f=>f.id!==d.id)),disabled:a,children:"×"})]},d.id))]}),s.jsx("textarea",{className:"message-input",placeholder:o,value:r,onChange:d=>c(d.target.value),onKeyDown:S,"aria-label":"消息输入框",disabled:a}),s.jsxs("div",{className:"input-actions",children:[s.jsxs("div",{className:"input-hints",children:[s.jsx("i",{className:"fas fa-lightbulb"})," 按 Enter 发送,Shift + Enter 换行"]}),s.jsxs(O,{type:"submit",variant:"primary",disabled:a,onClick:()=>{},children:[s.jsx("i",{className:"fas fa-paper-plane"}),"发送"]})]})]})})},je=({onFilesChange:t,acceptedFileTypes:a="image/*,.pdf,.xlsx,.docx",maxFiles:o=5,value:i,disabled:r=!1})=>{const c=v.useRef(null),[l,u]=v.useState(i||[]);v.useEffect(()=>{i!==void 0&&u(i)},[i]);const x=f=>{if(r)return;const b=Array.from(f.target.files||[]),j=[];b.forEach(g=>{if(l.length+j.length<o){const M="."+g.name.split(".").pop()?.toLowerCase();if(a.split(",").some(N=>(N=N.trim().toLowerCase(),N.startsWith(".")?M===N:N.endsWith("/*")?g.type.startsWith(N.slice(0,-1)):g.type===N))){const N={...g,id:K.v4(),...g.type.startsWith("image/")&&{preview:URL.createObjectURL(g)}};j.push(N)}else console.warn(`File type not accepted: ${g.name} (${g.type})`)}else console.warn(`Max files reached (${o}). Skipping ${g.name}.`)});const w=[...l,...j];u(w),t?.(w),c.current&&(c.current.value="")},E=f=>{if(r)return;const b=l.filter(j=>j.id!==f);u(b),t?.(b)},T=f=>f.type.startsWith("image/")?"🖼️":f.type==="application/pdf"?"📄":f.type==="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"||f.name.endsWith(".xlsx")?"📊":"📎",S=f=>{if(f===0)return"0 Bytes";const b=1024,j=["Bytes","KB","MB","GB","TB"],w=Math.floor(Math.log(f)/Math.log(b));return parseFloat((f/Math.pow(b,w)).toFixed(2))+" "+j[w]},d=l.length>=o;return s.jsxs("div",{className:"file-upload-container",children:[s.jsx("input",{type:"file",ref:c,multiple:!0,accept:a,onChange:x,disabled:r||d,style:{display:"none"}}),s.jsx("button",{type:"button",className:"file-upload-button",onClick:()=>c.current?.click(),disabled:r||d,children:d?"Max files reached":"Select Files"}),l.length>0&&s.jsx("div",{className:"file-list",children:l.map(f=>s.jsxs("div",{className:"file-card",children:[s.jsx("span",{className:"file-icon",children:T(f)}),f.preview&&s.jsx("img",{src:f.preview,alt:"preview",className:"file-preview"}),s.jsxs("div",{className:"file-info",children:[s.jsx("span",{className:"file-name",children:f.name}),s.jsx("span",{className:"file-size",children:S(f.size)})]}),s.jsx("button",{type:"button",className:"file-remove-button",onClick:()=>E(f.id),disabled:r,children:"×"})]},f.id))})]})},re=v.memo(({message:t,config:a})=>{const o=t.sender==="user",i=o?a?.userAvatar:a?.aiAvatar,r=o?"User Avatar":"AI Avatar",c=o?"primary":"secondary",l=u=>new Date(u).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"});return s.jsxs("div",{className:`message-row ${o?"user":""}`,children:[s.jsx(Z,{...i&&{src:i},alt:r,size:"medium",gradient:c,children:!i&&s.jsx("i",{className:`fas fa-${o?"user":"robot"}`})}),s.jsxs("div",{className:"message-content",children:[s.jsx(te,{id:t.id,content:t.content,sender:t.sender,type:t.type||"text",...t.isLoading!==void 0&&{isLoading:t.isLoading},...t.files&&{files:t.files}}),s.jsx("div",{className:"message-time",children:l(t.timestamp)})]})]})}),ne=({messages:t,config:a,isLoadingMore:o})=>{const i=v.useRef(null),r=()=>{i.current?.scrollIntoView({behavior:"smooth"})};return v.useEffect(()=>{r()},[t]),s.jsxs("div",{className:"chat-messages",children:[" ",t.map(c=>s.jsx(re,{message:c,...a&&{config:a}},c.id)),o&&s.jsx("div",{className:"loading-more",children:"Loading more messages..."}),s.jsx("div",{ref:i})," "]})},be=(t,a="HH:mm")=>pe(t).format(a),J=(t,a)=>t.length<=a?t:t.substring(0,a)+"...",Q={CONVERSATION_TITLE_MAX_LENGTH:30,MESSAGE_PREVIEW_MAX_LENGTH:50},ie=({conversation:t,isActive:a,onClick:o})=>{const i=t.messages.length>0&&t.messages[0]?J(t.messages[0].content,Q.CONVERSATION_TITLE_MAX_LENGTH):t.title,r=t.messages[t.messages.length-1],c=t.messages.length>0&&r?J(r.content,Q.MESSAGE_PREVIEW_MAX_LENGTH):"No messages yet.",l=be(t.lastUpdated);return s.jsx("div",{className:`conversation-item ${a?"active":""}`,onClick:()=>o(t.id),children:s.jsxs("div",{className:"conversation-info",children:[s.jsxs("div",{className:"conversation-title",children:[s.jsx("span",{children:i}),s.jsx("span",{className:"conversation-time",children:l})]}),s.jsx("div",{className:"conversation-preview",children:c})]})})},ge=({messages:t,onSendMessage:a,isAITyping:o=!1,config:i,conversationTitle:r})=>{const[c,l]=v.useState(!1),u=async(x,E)=>{l(!0),await a(x,E),l(!1)};return s.jsxs("div",{className:"chat-container",children:[" ",s.jsx("div",{className:"chat-header",children:s.jsx("div",{className:"chat-title",children:r||"新对话"})}),s.jsx(ne,{messages:t,...i&&{config:i}}),s.jsx(ae,{onSendMessage:u,isSending:c||o,placeholder:"输入消息..."})]})},Ne=({conversations:t,activeConversationId:a,onSelectConversation:o,onNewConversation:i})=>{const[r,c]=v.useState(""),l=v.useMemo(()=>{if(!r)return t;const u=r.toLowerCase();return t.filter(x=>x.title.toLowerCase().includes(u)||x.messages.some(E=>E.content.toLowerCase().includes(u)))},[t,r]);return s.jsxs("div",{className:"conversations-panel",children:[" ",s.jsxs("div",{className:"panel-header",children:[" ",s.jsxs("div",{className:"panel-title",children:[s.jsx("i",{className:"fas fa-comments"}),"对话列表",s.jsx(O,{isCircle:!0,onClick:i,className:"new-conversation-btn",children:s.jsx("i",{className:"fas fa-plus"})})]}),s.jsxs("div",{className:"search-container",children:[s.jsx("i",{className:"fas fa-search search-icon"}),s.jsx("input",{type:"text",className:"search-input",placeholder:"搜索对话...",value:r,onChange:u=>c(u.target.value)})]})]}),s.jsxs("div",{className:"conversation-list",children:[" ",l.length>0?l.map(u=>s.jsx(ie,{conversation:u,isActive:u.id===a,onClick:o},u.id)):s.jsx("div",{className:"conversation-list__empty",children:"No conversations found."})]})]})};exports.AIChatRoom=ge;exports.Avatar=Z;exports.Button=O;exports.ChatInputArea=ae;exports.ChatMessage=re;exports.ChatMessagesList=ne;exports.ConversationItem=ie;exports.ConversationList=Ne;exports.FileUpload=je;exports.MessageBubble=te;
//# sourceMappingURL=ai-chat-room-components.js.map