@kushagradhawan/kookie-ui 0.1.34 → 0.1.35

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.
@@ -7,6 +7,7 @@ type SendMode = 'always' | 'whenDirty' | 'never';
7
7
  type AttachmentStatus = 'idle' | 'uploading' | 'error' | 'done';
8
8
  /**
9
9
  * Attachment data model used by Chatbar.
10
+ * - `file` exposes the original File object for uploads and processing.
10
11
  * - `url` is an object URL used for image previews and is revoked on removal.
11
12
  */
12
13
  interface ChatbarAttachment {
@@ -14,6 +15,8 @@ interface ChatbarAttachment {
14
15
  name: string;
15
16
  size: number;
16
17
  type: string;
18
+ /** Original File object for uploads and processing */
19
+ file: File;
17
20
  url?: string;
18
21
  status?: AttachmentStatus;
19
22
  progress?: number;
@@ -198,5 +201,5 @@ interface SendProps extends Omit<IconButtonProps, 'size'> {
198
201
  }
199
202
  declare const Send: React.ForwardRefExoticComponent<SendProps & React.RefAttributes<HTMLButtonElement>>;
200
203
  export { Root, Textarea, InlineStart, InlineEnd, AttachmentsRow, Attachment, AttachTrigger, Row, RowStart, RowEnd, Send, };
201
- export type { RootProps as ChatbarRootProps, TextareaProps as ChatbarTextareaProps, RowProps as ChatbarRowProps, SendProps as ChatbarSendProps, };
204
+ export type { RootProps as ChatbarRootProps, TextareaProps as ChatbarTextareaProps, RowProps as ChatbarRowProps, SendProps as ChatbarSendProps, ChatbarAttachment, };
202
205
  //# sourceMappingURL=chatbar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chatbar.d.ts","sourceRoot":"","sources":["../../../src/components/chatbar.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chatbar.d.ts","sourceRoot":"","sources":["../../../src/components/chatbar.tsx"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";var qe=Object.create;var ie=Object.defineProperty;var Ye=Object.getOwnPropertyDescriptor;var Ge=Object.getOwnPropertyNames;var _e=Object.getPrototypeOf,Je=Object.prototype.hasOwnProperty;var Qe=(t,n)=>{for(var s in n)ie(t,s,{get:n[s],enumerable:!0})},He=(t,n,s,m)=>{if(n&&typeof n=="object"||typeof n=="function")for(let l of Ge(n))!Je.call(t,l)&&l!==s&&ie(t,l,{get:()=>n[l],enumerable:!(m=Ye(n,l))||m.enumerable});return t};var ze=(t,n,s)=>(s=t!=null?qe(_e(t)):{},He(n||!t||!t.__esModule?ie(s,"default",{value:t,enumerable:!0}):s,t)),Xe=t=>He(ie({},"__esModule",{value:!0}),t);var Ze={};Qe(Ze,{AttachTrigger:()=>Te,Attachment:()=>ce,AttachmentsRow:()=>we,InlineEnd:()=>Pe,InlineStart:()=>Re,Root:()=>xe,Row:()=>Ee,RowEnd:()=>Me,RowStart:()=>Se,Send:()=>Oe,Textarea:()=>Ae});module.exports=Xe(Ze);var e=ze(require("react")),S=ze(require("classnames")),ge=require("./icon-button.js"),me=require("./icons.js"),ae=require("./flex.js"),De=require("./scroll-area.js"),H=require("./slot.js"),ve=require("./card.js"),le=require("./text.js"),ke=require("react-dropzone");const Fe=typeof window<"u"?e.useLayoutEffect:e.useEffect,Ie=e.createContext(null),k=()=>{const t=e.useContext(Ie);if(!t)throw new Error("Chatbar context not found. Wrap parts in <Chatbar.Root>.");return t},xe=e.forwardRef((t,n)=>{const{className:s,style:m,children:l,value:u,defaultValue:y="",onValueChange:p,open:d,defaultOpen:r=!1,onOpenChange:v,expandOn:P="both",minLines:A=1,maxLines:w=6,sendMode:T="whenDirty",disabled:j,readOnly:Y,onSubmit:z,size:O="2",variant:W,width:U,maxWidth:K,asChild:N,attachments:F,defaultAttachments:oe=[],onAttachmentsChange:$,accept:G,multiple:_=!0,maxAttachments:V,maxFileSize:M,paste:se=!0,pasteAccept:B,clearOnSubmit:L=!0,onAttachmentReject:h,dropzone:I=!0,...de}=t,J=u!=null,[ue,pe]=e.useState(y),a=J?u:ue,c=d!=null,[x,g]=e.useState(r),E=c?d:x,Q=e.useRef(null),he=e.useRef(null),q=F!=null,[X,Z]=e.useState(oe),D=q?F:X,ee=e.useRef(new Set),fe=o=>Array.isArray(o)?o:typeof o=="string"?o.split(",").map(i=>i.trim()):[],te=fe(G),Le=fe(B).length>0?fe(B):te,be=(o,i)=>{if(i.length===0)return!0;const f=o.type.toLowerCase(),R=o.name.toLowerCase();for(const b of i){const C=b.toLowerCase();if(C.includes("/")){const[re,ye]=C.split("/"),[ne,$e]=f.split("/");if(re==="*"||re===ne&&(ye==="*"||ye===$e))return!0}else if(C.startsWith(".")&&R.endsWith(C))return!0}return!1},je=o=>{const i=[],f=[],R=typeof V=="number"?Math.max(V-D.length,0):1/0;for(const b of o){if(i.length>=R){f.push({file:b,reason:"count"});continue}if(typeof M=="number"&&b.size>M){f.push({file:b,reason:"size"});continue}if(!be(b,te)){f.push({file:b,reason:"type"});continue}const C=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,re=/\.(png|jpe?g|gif|webp|bmp|svg)$/i.test(b.name),ne=(b.type||"").toLowerCase().startsWith("image/")||re?URL.createObjectURL(b):void 0;ne&&ee.current.add(ne),i.push({id:C,name:b.name,size:b.size,type:b.type,url:ne,status:"idle"})}return{accepted:i,rejected:f}},Ce=o=>{const{accepted:i,rejected:f}=je(o);if(i.length>0){const R=D.concat(i);q||Z(R),$?.(R)}f.length>0&&h?.(f)},We=o=>{const i=C=>Le.length===0?be(C,te):be(C,Le),f=[],R=[],b=typeof V=="number"?Math.max(V-D.length,0):1/0;for(const C of o){if(f.length>=b){R.push({file:C,reason:"count"});continue}if(typeof M=="number"&&C.size>M){R.push({file:C,reason:"size"});continue}if(!i(C)){R.push({file:C,reason:"type"});continue}f.push(C)}f.length>0&&Ce(f),R.length>0&&h?.(R)};e.useEffect(()=>{const o=new Set(D.map(i=>i.url).filter(Boolean));for(const i of Array.from(ee.current))o.has(i)||(URL.revokeObjectURL(i),ee.current.delete(i))},[D]),e.useEffect(()=>()=>{for(const o of Array.from(ee.current))URL.revokeObjectURL(o);ee.current.clear()},[]);const Ve=N?H.Slot:"div",Be=e.useCallback(o=>{const i=o.relatedTarget,f=Q.current;f&&(i&&f.contains(i)||(a?.trim?.()??"").length===0&&(c||g(!1),v?.(!1)))},[c,v,a]),{getRootProps:Ue,getInputProps:Ke,isDragActive:Ne}=(0,ke.useDropzone)({onDrop:(o,i)=>{if(o.length>0&&Ce(o),i.length>0&&h){const f=i.map(({file:R,errors:b})=>{const C=b[0]?.code==="file-too-large"?"size":b[0]?.code==="file-invalid-type"?"type":"count";return{file:R,reason:C}});h(f)}},accept:te.length>0?te.reduce((o,i)=>(i.includes("/")?o[i]=[]:i.startsWith(".")&&(o[i]=[]),o),{}):void 0,multiple:_,maxSize:M,noClick:!0,noKeyboard:!0,disabled:!I||j});return e.createElement(Ie.Provider,{value:{open:E,setOpen:o=>{c||g(o),v?.(o)},isOpenControlled:c,value:a,setValue:o=>{J||pe(o),p?.(o)},isValueControlled:J,size:O,expandOn:P,minLines:A,maxLines:w,sendMode:T,disabled:j,readOnly:Y,onSubmit:z,rootRef:Q,textareaRef:he,attachments:D,setAttachments:o=>{q||Z(o),$?.(o)},isAttachmentsControlled:q,accept:G,multiple:_,maxAttachments:V,maxFileSize:M,paste:se,pasteAccept:B,clearOnSubmit:L,onAttachmentReject:h,dropzone:I,appendFiles:Ce,appendFilesFromPaste:We}},e.createElement(Ve,{...de,ref:o=>{typeof n=="function"?n(o):n&&(n.current=o),Q.current=o},className:(0,S.default)("rt-ChatbarRoot",`rt-r-size-${O}`,s),style:{position:"relative",width:U,maxWidth:K,...m},"data-state":E?"open":"closed","data-disabled":j?"":void 0,"data-readonly":Y?"":void 0,"data-drop-active":I&&Ne?"":void 0,"aria-expanded":E,onBlurCapture:Be},I&&e.createElement("input",{...Ke()}),e.createElement("div",{...I?Ue():{},style:{width:"100%",height:"100%"}},e.createElement(ve.Card,{className:"rt-ChatbarCard",size:Math.min(3,Number(O)+1).toString(),variant:W,style:{position:"relative"}},e.createElement("div",{className:"rt-ChatbarGrid"},l),I&&Ne&&e.createElement("div",{className:"rt-ChatbarDropOverlay"},e.createElement("div",{className:"rt-ChatbarDropContent"},e.createElement(le.Text,{color:"gray",size:O,weight:"medium"},"Drop files here to attach")))))))});xe.displayName="Chatbar.Root";const Ae=e.forwardRef((t,n)=>{const{className:s,style:m,asChild:l,onFocus:u,onInput:y,onChange:p,onPaste:d,onKeyDown:r,submitOnEnter:v=!1,rows:P,...A}=t,w=k(),{open:T,minLines:j,maxLines:Y,expandOn:z,disabled:O,readOnly:W,setOpen:U,setValue:K,textareaRef:N,value:F,isValueControlled:oe,sendMode:$,paste:G,appendFilesFromPaste:_,size:V}=w,M=e.useRef(0),se=e.useRef(0),B=e.useRef(0),L=e.useCallback(()=>{const a=N.current;if(!a)return;const c=window.getComputedStyle(a),x=parseFloat(c.lineHeight)||20,g=parseFloat(c.paddingTop)||0,E=parseFloat(c.paddingBottom)||0;M.current=x,se.current=g+E,B.current=Math.ceil(1*x)+g+E},[N]),h=e.useCallback(a=>{const c=N.current;if(!c)return;c.style.height="auto",M.current===0&&L();const x=M.current,g=se.current,E=a??T,Q=E?j:1,he=E?Y:1,q=Math.ceil(Q*x)+g,X=Math.ceil(he*x)+g,Z=Math.max(c.scrollHeight,q),D=Math.min(Z,X);c.style.height=`${D}px`,Z>X?(c.style.overflowY="auto",c.style.maxHeight=`${X}px`):(c.style.overflowY="hidden",c.style.maxHeight="none")},[T,j,Y,N,L]);Fe(()=>{h()},[h,F,T]),Fe(()=>{L(),h()},[L,h,V]),e.useEffect(()=>{const a=N.current;if(!a||typeof ResizeObserver>"u")return;let c=M.current;const x=new ResizeObserver(()=>{const g=window.getComputedStyle(a),E=parseFloat(g.lineHeight)||20;E!==c&&(c=E,L(),requestAnimationFrame(()=>h()))});return x.observe(a),()=>x.disconnect()},[N,L,h]),e.useEffect(()=>{},[]);const I=e.useCallback(a=>{O||W||((z==="focus"||z==="both")&&!T&&U(!0),u?.(a))},[O,W,z,T,U,u]),de=e.useCallback(a=>{const c=a.currentTarget,x=c.value;K(x),(z==="overflow"||z==="both")&&!T&&(c.style.height="auto",B.current===0&&L(),c.scrollHeight>B.current+1&&(U(!0),h(!0),requestAnimationFrame(()=>h(!0)))),requestAnimationFrame(()=>h()),p?.(a)},[z,T,U,K,p,h,L]),J=e.useCallback(a=>{if(G){const x=Array.from(a.clipboardData?.items??[]).filter(g=>g.kind==="file").map(g=>g.getAsFile()).filter(g=>!!g);x.length>0&&_(x)}setTimeout(()=>{T?h():h(!0)},0),d?.(a)},[G,T,h,d,_]),ue=e.useCallback(a=>{if(!v){r?.(a);return}if(a.key==="Enter"&&!a.shiftKey&&!a.altKey&&!a.ctrlKey&&!a.metaKey&&!a.nativeEvent.isComposing){if(O||W){r?.(a);return}if($==="never"){r?.(a);return}const c=F.trim();if($==="whenDirty"&&c.length===0){r?.(a);return}a.preventDefault(),w.onSubmit?.({value:F,attachments:w.attachments}),w.clearOnSubmit&&(oe||K(""),w.setAttachments([]))}r?.(a)},[v,O,W,$,F,oe,K,w,r]),pe=l?H.Slot:"textarea";return e.createElement("div",{className:(0,S.default)("rt-ChatbarField","rt-ChatbarTextarea",s)},e.createElement(pe,{...A,ref:a=>{typeof n=="function"?n(a):n&&(n.current=a),N.current=a},className:"rt-ChatbarInput",value:F,onInput:y,onChange:de,onFocus:I,onPaste:J,onKeyDown:ue,disabled:O,readOnly:W,rows:T?j:1,spellCheck:A.spellCheck??!0,autoCorrect:A.autoCorrect??"on",style:m}))});Ae.displayName="Chatbar.Textarea";const Re=e.forwardRef((t,n)=>{const{children:s,asChild:m,style:l,className:u,...y}=t;return k().open?null:e.createElement(m?H.Slot:"div",{...y,ref:n,className:(0,S.default)("rt-ChatbarInlineStart",u),style:l},s)});Re.displayName="Chatbar.InlineStart";const Pe=e.forwardRef((t,n)=>{const{children:s,asChild:m,style:l,className:u,...y}=t;return k().open?null:e.createElement(m?H.Slot:"div",{...y,ref:n,className:(0,S.default)("rt-ChatbarInlineEnd",u),style:l},s)});Pe.displayName="Chatbar.InlineEnd";const we=e.forwardRef((t,n)=>{const{asChild:s,forceMount:m,renderAttachment:l,className:u,style:y,...p}=t,d=k();return!(d.attachments.length>0)&&!m?null:e.createElement(s?H.Slot:"div",{...p,ref:n,className:(0,S.default)("rt-ChatbarAttachmentsRow",u),style:y,role:"list","aria-label":p["aria-label"]??"Attachments"},e.createElement(De.ScrollArea,{className:"rt-ChatbarScrollArea",scrollbars:"horizontal",size:"1"},e.createElement(ae.Flex,{align:"center",gap:"2",style:{minWidth:"fit-content"}},d.attachments.map(P=>e.createElement(ce,{key:P.id,attachment:P,asChild:!!l},l?.(P))))))});we.displayName="Chatbar.AttachmentsRow";const ce=e.forwardRef((t,n)=>{const{attachment:s,asChild:m,className:l,style:u,children:y,...p}=t,d=k(),r=m?H.Slot:"div",v=!!s.url&&s.type.startsWith("image/");return e.createElement(r,{...p,ref:n,className:(0,S.default)("rt-ChatbarAttachment",l),style:u,role:"listitem","data-kind":v?"image":"file",title:s.name},y??e.createElement(ve.Card,{size:d.size,variant:"soft"},e.createElement(ae.Flex,{align:"center",gap:"3",pr:v?void 0:"6"},e.createElement("div",{className:"rt-ChatbarAttachmentPreview","aria-hidden":!0},v?e.createElement("img",{className:"rt-ChatbarAttachmentImage",src:s.url,alt:""}):e.createElement(me.FileTextIcon,null)),!v&&e.createElement(ae.Flex,{direction:"column",gap:"0",style:{minWidth:0}},e.createElement(le.Text,{size:d.size,weight:"medium",style:{whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"}},s.name),e.createElement(le.Text,{size:"1",color:"gray"},Math.ceil(s.size/1024)," KB")),e.createElement(ge.IconButton,{className:"rt-ChatbarAttachmentRemove","aria-label":`Remove ${s.name}`,size:"1",variant:"classic",highContrast:!0,color:"gray",onClick:()=>d.setAttachments(d.attachments.filter(P=>P.id!==s.id))},e.createElement(me.CloseIcon,null)))))});ce.displayName="Chatbar.Attachment";const Te=e.forwardRef((t,n)=>{const{asChild:s,accept:m,multiple:l,className:u,style:y,...p}=t,d=k(),r=e.useRef(null),v=s?H.Slot:"button",P=(Array.isArray(m)?m:m?.split(",")??[]).join(",");return e.createElement(e.Fragment,null,e.createElement(v,{...p,ref:n,className:(0,S.default)("rt-ChatbarAttachTrigger",u),style:y,type:p.type??"button","aria-label":p["aria-label"]??"Add attachments",onClick:A=>{r.current&&r.current.click(),p.onClick?.(A)}}),e.createElement("input",{ref:r,type:"file",accept:P,multiple:l??d.multiple,tabIndex:-1,style:{display:"none"},onChange:A=>{const w=Array.from(A.currentTarget.files??[]);w.length>0&&d.appendFiles(w),A.currentTarget.value=""}}))});Te.displayName="Chatbar.AttachTrigger";const Ee=e.forwardRef((t,n)=>{const{asChild:s,children:m,className:l,style:u,...y}=t;return k().open?e.createElement(s?H.Slot:"div",{...y,ref:n,className:(0,S.default)("rt-ChatbarRow",l),style:u},e.createElement(ae.Flex,{align:"center",justify:"between",width:"100%"},m)):null});Ee.displayName="Chatbar.Row";const Se=e.forwardRef((t,n)=>{const{className:s,style:m,...l}=t;return e.createElement("div",{...l,ref:n,className:(0,S.default)("rt-ChatbarRowStart",s),style:m})});Se.displayName="Chatbar.RowStart";const Me=e.forwardRef((t,n)=>{const{className:s,style:m,...l}=t;return e.createElement("div",{...l,ref:n,className:(0,S.default)("rt-ChatbarRowEnd",s),style:m})});Me.displayName="Chatbar.RowEnd";const Oe=e.forwardRef((t,n)=>{const{asChild:s,clearOnSend:m=!0,disabled:l,children:u,className:y,style:p,...d}=t,r=k(),v=r.value.trim(),P=r.sendMode==="always"||r.sendMode==="whenDirty"&&v.length>0;if(r.sendMode==="never")return null;const A=w=>{r.disabled||r.readOnly||(r.onSubmit?.({value:r.value,attachments:r.attachments}),m&&(r.isValueControlled||r.setValue(""),r.clearOnSubmit&&r.setAttachments([])),d.onClick?.(w))};return e.createElement(ge.IconButton,{...d,ref:n,size:r.size,variant:r.open?"solid":"ghost",disabled:l||r.disabled||r.readOnly,className:(0,S.default)("rt-ChatbarSend",y),style:{opacity:P?1:0,pointerEvents:P?"auto":"none",...p},asChild:s,onClick:A,"aria-label":d["aria-label"]??"Send"},u??"Send")});Oe.displayName="Chatbar.Send";
1
+ "use strict";var qe=Object.create;var ie=Object.defineProperty;var Ye=Object.getOwnPropertyDescriptor;var Ge=Object.getOwnPropertyNames;var _e=Object.getPrototypeOf,Je=Object.prototype.hasOwnProperty;var Qe=(t,n)=>{for(var s in n)ie(t,s,{get:n[s],enumerable:!0})},He=(t,n,s,m)=>{if(n&&typeof n=="object"||typeof n=="function")for(let l of Ge(n))!Je.call(t,l)&&l!==s&&ie(t,l,{get:()=>n[l],enumerable:!(m=Ye(n,l))||m.enumerable});return t};var Fe=(t,n,s)=>(s=t!=null?qe(_e(t)):{},He(n||!t||!t.__esModule?ie(s,"default",{value:t,enumerable:!0}):s,t)),Xe=t=>He(ie({},"__esModule",{value:!0}),t);var Ze={};Qe(Ze,{AttachTrigger:()=>Te,Attachment:()=>ce,AttachmentsRow:()=>we,InlineEnd:()=>Pe,InlineStart:()=>Re,Root:()=>xe,Row:()=>Ee,RowEnd:()=>Me,RowStart:()=>Se,Send:()=>Oe,Textarea:()=>Ae});module.exports=Xe(Ze);var e=Fe(require("react")),S=Fe(require("classnames")),ge=require("./icon-button.js"),me=require("./icons.js"),ae=require("./flex.js"),De=require("./scroll-area.js"),H=require("./slot.js"),ve=require("./card.js"),le=require("./text.js"),ke=require("react-dropzone");const ze=typeof window<"u"?e.useLayoutEffect:e.useEffect,Ie=e.createContext(null),k=()=>{const t=e.useContext(Ie);if(!t)throw new Error("Chatbar context not found. Wrap parts in <Chatbar.Root>.");return t},xe=e.forwardRef((t,n)=>{const{className:s,style:m,children:l,value:u,defaultValue:y="",onValueChange:p,open:d,defaultOpen:r=!1,onOpenChange:x,expandOn:T="both",minLines:A=1,maxLines:R=6,sendMode:P="whenDirty",disabled:j,readOnly:Y,onSubmit:F,size:O="2",variant:W,width:U,maxWidth:K,asChild:N,attachments:z,defaultAttachments:oe=[],onAttachmentsChange:$,accept:G,multiple:_=!0,maxAttachments:V,maxFileSize:M,paste:se=!0,pasteAccept:B,clearOnSubmit:L=!0,onAttachmentReject:h,dropzone:I=!0,...de}=t,J=u!=null,[ue,pe]=e.useState(y),a=J?u:ue,c=d!=null,[g,v]=e.useState(r),E=c?d:g,Q=e.useRef(null),he=e.useRef(null),q=z!=null,[X,Z]=e.useState(oe),D=q?z:X,ee=e.useRef(new Set),fe=o=>Array.isArray(o)?o:typeof o=="string"?o.split(",").map(i=>i.trim()):[],te=fe(G),Le=fe(B).length>0?fe(B):te,be=(o,i)=>{if(i.length===0)return!0;const f=o.type.toLowerCase(),w=o.name.toLowerCase();for(const b of i){const C=b.toLowerCase();if(C.includes("/")){const[re,ye]=C.split("/"),[ne,$e]=f.split("/");if(re==="*"||re===ne&&(ye==="*"||ye===$e))return!0}else if(C.startsWith(".")&&w.endsWith(C))return!0}return!1},je=o=>{const i=[],f=[],w=typeof V=="number"?Math.max(V-D.length,0):1/0;for(const b of o){if(i.length>=w){f.push({file:b,reason:"count"});continue}if(typeof M=="number"&&b.size>M){f.push({file:b,reason:"size"});continue}if(!be(b,te)){f.push({file:b,reason:"type"});continue}const C=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,re=/\.(png|jpe?g|gif|webp|bmp|svg)$/i.test(b.name),ne=(b.type||"").toLowerCase().startsWith("image/")||re?URL.createObjectURL(b):void 0;ne&&ee.current.add(ne),i.push({id:C,name:b.name,size:b.size,type:b.type,file:b,url:ne,status:"idle"})}return{accepted:i,rejected:f}},Ce=o=>{const{accepted:i,rejected:f}=je(o);if(i.length>0){const w=D.concat(i);q||Z(w),$?.(w)}f.length>0&&h?.(f)},We=o=>{const i=C=>Le.length===0?be(C,te):be(C,Le),f=[],w=[],b=typeof V=="number"?Math.max(V-D.length,0):1/0;for(const C of o){if(f.length>=b){w.push({file:C,reason:"count"});continue}if(typeof M=="number"&&C.size>M){w.push({file:C,reason:"size"});continue}if(!i(C)){w.push({file:C,reason:"type"});continue}f.push(C)}f.length>0&&Ce(f),w.length>0&&h?.(w)};e.useEffect(()=>{const o=new Set(D.map(i=>i.url).filter(Boolean));for(const i of Array.from(ee.current))o.has(i)||(URL.revokeObjectURL(i),ee.current.delete(i))},[D]),e.useEffect(()=>()=>{for(const o of Array.from(ee.current))URL.revokeObjectURL(o);ee.current.clear()},[]);const Ve=N?H.Slot:"div",Be=e.useCallback(o=>{const i=o.relatedTarget,f=Q.current;f&&(i&&f.contains(i)||(a?.trim?.()??"").length===0&&(c||v(!1),x?.(!1)))},[c,x,a]),{getRootProps:Ue,getInputProps:Ke,isDragActive:Ne}=(0,ke.useDropzone)({onDrop:(o,i)=>{if(o.length>0&&Ce(o),i.length>0&&h){const f=i.map(({file:w,errors:b})=>{const C=b[0]?.code==="file-too-large"?"size":b[0]?.code==="file-invalid-type"?"type":"count";return{file:w,reason:C}});h(f)}},accept:te.length>0?te.reduce((o,i)=>(i.includes("/")?o[i]=[]:i.startsWith(".")&&(o[i]=[]),o),{}):void 0,multiple:_,maxSize:M,noClick:!0,noKeyboard:!0,disabled:!I||j});return e.createElement(Ie.Provider,{value:{open:E,setOpen:o=>{c||v(o),x?.(o)},isOpenControlled:c,value:a,setValue:o=>{J||pe(o),p?.(o)},isValueControlled:J,size:O,expandOn:T,minLines:A,maxLines:R,sendMode:P,disabled:j,readOnly:Y,onSubmit:F,rootRef:Q,textareaRef:he,attachments:D,setAttachments:o=>{q||Z(o),$?.(o)},isAttachmentsControlled:q,accept:G,multiple:_,maxAttachments:V,maxFileSize:M,paste:se,pasteAccept:B,clearOnSubmit:L,onAttachmentReject:h,dropzone:I,appendFiles:Ce,appendFilesFromPaste:We}},e.createElement(Ve,{...de,ref:o=>{typeof n=="function"?n(o):n&&(n.current=o),Q.current=o},className:(0,S.default)("rt-ChatbarRoot",`rt-r-size-${O}`,s),style:{position:"relative",width:U,maxWidth:K,...m},"data-state":E?"open":"closed","data-disabled":j?"":void 0,"data-readonly":Y?"":void 0,"data-drop-active":I&&Ne?"":void 0,"aria-expanded":E,onBlurCapture:Be},I&&e.createElement("input",{...Ke()}),e.createElement("div",{...I?Ue():{},style:{width:"100%",height:"100%"}},e.createElement(ve.Card,{className:"rt-ChatbarCard",size:Math.min(3,Number(O)+1).toString(),variant:W,style:{position:"relative"}},e.createElement("div",{className:"rt-ChatbarGrid"},l),I&&Ne&&e.createElement("div",{className:"rt-ChatbarDropOverlay"},e.createElement("div",{className:"rt-ChatbarDropContent"},e.createElement(le.Text,{color:"gray",size:O,weight:"medium"},"Drop files here to attach")))))))});xe.displayName="Chatbar.Root";const Ae=e.forwardRef((t,n)=>{const{className:s,style:m,asChild:l,onFocus:u,onInput:y,onChange:p,onPaste:d,onKeyDown:r,submitOnEnter:x=!1,rows:T,...A}=t,R=k(),{open:P,minLines:j,maxLines:Y,expandOn:F,disabled:O,readOnly:W,setOpen:U,setValue:K,textareaRef:N,value:z,isValueControlled:oe,sendMode:$,paste:G,appendFilesFromPaste:_,size:V}=R,M=e.useRef(0),se=e.useRef(0),B=e.useRef(0),L=e.useCallback(()=>{const a=N.current;if(!a)return;const c=window.getComputedStyle(a),g=parseFloat(c.lineHeight)||20,v=parseFloat(c.paddingTop)||0,E=parseFloat(c.paddingBottom)||0;M.current=g,se.current=v+E,B.current=Math.ceil(1*g)+v+E},[N]),h=e.useCallback(a=>{const c=N.current;if(!c)return;c.style.height="auto",M.current===0&&L();const g=M.current,v=se.current,E=a??P,Q=E?j:1,he=E?Y:1,q=Math.ceil(Q*g)+v,X=Math.ceil(he*g)+v,Z=Math.max(c.scrollHeight,q),D=Math.min(Z,X);c.style.height=`${D}px`,Z>X?(c.style.overflowY="auto",c.style.maxHeight=`${X}px`):(c.style.overflowY="hidden",c.style.maxHeight="none")},[P,j,Y,N,L]);ze(()=>{h()},[h,z,P]),ze(()=>{L(),h()},[L,h,V]),e.useEffect(()=>{const a=N.current;if(!a||typeof ResizeObserver>"u")return;let c=M.current;const g=new ResizeObserver(()=>{const v=window.getComputedStyle(a),E=parseFloat(v.lineHeight)||20;E!==c&&(c=E,L(),requestAnimationFrame(()=>h()))});return g.observe(a),()=>g.disconnect()},[N,L,h]),e.useEffect(()=>{},[]);const I=e.useCallback(a=>{O||W||((F==="focus"||F==="both")&&!P&&U(!0),u?.(a))},[O,W,F,P,U,u]),de=e.useCallback(a=>{const c=a.currentTarget,g=c.value;K(g),(F==="overflow"||F==="both")&&!P&&(c.style.height="auto",B.current===0&&L(),c.scrollHeight>B.current+1&&(U(!0),h(!0),requestAnimationFrame(()=>h(!0)))),requestAnimationFrame(()=>h()),p?.(a)},[F,P,U,K,p,h,L]),J=e.useCallback(a=>{if(G){const g=Array.from(a.clipboardData?.items??[]).filter(v=>v.kind==="file").map(v=>v.getAsFile()).filter(v=>!!v);g.length>0&&_(g)}setTimeout(()=>{P?h():h(!0)},0),d?.(a)},[G,P,h,d,_]),ue=e.useCallback(a=>{if(!x){r?.(a);return}if(a.key==="Enter"&&!a.shiftKey&&!a.altKey&&!a.ctrlKey&&!a.metaKey&&!a.nativeEvent.isComposing){if(O||W){r?.(a);return}if($==="never"){r?.(a);return}const g=z.trim().length>0||R.attachments.length>0;if($==="whenDirty"&&!g){r?.(a);return}a.preventDefault(),R.onSubmit?.({value:z,attachments:R.attachments}),R.clearOnSubmit&&(oe||K(""),R.setAttachments([]))}r?.(a)},[x,O,W,$,z,oe,K,R,r]),pe=l?H.Slot:"textarea";return e.createElement("div",{className:(0,S.default)("rt-ChatbarField","rt-ChatbarTextarea",s)},e.createElement(pe,{...A,ref:a=>{typeof n=="function"?n(a):n&&(n.current=a),N.current=a},className:"rt-ChatbarInput",value:z,onInput:y,onChange:de,onFocus:I,onPaste:J,onKeyDown:ue,disabled:O,readOnly:W,rows:P?j:1,spellCheck:A.spellCheck??!0,autoCorrect:A.autoCorrect??"on",style:m}))});Ae.displayName="Chatbar.Textarea";const Re=e.forwardRef((t,n)=>{const{children:s,asChild:m,style:l,className:u,...y}=t;return k().open?null:e.createElement(m?H.Slot:"div",{...y,ref:n,className:(0,S.default)("rt-ChatbarInlineStart",u),style:l},s)});Re.displayName="Chatbar.InlineStart";const Pe=e.forwardRef((t,n)=>{const{children:s,asChild:m,style:l,className:u,...y}=t;return k().open?null:e.createElement(m?H.Slot:"div",{...y,ref:n,className:(0,S.default)("rt-ChatbarInlineEnd",u),style:l},s)});Pe.displayName="Chatbar.InlineEnd";const we=e.forwardRef((t,n)=>{const{asChild:s,forceMount:m,renderAttachment:l,className:u,style:y,...p}=t,d=k();return!(d.attachments.length>0)&&!m?null:e.createElement(s?H.Slot:"div",{...p,ref:n,className:(0,S.default)("rt-ChatbarAttachmentsRow",u),style:y,role:"list","aria-label":p["aria-label"]??"Attachments"},e.createElement(De.ScrollArea,{className:"rt-ChatbarScrollArea",scrollbars:"horizontal",size:"1"},e.createElement(ae.Flex,{align:"center",gap:"2",style:{minWidth:"fit-content"}},d.attachments.map(T=>e.createElement(ce,{key:T.id,attachment:T,asChild:!!l},l?.(T))))))});we.displayName="Chatbar.AttachmentsRow";const ce=e.forwardRef((t,n)=>{const{attachment:s,asChild:m,className:l,style:u,children:y,...p}=t,d=k(),r=m?H.Slot:"div",x=!!s.url&&s.type.startsWith("image/");return e.createElement(r,{...p,ref:n,className:(0,S.default)("rt-ChatbarAttachment",l),style:u,role:"listitem","data-kind":x?"image":"file",title:s.name},y??e.createElement(ve.Card,{size:d.size,variant:"soft"},e.createElement(ae.Flex,{align:"center",gap:"3",pr:x?void 0:"6"},e.createElement("div",{className:"rt-ChatbarAttachmentPreview","aria-hidden":!0},x?e.createElement("img",{className:"rt-ChatbarAttachmentImage",src:s.url,alt:""}):e.createElement(me.FileTextIcon,null)),!x&&e.createElement(ae.Flex,{direction:"column",gap:"0",style:{minWidth:0}},e.createElement(le.Text,{size:d.size,weight:"medium",style:{whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"}},s.name),e.createElement(le.Text,{size:"1",color:"gray"},Math.ceil(s.size/1024)," KB")),e.createElement(ge.IconButton,{className:"rt-ChatbarAttachmentRemove","aria-label":`Remove ${s.name}`,size:"1",variant:"classic",highContrast:!0,color:"gray",onClick:()=>d.setAttachments(d.attachments.filter(T=>T.id!==s.id))},e.createElement(me.CloseIcon,null)))))});ce.displayName="Chatbar.Attachment";const Te=e.forwardRef((t,n)=>{const{asChild:s,accept:m,multiple:l,className:u,style:y,...p}=t,d=k(),r=e.useRef(null),x=s?H.Slot:"button",T=(Array.isArray(m)?m:m?.split(",")??[]).join(",");return e.createElement(e.Fragment,null,e.createElement(x,{...p,ref:n,className:(0,S.default)("rt-ChatbarAttachTrigger",u),style:y,type:p.type??"button","aria-label":p["aria-label"]??"Add attachments",onClick:A=>{r.current&&r.current.click(),p.onClick?.(A)}}),e.createElement("input",{ref:r,type:"file",accept:T,multiple:l??d.multiple,tabIndex:-1,style:{display:"none"},onChange:A=>{const R=Array.from(A.currentTarget.files??[]);R.length>0&&d.appendFiles(R),A.currentTarget.value=""}}))});Te.displayName="Chatbar.AttachTrigger";const Ee=e.forwardRef((t,n)=>{const{asChild:s,children:m,className:l,style:u,...y}=t;return k().open?e.createElement(s?H.Slot:"div",{...y,ref:n,className:(0,S.default)("rt-ChatbarRow",l),style:u},e.createElement(ae.Flex,{align:"center",justify:"between",width:"100%"},m)):null});Ee.displayName="Chatbar.Row";const Se=e.forwardRef((t,n)=>{const{className:s,style:m,...l}=t;return e.createElement("div",{...l,ref:n,className:(0,S.default)("rt-ChatbarRowStart",s),style:m})});Se.displayName="Chatbar.RowStart";const Me=e.forwardRef((t,n)=>{const{className:s,style:m,...l}=t;return e.createElement("div",{...l,ref:n,className:(0,S.default)("rt-ChatbarRowEnd",s),style:m})});Me.displayName="Chatbar.RowEnd";const Oe=e.forwardRef((t,n)=>{const{asChild:s,clearOnSend:m=!0,disabled:l,children:u,className:y,style:p,...d}=t,r=k(),T=r.value.trim().length>0||r.attachments.length>0,A=r.sendMode==="always"||r.sendMode==="whenDirty"&&T;if(r.sendMode==="never")return null;const R=P=>{r.disabled||r.readOnly||(r.onSubmit?.({value:r.value,attachments:r.attachments}),m&&(r.isValueControlled||r.setValue(""),r.clearOnSubmit&&r.setAttachments([])),d.onClick?.(P))};return e.createElement(ge.IconButton,{...d,ref:n,size:r.size,variant:r.open?"solid":"ghost",disabled:l||r.disabled||r.readOnly,className:(0,S.default)("rt-ChatbarSend",y),style:{opacity:A?1:0,pointerEvents:A?"auto":"none",...p},asChild:s,onClick:R,"aria-label":d["aria-label"]??"Send"},u??"Send")});Oe.displayName="Chatbar.Send";
2
2
  //# sourceMappingURL=chatbar.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/chatbar.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nimport classNames from 'classnames';\n\nimport { IconButton, type IconButtonProps } from './icon-button.js';\nimport { CloseIcon, FileTextIcon } from './icons.js';\nimport { Flex } from './flex.js';\n\nimport { ScrollArea } from './scroll-area.js';\nimport { Slot } from './slot.js';\nimport { Card } from './card.js';\nimport { Text } from './text.js';\nimport { useDropzone } from 'react-dropzone';\nimport type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js';\n\n// Avoid SSR warnings by using an isomorphic layout effect\nconst useIsomorphicLayoutEffect =\n typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;\n\ntype ExpandOn = 'none' | 'focus' | 'overflow' | 'both';\ntype SendMode = 'always' | 'whenDirty' | 'never';\n\n// Attachments\n/** Status flag for attachment lifecycle. */\ntype AttachmentStatus = 'idle' | 'uploading' | 'error' | 'done';\n/**\n * Attachment data model used by Chatbar.\n * - `url` is an object URL used for image previews and is revoked on removal.\n */\ninterface ChatbarAttachment {\n id: string;\n name: string;\n size: number;\n type: string;\n url?: string;\n status?: AttachmentStatus;\n progress?: number;\n meta?: Record<string, unknown>;\n}\n\ninterface ChatbarContextValue {\n open: boolean;\n setOpen(next: boolean): void;\n isOpenControlled: boolean;\n\n value: string;\n setValue(next: string): void;\n isValueControlled: boolean;\n\n size: '1' | '2' | '3';\n expandOn: ExpandOn;\n minLines: number;\n maxLines: number;\n sendMode: SendMode;\n disabled?: boolean;\n readOnly?: boolean;\n\n // Submit returns both message and attachments\n onSubmit?: (payload: { value: string; attachments: ChatbarAttachment[] }) => void;\n\n rootRef: React.RefObject<HTMLDivElement | null>;\n textareaRef: React.RefObject<HTMLTextAreaElement | null>;\n\n // Attachments state\n attachments: ChatbarAttachment[];\n setAttachments(next: ChatbarAttachment[]): void;\n isAttachmentsControlled: boolean;\n\n // Config\n accept?: string | string[];\n multiple: boolean;\n maxAttachments?: number;\n maxFileSize?: number;\n paste: boolean;\n pasteAccept?: string | string[];\n clearOnSubmit: boolean;\n\n // Dropzone\n dropzone: boolean;\n\n // Events\n onAttachmentReject?: (rejections: { file: File; reason: 'type' | 'size' | 'count' }[]) => void;\n\n // Helpers\n appendFiles(files: File[]): void;\n appendFilesFromPaste(files: File[]): void;\n}\n\nconst ChatbarContext = React.createContext<ChatbarContextValue | null>(null);\nconst useChatbarContext = () => {\n const ctx = React.useContext(ChatbarContext);\n if (!ctx) throw new Error('Chatbar context not found. Wrap parts in <Chatbar.Root>.');\n return ctx;\n};\n\n/**\n * Chatbar container and state provider.\n *\n * Value & Open\n * - Supports controlled/uncontrolled `value` and `open`.\n *\n * Attachments\n * - Controlled/uncontrolled attachments with client-side filtering.\n * - Filters by `accept`/`pasteAccept`, `maxAttachments`, and `maxFileSize`.\n * - Rejections are reported via `onAttachmentReject`.\n *\n * Submit\n * - `onSubmit({ value, attachments })` emits both message and attachments.\n * - `clearOnSubmit` clears message and attachments by default.\n */\ninterface ChatbarRootBaseProps {\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n\n expandOn?: ExpandOn;\n\n /** Minimum number of lines in compact state (default: 1) */\n minLines?: number;\n /** Maximum number of lines before scrolling (default: 6) */\n maxLines?: number;\n\n sendMode?: SendMode;\n\n disabled?: boolean;\n readOnly?: boolean;\n\n /** Combined submit payload */\n onSubmit?: (payload: { value: string; attachments: ChatbarAttachment[] }) => void;\n\n size?: '1' | '2' | '3';\n variant?: 'surface' | 'outline' | 'classic' | 'ghost' | 'soft';\n\n width?: React.CSSProperties['width'];\n maxWidth?: React.CSSProperties['maxWidth'];\n asChild?: boolean;\n\n // Attachments API\n attachments?: ChatbarAttachment[];\n defaultAttachments?: ChatbarAttachment[];\n onAttachmentsChange?: (attachments: ChatbarAttachment[]) => void;\n accept?: string | string[];\n multiple?: boolean;\n maxAttachments?: number;\n maxFileSize?: number;\n paste?: boolean;\n pasteAccept?: string | string[];\n clearOnSubmit?: boolean;\n onAttachmentReject?: (rejections: { file: File; reason: 'type' | 'size' | 'count' }[]) => void;\n\n /**\n * Enables drag-and-drop file uploads when true.\n *\n * When enabled:\n * - Files can be dropped anywhere on the chatbar\n * - Same validation rules apply (accept, maxFileSize, maxAttachments)\n * - Visual feedback shows during drag operations\n * - Rejected files trigger onAttachmentReject\n *\n * @default true\n */\n dropzone?: boolean;\n}\n\ntype RootElement = React.ElementRef<'div'>;\n/**\n * Chatbar container and state provider.\n *\n * Behavior\n * - Supports controlled and uncontrolled `value` and `open` states via props.\n * - Provides context to subcomponents like `Textarea`, `Row`, and `Send`.\n * - Exposes `data-state`, `data-disabled`, and `data-readonly` attributes for styling.\n * - Sets `aria-expanded` to reflect open/closed state for assistive technologies.\n *\n * Attachments\n * - Controlled/uncontrolled attachments with client-side filtering.\n * - Filters by `accept`/`pasteAccept`, `maxAttachments`, and `maxFileSize`.\n * - Rejections are reported via `onAttachmentReject`.\n * - Paste-to-attach: when `paste` is enabled, pasting files adds attachments.\n *\n * Dropzone\n * - When `dropzone` is true, enables drag-and-drop file uploads.\n * - Files are validated using the same rules as paste and file picker.\n * - Visual feedback via `data-drop-active` attribute during drag operations.\n * - Rejected files trigger `onAttachmentReject` with appropriate reasons.\n *\n * Submit\n * - `onSubmit` receives both message text and attachments array.\n * - `clearOnSubmit` controls whether attachments are cleared after submission.\n *\n * Accessibility\n * - Consumers should label the `Textarea` via `aria-label`/`aria-labelledby`.\n * - `aria-expanded` on the root reflects the disclosure state of the input area.\n * - Dropzone provides proper ARIA attributes for drag and drop operations.\n */\ninterface RootProps\n extends ComponentPropsWithout<'div', RemovedProps | 'onSubmit'>,\n ChatbarRootBaseProps {}\n\nconst Root = React.forwardRef<RootElement, RootProps>((props, forwardedRef) => {\n const {\n className,\n style,\n children,\n value: valueProp,\n defaultValue = '',\n onValueChange: onValueChangeProp,\n open: openProp,\n defaultOpen = false,\n onOpenChange: onOpenChangeProp,\n expandOn = 'both',\n minLines = 1,\n maxLines = 6,\n sendMode = 'whenDirty',\n disabled,\n readOnly,\n onSubmit,\n size = '2',\n variant,\n width,\n maxWidth,\n asChild,\n attachments: attachmentsProp,\n defaultAttachments = [],\n onAttachmentsChange,\n accept,\n multiple = true,\n maxAttachments,\n maxFileSize,\n paste = true,\n pasteAccept,\n clearOnSubmit = true,\n onAttachmentReject,\n dropzone = true,\n ...divProps\n } = props;\n\n const isValueControlled = valueProp != null;\n const [valueUncontrolled, setValueUncontrolled] = React.useState<string>(defaultValue);\n const value = isValueControlled ? (valueProp as string) : valueUncontrolled;\n\n const isOpenControlled = openProp != null;\n const [openUncontrolled, setOpenUncontrolled] = React.useState<boolean>(defaultOpen);\n const open = isOpenControlled ? (openProp as boolean) : openUncontrolled;\n\n const rootRef = React.useRef<HTMLDivElement>(null);\n const textareaRef = React.useRef<HTMLTextAreaElement>(null);\n\n // Attachments state\n const isAttachmentsControlled = attachmentsProp != null;\n const [attachmentsUncontrolled, setAttachmentsUncontrolled] =\n React.useState<ChatbarAttachment[]>(defaultAttachments);\n const attachments = isAttachmentsControlled\n ? (attachmentsProp as ChatbarAttachment[])\n : attachmentsUncontrolled;\n\n // Track generated object URLs for cleanup\n const generatedUrlSetRef = React.useRef<Set<string>>(new Set());\n\n const toArray = (val: string | string[] | undefined) =>\n Array.isArray(val) ? val : typeof val === 'string' ? val.split(',').map((s) => s.trim()) : [];\n\n const accepts = toArray(accept);\n const pasteAccepts = toArray(pasteAccept).length > 0 ? toArray(pasteAccept) : accepts;\n\n const matchesAccept = (file: File, patterns: string[]) => {\n if (patterns.length === 0) return true;\n const mime = file.type.toLowerCase();\n const name = file.name.toLowerCase();\n for (const patRaw of patterns) {\n const pat = patRaw.toLowerCase();\n if (pat.includes('/')) {\n // MIME pattern\n const [type, subtype] = pat.split('/');\n const [fmType, fmSubtype] = mime.split('/');\n if (type === '*' || (type === fmType && (subtype === '*' || subtype === fmSubtype)))\n return true;\n } else if (pat.startsWith('.')) {\n if (name.endsWith(pat)) return true;\n }\n }\n return false;\n };\n\n /**\n * Maps File objects to attachments with validation and preview URL generation.\n */\n const mapFilesToAttachments = (\n files: File[],\n ): {\n accepted: ChatbarAttachment[];\n rejected: { file: File; reason: 'type' | 'size' | 'count' }[];\n } => {\n const next: ChatbarAttachment[] = [];\n const rejected: { file: File; reason: 'type' | 'size' | 'count' }[] = [];\n\n const remainingSlots =\n typeof maxAttachments === 'number'\n ? Math.max(maxAttachments - attachments.length, 0)\n : Infinity;\n\n for (const file of files) {\n if (next.length >= remainingSlots) {\n rejected.push({ file, reason: 'count' });\n continue;\n }\n if (typeof maxFileSize === 'number' && file.size > maxFileSize) {\n rejected.push({ file, reason: 'size' });\n continue;\n }\n if (!matchesAccept(file, accepts)) {\n rejected.push({ file, reason: 'type' });\n continue;\n }\n const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n const looksLikeImageByExt = /\\.(png|jpe?g|gif|webp|bmp|svg)$/i.test(file.name);\n const isImageType = (file.type || '').toLowerCase().startsWith('image/');\n const url = isImageType || looksLikeImageByExt ? URL.createObjectURL(file) : undefined;\n if (url) generatedUrlSetRef.current.add(url);\n next.push({ id, name: file.name, size: file.size, type: file.type, url, status: 'idle' });\n }\n return { accepted: next, rejected };\n };\n\n const appendFiles = (files: File[]) => {\n const { accepted, rejected } = mapFilesToAttachments(files);\n if (accepted.length > 0) {\n const merged = attachments.concat(accepted);\n if (!isAttachmentsControlled) setAttachmentsUncontrolled(merged);\n onAttachmentsChange?.(merged);\n }\n if (rejected.length > 0) onAttachmentReject?.(rejected);\n };\n\n const appendFilesFromPaste = (files: File[]) => {\n // Use pasteAccepts for type filtering\n const matches = (file: File) => {\n if (pasteAccepts.length === 0) return matchesAccept(file, accepts);\n return matchesAccept(file, pasteAccepts);\n };\n const acceptedFiles: File[] = [];\n const rejected: { file: File; reason: 'type' | 'size' | 'count' }[] = [];\n\n // Enforce maxAttachments and maxFileSize\n const remainingSlots =\n typeof maxAttachments === 'number'\n ? Math.max(maxAttachments - attachments.length, 0)\n : Infinity;\n for (const file of files) {\n if (acceptedFiles.length >= remainingSlots) {\n rejected.push({ file, reason: 'count' });\n continue;\n }\n if (typeof maxFileSize === 'number' && file.size > maxFileSize) {\n rejected.push({ file, reason: 'size' });\n continue;\n }\n if (!matches(file)) {\n rejected.push({ file, reason: 'type' });\n continue;\n }\n acceptedFiles.push(file);\n }\n if (acceptedFiles.length > 0) appendFiles(acceptedFiles);\n if (rejected.length > 0) onAttachmentReject?.(rejected);\n };\n\n // Revoke object URLs that are no longer referenced by current attachments\n React.useEffect(() => {\n const currentUrls = new Set(attachments.map((a) => a.url).filter(Boolean) as string[]);\n for (const url of Array.from(generatedUrlSetRef.current)) {\n if (!currentUrls.has(url)) {\n URL.revokeObjectURL(url);\n generatedUrlSetRef.current.delete(url);\n }\n }\n }, [attachments]);\n\n // Revoke any remaining generated URLs on unmount\n React.useEffect(() => {\n return () => {\n for (const url of Array.from(generatedUrlSetRef.current)) {\n URL.revokeObjectURL(url);\n }\n generatedUrlSetRef.current.clear();\n };\n }, []);\n\n const Comp = asChild ? Slot : ('div' as any);\n\n const handleBlurCapture = React.useCallback(\n (event: React.FocusEvent) => {\n const nextTarget = event.relatedTarget as Node | null;\n const rootEl = rootRef.current;\n if (!rootEl) return;\n // If focus remains within root, ignore\n if (nextTarget && rootEl.contains(nextTarget)) return;\n // Collapse when leaving the root if the value is empty\n if ((value?.trim?.() ?? '').length === 0) {\n if (!isOpenControlled) setOpenUncontrolled(false);\n onOpenChangeProp?.(false);\n }\n },\n [isOpenControlled, onOpenChangeProp, value],\n );\n\n // Dropzone functionality\n const { getRootProps, getInputProps, isDragActive } = useDropzone({\n onDrop: (acceptedFiles, rejectedFiles) => {\n if (acceptedFiles.length > 0) {\n appendFiles(acceptedFiles);\n }\n if (rejectedFiles.length > 0 && onAttachmentReject) {\n const rejections = rejectedFiles.map(({ file, errors }) => {\n const reason =\n errors[0]?.code === 'file-too-large'\n ? 'size'\n : errors[0]?.code === 'file-invalid-type'\n ? 'type'\n : 'count';\n return { file, reason: reason as 'type' | 'size' | 'count' };\n });\n onAttachmentReject(rejections);\n }\n },\n accept:\n accepts.length > 0\n ? accepts.reduce(\n (acc, pattern) => {\n if (pattern.includes('/')) {\n // MIME type pattern\n acc[pattern] = [];\n } else if (pattern.startsWith('.')) {\n // File extension pattern\n acc[pattern] = [];\n }\n return acc;\n },\n {} as Record<string, string[]>,\n )\n : undefined,\n multiple,\n maxSize: maxFileSize,\n noClick: true,\n noKeyboard: true,\n disabled: !dropzone || disabled,\n });\n\n return (\n <ChatbarContext.Provider\n value={{\n open,\n setOpen: (next) => {\n if (!isOpenControlled) setOpenUncontrolled(next);\n onOpenChangeProp?.(next);\n },\n isOpenControlled,\n value,\n setValue: (next) => {\n if (!isValueControlled) setValueUncontrolled(next);\n onValueChangeProp?.(next);\n },\n isValueControlled,\n size,\n expandOn,\n minLines,\n maxLines,\n sendMode,\n disabled,\n readOnly,\n onSubmit,\n rootRef,\n textareaRef,\n attachments,\n setAttachments: (next) => {\n if (!isAttachmentsControlled) setAttachmentsUncontrolled(next);\n onAttachmentsChange?.(next);\n },\n isAttachmentsControlled,\n accept,\n multiple,\n maxAttachments,\n maxFileSize,\n paste,\n pasteAccept,\n clearOnSubmit,\n onAttachmentReject,\n dropzone,\n appendFiles,\n appendFilesFromPaste,\n }}\n >\n <Comp\n {...divProps}\n ref={(node: HTMLDivElement) => {\n if (typeof forwardedRef === 'function') forwardedRef(node);\n else if (forwardedRef)\n (forwardedRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n (rootRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n }}\n className={classNames('rt-ChatbarRoot', `rt-r-size-${size}`, className)}\n style={{ position: 'relative', width, maxWidth, ...style }}\n data-state={open ? 'open' : 'closed'}\n data-disabled={disabled ? '' : undefined}\n data-readonly={readOnly ? '' : undefined}\n data-drop-active={dropzone && isDragActive ? '' : undefined}\n aria-expanded={open}\n onBlurCapture={handleBlurCapture}\n >\n {dropzone && <input {...getInputProps()} />}\n <div {...(dropzone ? getRootProps() : {})} style={{ width: '100%', height: '100%' }}>\n <Card\n className=\"rt-ChatbarCard\"\n size={Math.min(3, Number(size) + 1).toString() as '1' | '2' | '3'}\n variant={variant as any}\n style={{ position: 'relative' }}\n >\n <div className=\"rt-ChatbarGrid\">{children}</div>\n {dropzone && isDragActive && (\n <div className=\"rt-ChatbarDropOverlay\">\n <div className=\"rt-ChatbarDropContent\">\n <Text color=\"gray\" size={size} weight=\"medium\">\n Drop files here to attach\n </Text>\n </div>\n </div>\n )}\n </Card>\n </div>\n </Comp>\n </ChatbarContext.Provider>\n );\n});\nRoot.displayName = 'Chatbar.Root';\n\n/**\n * Multi-line text input for Chatbar.\n * - Uses onChange to control value and avoid duplicate updates.\n * - Auto-resizes between minLines and maxLines.\n * - Expands on focus/overflow per `expandOn`.\n * - Paste-to-attach: when `paste` is enabled on Root, pasting files adds attachments.\n * - Provide `aria-label` or `aria-labelledby` for an accessible name.\n */\ninterface TextareaProps extends Omit<React.ComponentPropsWithoutRef<'textarea'>, 'size'> {\n asChild?: boolean;\n /**\n * Handler for paste events. This is forwarded to the underlying <textarea>.\n */\n onPaste?: React.ClipboardEventHandler<HTMLTextAreaElement>;\n /**\n * When true, pressing Enter submits via onSend (Shift+Enter inserts newline).\n * Defaults to false.\n */\n submitOnEnter?: boolean;\n}\n\n/**\n * Chatbar multi-line text input.\n *\n * Behavior\n * - Controls the Chatbar value via React onChange. We intentionally do not\n * update state in onInput to avoid duplicate updates per keystroke.\n * - Auto-resizes between minLines and maxLines using layout measurements.\n * - When expandOn is `overflow` or `both`, the Chatbar opens as soon as the\n * content exceeds the compact height.\n * - Height recalculations occur on change, paste, and whenever `value` or `open`\n * changes via an isomorphic layout effect to avoid SSR warnings.\n *\n * Accessibility\n * - Consumers should provide labeling via aria-label or aria-labelledby\n * on this component, as no implicit label is rendered.\n */\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>((props, forwardedRef) => {\n const {\n className,\n style,\n asChild,\n onFocus,\n onInput,\n onChange,\n onPaste,\n onKeyDown,\n submitOnEnter = false,\n rows,\n ...textareaProps\n } = props;\n const ctx = useChatbarContext();\n const {\n open,\n minLines,\n maxLines,\n expandOn,\n disabled,\n readOnly,\n setOpen,\n setValue,\n textareaRef,\n value,\n isValueControlled,\n sendMode,\n paste,\n appendFilesFromPaste,\n size,\n } = ctx;\n\n // Cached metrics to avoid repeated getComputedStyle calls\n const lineHeightRef = React.useRef<number>(0);\n const paddingRef = React.useRef<number>(0);\n const compactHeightRef = React.useRef<number>(0);\n\n const recomputeMetrics = React.useCallback(() => {\n const el = textareaRef.current;\n if (!el) return;\n const computedStyle = window.getComputedStyle(el);\n const lineHeight = parseFloat(computedStyle.lineHeight) || 20;\n const paddingTop = parseFloat(computedStyle.paddingTop) || 0;\n const paddingBottom = parseFloat(computedStyle.paddingBottom) || 0;\n lineHeightRef.current = lineHeight;\n paddingRef.current = paddingTop + paddingBottom;\n compactHeightRef.current = Math.ceil(1 * lineHeight) + paddingTop + paddingBottom;\n }, [textareaRef]);\n\n // Auto-resize logic - optimized for fixed widths\n const updateHeight = React.useCallback(\n (forceOpen?: boolean) => {\n const textarea = textareaRef.current;\n if (!textarea) return;\n\n textarea.style.height = 'auto';\n\n if (lineHeightRef.current === 0) {\n recomputeMetrics();\n }\n const lineHeight = lineHeightRef.current;\n const padding = paddingRef.current;\n\n const isOpen = forceOpen ?? open;\n const effectiveMinLines = isOpen ? minLines : 1;\n const effectiveMaxLines = isOpen ? maxLines : 1;\n\n const minHeight = Math.ceil(effectiveMinLines * lineHeight) + padding;\n const maxHeight = Math.ceil(effectiveMaxLines * lineHeight) + padding;\n\n const contentHeight = Math.max(textarea.scrollHeight, minHeight);\n const finalHeight = Math.min(contentHeight, maxHeight);\n\n textarea.style.height = `${finalHeight}px`;\n\n if (contentHeight > maxHeight) {\n textarea.style.overflowY = 'auto';\n textarea.style.maxHeight = `${maxHeight}px`;\n } else {\n textarea.style.overflowY = 'hidden';\n textarea.style.maxHeight = 'none';\n }\n },\n [open, minLines, maxLines, textareaRef, recomputeMetrics],\n );\n\n // Update height when value or open state changes\n useIsomorphicLayoutEffect(() => {\n updateHeight();\n }, [updateHeight, value, open]);\n\n // Recompute metrics on mount and when size changes may affect typography\n useIsomorphicLayoutEffect(() => {\n recomputeMetrics();\n updateHeight();\n }, [recomputeMetrics, updateHeight, size]);\n\n // Observe responsive changes that alter line-height\n React.useEffect(() => {\n const el = textareaRef.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n let prevLineHeight = lineHeightRef.current;\n const ro = new ResizeObserver(() => {\n const computedStyle = window.getComputedStyle(el);\n const lh = parseFloat(computedStyle.lineHeight) || 20;\n if (lh !== prevLineHeight) {\n prevLineHeight = lh;\n recomputeMetrics();\n requestAnimationFrame(() => updateHeight());\n }\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, [textareaRef, recomputeMetrics, updateHeight]);\n\n // Dev-only warning if no accessible name is provided\n React.useEffect(() => {\n if (process.env.NODE_ENV === 'production') return;\n const hasLabel =\n textareaProps['aria-label'] != null || textareaProps['aria-labelledby'] != null;\n if (!hasLabel) {\n // eslint-disable-next-line no-console\n console.warn(\n '[Chatbar.Textarea] Provide aria-label or aria-labelledby to ensure the control has an accessible name.',\n );\n }\n // warn only on mount\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Note: No MutationObserver is used because <textarea> value changes are not\n // reflected in DOM text nodes. Height updates are handled by effects and events.\n\n const handleFocus = React.useCallback<React.FocusEventHandler<HTMLTextAreaElement>>(\n (event) => {\n if (disabled || readOnly) return;\n if ((expandOn === 'focus' || expandOn === 'both') && !open) setOpen(true);\n onFocus?.(event);\n },\n [disabled, readOnly, expandOn, open, setOpen, onFocus],\n );\n\n const handleChange = React.useCallback<React.ChangeEventHandler<HTMLTextAreaElement>>(\n (event) => {\n const el = event.currentTarget;\n const nextValue = el.value;\n setValue(nextValue);\n\n if ((expandOn === 'overflow' || expandOn === 'both') && !open) {\n el.style.height = 'auto';\n\n if (compactHeightRef.current === 0) {\n recomputeMetrics();\n }\n const shouldExpand = el.scrollHeight > compactHeightRef.current + 1;\n if (shouldExpand) {\n setOpen(true);\n // Immediately size for open state to avoid 1-line + scrollbar flash\n updateHeight(true);\n requestAnimationFrame(() => updateHeight(true));\n }\n }\n\n // Always recalc after any input\n requestAnimationFrame(() => updateHeight());\n onChange?.(event);\n },\n [expandOn, open, setOpen, setValue, onChange, updateHeight, recomputeMetrics],\n );\n\n const handlePaste = React.useCallback<React.ClipboardEventHandler<HTMLTextAreaElement>>(\n (event) => {\n // Attach files from clipboard if enabled\n if (paste) {\n const items = Array.from(event.clipboardData?.items ?? []);\n const files = items\n .filter((i) => i.kind === 'file')\n .map((i) => i.getAsFile())\n .filter((f): f is File => !!f);\n if (files.length > 0) {\n appendFilesFromPaste(files);\n }\n }\n setTimeout(() => {\n // If pasting in compact mode, force sizing as open if content overflowed\n if (!open) {\n updateHeight(true);\n } else {\n updateHeight();\n }\n }, 0);\n onPaste?.(event);\n },\n [paste, open, updateHeight, onPaste, appendFilesFromPaste],\n );\n\n const handleKeyDown = React.useCallback<React.KeyboardEventHandler<HTMLTextAreaElement>>(\n (event) => {\n if (!submitOnEnter) {\n onKeyDown?.(event);\n return;\n }\n if (\n event.key === 'Enter' &&\n !event.shiftKey &&\n !event.altKey &&\n !event.ctrlKey &&\n !event.metaKey &&\n !event.nativeEvent.isComposing\n ) {\n if (disabled || readOnly) {\n onKeyDown?.(event);\n return;\n }\n if (sendMode === 'never') {\n onKeyDown?.(event);\n return;\n }\n const trimmed = value.trim();\n if (sendMode === 'whenDirty' && trimmed.length === 0) {\n onKeyDown?.(event);\n return;\n }\n event.preventDefault();\n ctx.onSubmit?.({ value, attachments: ctx.attachments });\n if (ctx.clearOnSubmit) {\n if (!isValueControlled) setValue('');\n ctx.setAttachments([]);\n }\n }\n onKeyDown?.(event);\n },\n [\n submitOnEnter,\n disabled,\n readOnly,\n sendMode,\n value,\n isValueControlled,\n setValue,\n ctx,\n onKeyDown,\n ],\n );\n\n const Comp = asChild ? Slot : ('textarea' as any);\n return (\n <div className={classNames('rt-ChatbarField', 'rt-ChatbarTextarea', className)}>\n <Comp\n {...textareaProps}\n ref={(node: HTMLTextAreaElement) => {\n if (typeof forwardedRef === 'function') forwardedRef(node);\n else if (forwardedRef)\n (forwardedRef as React.MutableRefObject<HTMLTextAreaElement | null>).current = node;\n (textareaRef as React.MutableRefObject<HTMLTextAreaElement | null>).current = node;\n }}\n className=\"rt-ChatbarInput\"\n value={value}\n onInput={onInput}\n onChange={handleChange}\n onFocus={handleFocus}\n onPaste={handlePaste}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n readOnly={readOnly}\n rows={open ? minLines : 1}\n spellCheck={textareaProps.spellCheck ?? true}\n autoCorrect={textareaProps.autoCorrect ?? 'on'}\n style={style}\n />\n </div>\n );\n});\nTextarea.displayName = 'Chatbar.Textarea';\n\ninterface InlineSlotProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'children'> {\n asChild?: boolean;\n children?: React.ReactNode;\n}\n\nconst InlineStart = React.forwardRef<HTMLDivElement, InlineSlotProps>((props, forwardedRef) => {\n const { children, asChild, style, className, ...divProps } = props;\n const ctx = useChatbarContext();\n if (ctx.open) return null;\n const Comp = asChild ? Slot : ('div' as any);\n return (\n <Comp\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarInlineStart', className)}\n style={style}\n >\n {children}\n </Comp>\n );\n});\nInlineStart.displayName = 'Chatbar.InlineStart';\n\nconst InlineEnd = React.forwardRef<HTMLDivElement, InlineSlotProps>((props, forwardedRef) => {\n const { children, asChild, style, className, ...divProps } = props;\n const ctx = useChatbarContext();\n if (ctx.open) return null;\n const Comp = asChild ? Slot : ('div' as any);\n return (\n <Comp\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarInlineEnd', className)}\n style={style}\n >\n {children}\n </Comp>\n );\n});\nInlineEnd.displayName = 'Chatbar.InlineEnd';\n\n/**\n * Renders a horizontally scrollable list of attachments above the inline row.\n * Hidden when empty unless `forceMount`. Override per-item with `renderAttachment`.\n */\ninterface AttachmentsRowProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'children'> {\n asChild?: boolean;\n forceMount?: boolean;\n /** If provided, custom-render a tile; otherwise default tile is used */\n renderAttachment?: (attachment: ChatbarAttachment) => React.ReactNode;\n}\n\nconst AttachmentsRow = React.forwardRef<HTMLDivElement, AttachmentsRowProps>(\n (props, forwardedRef) => {\n const { asChild, forceMount, renderAttachment, className, style, ...divProps } = props;\n const ctx = useChatbarContext();\n const hasItems = ctx.attachments.length > 0;\n if (!hasItems && !forceMount) return null;\n const Comp = asChild ? Slot : ('div' as any);\n return (\n <Comp\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarAttachmentsRow', className)}\n style={style}\n role=\"list\"\n aria-label={divProps['aria-label'] ?? 'Attachments'}\n >\n <ScrollArea className=\"rt-ChatbarScrollArea\" scrollbars=\"horizontal\" size=\"1\">\n <Flex align=\"center\" gap=\"2\" style={{ minWidth: 'fit-content' }}>\n {ctx.attachments.map((att) => (\n <Attachment key={att.id} attachment={att} asChild={!!renderAttachment}>\n {renderAttachment?.(att)}\n </Attachment>\n ))}\n </Flex>\n </ScrollArea>\n </Comp>\n );\n },\n);\nAttachmentsRow.displayName = 'Chatbar.AttachmentsRow';\n\n/** Default tile renderer for a single attachment. */\ninterface AttachmentProps extends React.ComponentPropsWithoutRef<'div'> {\n attachment: ChatbarAttachment;\n asChild?: boolean;\n}\n\nconst Attachment = React.forwardRef<HTMLDivElement, AttachmentProps>((props, forwardedRef) => {\n const { attachment, asChild, className, style, children, ...divProps } = props;\n const ctx = useChatbarContext();\n const Comp = asChild ? Slot : ('div' as any);\n const isImage = !!attachment.url && attachment.type.startsWith('image/');\n return (\n <Comp\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarAttachment', className)}\n style={style}\n role=\"listitem\"\n data-kind={isImage ? 'image' : 'file'}\n title={attachment.name}\n >\n {children ?? (\n <Card size={ctx.size} variant=\"soft\">\n <Flex align=\"center\" gap=\"3\" pr={!isImage ? '6' : undefined}>\n <div className=\"rt-ChatbarAttachmentPreview\" aria-hidden>\n {isImage ? (\n <img className=\"rt-ChatbarAttachmentImage\" src={attachment.url} alt=\"\" />\n ) : (\n <FileTextIcon />\n )}\n </div>\n {!isImage && (\n <Flex direction=\"column\" gap=\"0\" style={{ minWidth: 0 }}>\n <Text\n size={ctx.size}\n weight=\"medium\"\n style={{ whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}\n >\n {attachment.name}\n </Text>\n <Text size=\"1\" color=\"gray\">\n {Math.ceil(attachment.size / 1024)} KB\n </Text>\n </Flex>\n )}\n <IconButton\n className=\"rt-ChatbarAttachmentRemove\"\n aria-label={`Remove ${attachment.name}`}\n size=\"1\"\n // size={ctx.size}\n variant=\"classic\"\n highContrast\n color=\"gray\"\n onClick={() =>\n ctx.setAttachments(ctx.attachments.filter((a) => a.id !== attachment.id))\n }\n >\n <CloseIcon />\n </IconButton>\n </Flex>\n </Card>\n )}\n </Comp>\n );\n});\nAttachment.displayName = 'Chatbar.Attachment';\n\ninterface AttachTriggerProps extends React.ComponentPropsWithoutRef<'button'> {\n asChild?: boolean;\n accept?: string | string[];\n multiple?: boolean;\n}\n\nconst AttachTrigger = React.forwardRef<HTMLButtonElement, AttachTriggerProps>(\n (props, forwardedRef) => {\n const { asChild, accept, multiple, className, style, ...buttonProps } = props;\n const ctx = useChatbarContext();\n const inputRef = React.useRef<HTMLInputElement | null>(null);\n const Comp = asChild ? Slot : ('button' as any);\n const actualAccept = (Array.isArray(accept) ? accept : (accept?.split(',') ?? [])).join(',');\n return (\n <>\n <Comp\n {...(buttonProps as any)}\n ref={forwardedRef as any}\n className={classNames('rt-ChatbarAttachTrigger', className)}\n style={style}\n type={buttonProps.type ?? 'button'}\n aria-label={buttonProps['aria-label'] ?? 'Add attachments'}\n onClick={(e: any) => {\n // Ensure file input opens reliably by clicking it first\n if (inputRef.current) {\n inputRef.current.click();\n }\n // Then call user's onClick if provided\n buttonProps.onClick?.(e);\n }}\n />\n <input\n ref={inputRef}\n type=\"file\"\n accept={actualAccept}\n multiple={multiple ?? ctx.multiple}\n tabIndex={-1}\n style={{ display: 'none' }}\n onChange={(e) => {\n const files = Array.from(e.currentTarget.files ?? []);\n if (files.length > 0) {\n ctx.appendFiles(files);\n }\n // Reset input value to allow selecting the same file again\n e.currentTarget.value = '';\n }}\n />\n </>\n );\n },\n);\nAttachTrigger.displayName = 'Chatbar.AttachTrigger';\ninterface RowProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'children'> {\n asChild?: boolean;\n children?: React.ReactNode;\n}\n\nconst Row = React.forwardRef<HTMLDivElement, RowProps>((props, forwardedRef) => {\n const { asChild, children, className, style, ...divProps } = props;\n const ctx = useChatbarContext();\n if (!ctx.open) return null;\n const Comp = asChild ? Slot : ('div' as any);\n return (\n <Comp\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarRow', className)}\n style={style}\n >\n <Flex align=\"center\" justify=\"between\" width=\"100%\">\n {children}\n </Flex>\n </Comp>\n );\n});\nRow.displayName = 'Chatbar.Row';\n\nconst RowStart = React.forwardRef<HTMLDivElement, React.ComponentPropsWithoutRef<'div'>>(\n (props, forwardedRef) => {\n const { className, style, ...divProps } = props;\n return (\n <div\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarRowStart', className)}\n style={style}\n />\n );\n },\n);\nRowStart.displayName = 'Chatbar.RowStart';\n\nconst RowEnd = React.forwardRef<HTMLDivElement, React.ComponentPropsWithoutRef<'div'>>(\n (props, forwardedRef) => {\n const { className, style, ...divProps } = props;\n return (\n <div\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarRowEnd', className)}\n style={style}\n />\n );\n },\n);\nRowEnd.displayName = 'Chatbar.RowEnd';\n\ninterface SendProps extends Omit<IconButtonProps, 'size'> {\n asChild?: boolean;\n clearOnSend?: boolean;\n}\n\nconst Send = React.forwardRef<HTMLButtonElement, SendProps>((props, forwardedRef) => {\n const {\n asChild,\n clearOnSend = true,\n disabled,\n children,\n className,\n style,\n ...buttonProps\n } = props;\n const ctx = useChatbarContext();\n\n const trimmed = ctx.value.trim();\n const visible = ctx.sendMode === 'always' || (ctx.sendMode === 'whenDirty' && trimmed.length > 0);\n if (ctx.sendMode === 'never') return null;\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n if (ctx.disabled || ctx.readOnly) return;\n ctx.onSubmit?.({ value: ctx.value, attachments: ctx.attachments });\n if (clearOnSend) {\n if (!ctx.isValueControlled) ctx.setValue('');\n if (ctx.clearOnSubmit) ctx.setAttachments([]);\n }\n buttonProps.onClick?.(event);\n };\n\n return (\n <IconButton\n {...(buttonProps as any)}\n ref={forwardedRef as any}\n size={ctx.size}\n variant={ctx.open ? 'solid' : 'ghost'}\n disabled={disabled || ctx.disabled || ctx.readOnly}\n className={classNames('rt-ChatbarSend', className)}\n style={{\n opacity: visible ? 1 : 0,\n pointerEvents: visible ? 'auto' : 'none',\n ...style,\n }}\n asChild={asChild}\n onClick={handleClick}\n aria-label={buttonProps['aria-label'] ?? 'Send'}\n >\n {children ?? 'Send'}\n </IconButton>\n );\n});\nSend.displayName = 'Chatbar.Send';\n\nexport {\n Root,\n Textarea,\n InlineStart,\n InlineEnd,\n AttachmentsRow,\n Attachment,\n AttachTrigger,\n Row,\n RowStart,\n RowEnd,\n Send,\n};\nexport type {\n RootProps as ChatbarRootProps,\n TextareaProps as ChatbarTextareaProps,\n RowProps as ChatbarRowProps,\n SendProps as ChatbarSendProps,\n};\n"],
5
- "mappings": "+kBAAA,IAAAA,GAAA,GAAAC,GAAAD,GAAA,mBAAAE,GAAA,eAAAC,GAAA,mBAAAC,GAAA,cAAAC,GAAA,gBAAAC,GAAA,SAAAC,GAAA,QAAAC,GAAA,WAAAC,GAAA,aAAAC,GAAA,SAAAC,GAAA,aAAAC,KAAA,eAAAC,GAAAb,IAAA,IAAAc,EAAuB,qBACvBC,EAAuB,0BAEvBC,GAAiD,4BACjDC,GAAwC,sBACxCC,GAAqB,qBAErBC,GAA2B,4BAC3BC,EAAqB,qBACrBC,GAAqB,qBACrBC,GAAqB,qBACrBC,GAA4B,0BAI5B,MAAMC,GACJ,OAAO,OAAW,IAAcV,EAAM,gBAAkBA,EAAM,UAuE1DW,GAAiBX,EAAM,cAA0C,IAAI,EACrEY,EAAoB,IAAM,CAC9B,MAAMC,EAAMb,EAAM,WAAWW,EAAc,EAC3C,GAAI,CAACE,EAAK,MAAM,IAAI,MAAM,0DAA0D,EACpF,OAAOA,CACT,EA8GMpB,GAAOO,EAAM,WAAmC,CAACc,EAAOC,IAAiB,CAC7E,KAAM,CACJ,UAAAC,EACA,MAAAC,EACA,SAAAC,EACA,MAAOC,EACP,aAAAC,EAAe,GACf,cAAeC,EACf,KAAMC,EACN,YAAAC,EAAc,GACd,aAAcC,EACd,SAAAC,EAAW,OACX,SAAAC,EAAW,EACX,SAAAC,EAAW,EACX,SAAAC,EAAW,YACX,SAAAC,EACA,SAAAC,EACA,SAAAC,EACA,KAAAC,EAAO,IACP,QAAAC,EACA,MAAAC,EACA,SAAAC,EACA,QAAAC,EACA,YAAaC,EACb,mBAAAC,GAAqB,CAAC,EACtB,oBAAAC,EACA,OAAAC,EACA,SAAAC,EAAW,GACX,eAAAC,EACA,YAAAC,EACA,MAAAC,GAAQ,GACR,YAAAC,EACA,cAAAC,EAAgB,GAChB,mBAAAC,EACA,SAAAC,EAAW,GACX,GAAGC,EACL,EAAInC,EAEEoC,EAAoB/B,GAAa,KACjC,CAACgC,GAAmBC,EAAoB,EAAIpD,EAAM,SAAiBoB,CAAY,EAC/EiC,EAAQH,EAAqB/B,EAAuBgC,GAEpDG,EAAmBhC,GAAY,KAC/B,CAACiC,EAAkBC,CAAmB,EAAIxD,EAAM,SAAkBuB,CAAW,EAC7EkC,EAAOH,EAAoBhC,EAAuBiC,EAElDG,EAAU1D,EAAM,OAAuB,IAAI,EAC3C2D,GAAc3D,EAAM,OAA4B,IAAI,EAGpD4D,EAA0BvB,GAAmB,KAC7C,CAACwB,EAAyBC,CAA0B,EACxD9D,EAAM,SAA8BsC,EAAkB,EAClDyB,EAAcH,EACfvB,EACDwB,EAGEG,GAAqBhE,EAAM,OAAoB,IAAI,GAAK,EAExDiE,GAAWC,GACf,MAAM,QAAQA,CAAG,EAAIA,EAAM,OAAOA,GAAQ,SAAWA,EAAI,MAAM,GAAG,EAAE,IAAKC,GAAMA,EAAE,KAAK,CAAC,EAAI,CAAC,EAExFC,GAAUH,GAAQzB,CAAM,EACxB6B,GAAeJ,GAAQpB,CAAW,EAAE,OAAS,EAAIoB,GAAQpB,CAAW,EAAIuB,GAExEE,GAAgB,CAACC,EAAYC,IAAuB,CACxD,GAAIA,EAAS,SAAW,EAAG,MAAO,GAClC,MAAMC,EAAOF,EAAK,KAAK,YAAY,EAC7BG,EAAOH,EAAK,KAAK,YAAY,EACnC,UAAWI,KAAUH,EAAU,CAC7B,MAAMI,EAAMD,EAAO,YAAY,EAC/B,GAAIC,EAAI,SAAS,GAAG,EAAG,CAErB,KAAM,CAACC,GAAMC,EAAO,EAAIF,EAAI,MAAM,GAAG,EAC/B,CAACG,GAAQC,EAAS,EAAIP,EAAK,MAAM,GAAG,EAC1C,GAAII,KAAS,KAAQA,KAASE,KAAWD,KAAY,KAAOA,KAAYE,IACtE,MAAO,EACX,SAAWJ,EAAI,WAAW,GAAG,GACvBF,EAAK,SAASE,CAAG,EAAG,MAAO,EAEnC,CACA,MAAO,EACT,EAKMK,GACJC,GAIG,CACH,MAAMC,EAA4B,CAAC,EAC7BC,EAAgE,CAAC,EAEjEC,EACJ,OAAO3C,GAAmB,SACtB,KAAK,IAAIA,EAAiBqB,EAAY,OAAQ,CAAC,EAC/C,IAEN,UAAWQ,KAAQW,EAAO,CACxB,GAAIC,EAAK,QAAUE,EAAgB,CACjCD,EAAS,KAAK,CAAE,KAAAb,EAAM,OAAQ,OAAQ,CAAC,EACvC,QACF,CACA,GAAI,OAAO5B,GAAgB,UAAY4B,EAAK,KAAO5B,EAAa,CAC9DyC,EAAS,KAAK,CAAE,KAAAb,EAAM,OAAQ,MAAO,CAAC,EACtC,QACF,CACA,GAAI,CAACD,GAAcC,EAAMH,EAAO,EAAG,CACjCgB,EAAS,KAAK,CAAE,KAAAb,EAAM,OAAQ,MAAO,CAAC,EACtC,QACF,CACA,MAAMe,EAAK,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,EAAG,CAAC,CAAC,GAC5DC,GAAsB,mCAAmC,KAAKhB,EAAK,IAAI,EAEvEiB,IADejB,EAAK,MAAQ,IAAI,YAAY,EAAE,WAAW,QAAQ,GAC5CgB,GAAsB,IAAI,gBAAgBhB,CAAI,EAAI,OACzEiB,IAAKxB,GAAmB,QAAQ,IAAIwB,EAAG,EAC3CL,EAAK,KAAK,CAAE,GAAAG,EAAI,KAAMf,EAAK,KAAM,KAAMA,EAAK,KAAM,KAAMA,EAAK,KAAM,IAAAiB,GAAK,OAAQ,MAAO,CAAC,CAC1F,CACA,MAAO,CAAE,SAAUL,EAAM,SAAAC,CAAS,CACpC,EAEMK,GAAeP,GAAkB,CACrC,KAAM,CAAE,SAAAQ,EAAU,SAAAN,CAAS,EAAIH,GAAsBC,CAAK,EAC1D,GAAIQ,EAAS,OAAS,EAAG,CACvB,MAAMC,EAAS5B,EAAY,OAAO2B,CAAQ,EACrC9B,GAAyBE,EAA2B6B,CAAM,EAC/DpD,IAAsBoD,CAAM,CAC9B,CACIP,EAAS,OAAS,GAAGrC,IAAqBqC,CAAQ,CACxD,EAEMQ,GAAwBV,GAAkB,CAE9C,MAAMW,EAAWtB,GACXF,GAAa,SAAW,EAAUC,GAAcC,EAAMH,EAAO,EAC1DE,GAAcC,EAAMF,EAAY,EAEnCyB,EAAwB,CAAC,EACzBV,EAAgE,CAAC,EAGjEC,EACJ,OAAO3C,GAAmB,SACtB,KAAK,IAAIA,EAAiBqB,EAAY,OAAQ,CAAC,EAC/C,IACN,UAAWQ,KAAQW,EAAO,CACxB,GAAIY,EAAc,QAAUT,EAAgB,CAC1CD,EAAS,KAAK,CAAE,KAAAb,EAAM,OAAQ,OAAQ,CAAC,EACvC,QACF,CACA,GAAI,OAAO5B,GAAgB,UAAY4B,EAAK,KAAO5B,EAAa,CAC9DyC,EAAS,KAAK,CAAE,KAAAb,EAAM,OAAQ,MAAO,CAAC,EACtC,QACF,CACA,GAAI,CAACsB,EAAQtB,CAAI,EAAG,CAClBa,EAAS,KAAK,CAAE,KAAAb,EAAM,OAAQ,MAAO,CAAC,EACtC,QACF,CACAuB,EAAc,KAAKvB,CAAI,CACzB,CACIuB,EAAc,OAAS,GAAGL,GAAYK,CAAa,EACnDV,EAAS,OAAS,GAAGrC,IAAqBqC,CAAQ,CACxD,EAGApF,EAAM,UAAU,IAAM,CACpB,MAAM+F,EAAc,IAAI,IAAIhC,EAAY,IAAKiC,GAAMA,EAAE,GAAG,EAAE,OAAO,OAAO,CAAa,EACrF,UAAWR,KAAO,MAAM,KAAKxB,GAAmB,OAAO,EAChD+B,EAAY,IAAIP,CAAG,IACtB,IAAI,gBAAgBA,CAAG,EACvBxB,GAAmB,QAAQ,OAAOwB,CAAG,EAG3C,EAAG,CAACzB,CAAW,CAAC,EAGhB/D,EAAM,UAAU,IACP,IAAM,CACX,UAAWwF,KAAO,MAAM,KAAKxB,GAAmB,OAAO,EACrD,IAAI,gBAAgBwB,CAAG,EAEzBxB,GAAmB,QAAQ,MAAM,CACnC,EACC,CAAC,CAAC,EAEL,MAAMiC,GAAO7D,EAAU,OAAQ,MAEzB8D,GAAoBlG,EAAM,YAC7BmG,GAA4B,CAC3B,MAAMC,EAAaD,EAAM,cACnBE,EAAS3C,EAAQ,QAClB2C,IAEDD,GAAcC,EAAO,SAASD,CAAU,IAEvC/C,GAAO,OAAO,GAAK,IAAI,SAAW,IAChCC,GAAkBE,EAAoB,EAAK,EAChDhC,IAAmB,EAAK,GAE5B,EACA,CAAC8B,EAAkB9B,EAAkB6B,CAAK,CAC5C,EAGM,CAAE,aAAAiD,GAAc,cAAAC,GAAe,aAAAC,EAAa,KAAI,gBAAY,CAChE,OAAQ,CAACV,EAAeW,IAAkB,CAIxC,GAHIX,EAAc,OAAS,GACzBL,GAAYK,CAAa,EAEvBW,EAAc,OAAS,GAAK1D,EAAoB,CAClD,MAAM2D,EAAaD,EAAc,IAAI,CAAC,CAAE,KAAAlC,EAAM,OAAAoC,CAAO,IAAM,CACzD,MAAMC,EACJD,EAAO,CAAC,GAAG,OAAS,iBAChB,OACAA,EAAO,CAAC,GAAG,OAAS,oBAClB,OACA,QACR,MAAO,CAAE,KAAApC,EAAM,OAAQqC,CAAoC,CAC7D,CAAC,EACD7D,EAAmB2D,CAAU,CAC/B,CACF,EACA,OACEtC,GAAQ,OAAS,EACbA,GAAQ,OACN,CAACyC,EAAKC,KACAA,EAAQ,SAAS,GAAG,EAEtBD,EAAIC,CAAO,EAAI,CAAC,EACPA,EAAQ,WAAW,GAAG,IAE/BD,EAAIC,CAAO,EAAI,CAAC,GAEXD,GAET,CAAC,CACH,EACA,OACN,SAAApE,EACA,QAASE,EACT,QAAS,GACT,WAAY,GACZ,SAAU,CAACK,GAAYnB,CACzB,CAAC,EAED,OACE7B,EAAA,cAACW,GAAe,SAAf,CACC,MAAO,CACL,KAAA8C,EACA,QAAU0B,GAAS,CACZ7B,GAAkBE,EAAoB2B,CAAI,EAC/C3D,IAAmB2D,CAAI,CACzB,EACA,iBAAA7B,EACA,MAAAD,EACA,SAAW8B,GAAS,CACbjC,GAAmBE,GAAqB+B,CAAI,EACjD9D,IAAoB8D,CAAI,CAC1B,EACA,kBAAAjC,EACA,KAAAlB,EACA,SAAAP,EACA,SAAAC,EACA,SAAAC,EACA,SAAAC,EACA,SAAAC,EACA,SAAAC,EACA,SAAAC,EACA,QAAA2B,EACA,YAAAC,GACA,YAAAI,EACA,eAAiBoB,GAAS,CACnBvB,GAAyBE,EAA2BqB,CAAI,EAC7D5C,IAAsB4C,CAAI,CAC5B,EACA,wBAAAvB,EACA,OAAApB,EACA,SAAAC,EACA,eAAAC,EACA,YAAAC,EACA,MAAAC,GACA,YAAAC,EACA,cAAAC,EACA,mBAAAC,EACA,SAAAC,EACA,YAAAyC,GACA,qBAAAG,EACF,GAEA5F,EAAA,cAACiG,GAAA,CACE,GAAGhD,GACJ,IAAM8D,GAAyB,CACzB,OAAOhG,GAAiB,WAAYA,EAAagG,CAAI,EAChDhG,IACNA,EAA+D,QAAUgG,GAC3ErD,EAA0D,QAAUqD,CACvE,EACA,aAAW,EAAAC,SAAW,iBAAkB,aAAahF,CAAI,GAAIhB,CAAS,EACtE,MAAO,CAAE,SAAU,WAAY,MAAAkB,EAAO,SAAAC,EAAU,GAAGlB,CAAM,EACzD,aAAYwC,EAAO,OAAS,SAC5B,gBAAe5B,EAAW,GAAK,OAC/B,gBAAeC,EAAW,GAAK,OAC/B,mBAAkBkB,GAAYwD,GAAe,GAAK,OAClD,gBAAe/C,EACf,cAAeyC,IAEdlD,GAAYhD,EAAA,cAAC,SAAO,GAAGuG,GAAc,EAAG,EACzCvG,EAAA,cAAC,OAAK,GAAIgD,EAAWsD,GAAa,EAAI,CAAC,EAAI,MAAO,CAAE,MAAO,OAAQ,OAAQ,MAAO,GAChFtG,EAAA,cAAC,SACC,UAAU,iBACV,KAAM,KAAK,IAAI,EAAG,OAAOgC,CAAI,EAAI,CAAC,EAAE,SAAS,EAC7C,QAASC,EACT,MAAO,CAAE,SAAU,UAAW,GAE9BjC,EAAA,cAAC,OAAI,UAAU,kBAAkBkB,CAAS,EACzC8B,GAAYwD,IACXxG,EAAA,cAAC,OAAI,UAAU,yBACbA,EAAA,cAAC,OAAI,UAAU,yBACbA,EAAA,cAAC,SAAK,MAAM,OAAO,KAAMgC,EAAM,OAAO,UAAS,2BAE/C,CACF,CACF,CAEJ,CACF,CACF,CACF,CAEJ,CAAC,EACDvC,GAAK,YAAc,eAuCnB,MAAMK,GAAWE,EAAM,WAA+C,CAACc,EAAOC,IAAiB,CAC7F,KAAM,CACJ,UAAAC,EACA,MAAAC,EACA,QAAAmB,EACA,QAAA6E,EACA,QAAAC,EACA,SAAAC,EACA,QAAAC,EACA,UAAAC,EACA,cAAAC,EAAgB,GAChB,KAAAC,EACA,GAAGC,CACL,EAAI1G,EACED,EAAMD,EAAkB,EACxB,CACJ,KAAA6C,EACA,SAAA/B,EACA,SAAAC,EACA,SAAAF,EACA,SAAAI,EACA,SAAAC,EACA,QAAA2F,EACA,SAAAC,EACA,YAAA/D,EACA,MAAAN,EACA,kBAAAH,GACA,SAAAtB,EACA,MAAAgB,EACA,qBAAAgD,EACA,KAAA5D,CACF,EAAInB,EAGE8G,EAAgB3H,EAAM,OAAe,CAAC,EACtC4H,GAAa5H,EAAM,OAAe,CAAC,EACnC6H,EAAmB7H,EAAM,OAAe,CAAC,EAEzC8H,EAAmB9H,EAAM,YAAY,IAAM,CAC/C,MAAM+H,EAAKpE,EAAY,QACvB,GAAI,CAACoE,EAAI,OACT,MAAMC,EAAgB,OAAO,iBAAiBD,CAAE,EAC1CE,EAAa,WAAWD,EAAc,UAAU,GAAK,GACrDE,EAAa,WAAWF,EAAc,UAAU,GAAK,EACrDG,EAAgB,WAAWH,EAAc,aAAa,GAAK,EACjEL,EAAc,QAAUM,EACxBL,GAAW,QAAUM,EAAaC,EAClCN,EAAiB,QAAU,KAAK,KAAK,EAAII,CAAU,EAAIC,EAAaC,CACtE,EAAG,CAACxE,CAAW,CAAC,EAGVyE,EAAepI,EAAM,YACxBqI,GAAwB,CACvB,MAAMC,EAAW3E,EAAY,QAC7B,GAAI,CAAC2E,EAAU,OAEfA,EAAS,MAAM,OAAS,OAEpBX,EAAc,UAAY,GAC5BG,EAAiB,EAEnB,MAAMG,EAAaN,EAAc,QAC3BY,EAAUX,GAAW,QAErBY,EAASH,GAAa5E,EACtBgF,EAAoBD,EAAS9G,EAAW,EACxCgH,GAAoBF,EAAS7G,EAAW,EAExCgH,EAAY,KAAK,KAAKF,EAAoBR,CAAU,EAAIM,EACxDK,EAAY,KAAK,KAAKF,GAAoBT,CAAU,EAAIM,EAExDM,EAAgB,KAAK,IAAIP,EAAS,aAAcK,CAAS,EACzDG,EAAc,KAAK,IAAID,EAAeD,CAAS,EAErDN,EAAS,MAAM,OAAS,GAAGQ,CAAW,KAElCD,EAAgBD,GAClBN,EAAS,MAAM,UAAY,OAC3BA,EAAS,MAAM,UAAY,GAAGM,CAAS,OAEvCN,EAAS,MAAM,UAAY,SAC3BA,EAAS,MAAM,UAAY,OAE/B,EACA,CAAC7E,EAAM/B,EAAUC,EAAUgC,EAAamE,CAAgB,CAC1D,EAGApH,GAA0B,IAAM,CAC9B0H,EAAa,CACf,EAAG,CAACA,EAAc/E,EAAOI,CAAI,CAAC,EAG9B/C,GAA0B,IAAM,CAC9BoH,EAAiB,EACjBM,EAAa,CACf,EAAG,CAACN,EAAkBM,EAAcpG,CAAI,CAAC,EAGzChC,EAAM,UAAU,IAAM,CACpB,MAAM+H,EAAKpE,EAAY,QACvB,GAAI,CAACoE,GAAM,OAAO,eAAmB,IAAa,OAClD,IAAIgB,EAAiBpB,EAAc,QACnC,MAAMqB,EAAK,IAAI,eAAe,IAAM,CAClC,MAAMhB,EAAgB,OAAO,iBAAiBD,CAAE,EAC1CkB,EAAK,WAAWjB,EAAc,UAAU,GAAK,GAC/CiB,IAAOF,IACTA,EAAiBE,EACjBnB,EAAiB,EACjB,sBAAsB,IAAMM,EAAa,CAAC,EAE9C,CAAC,EACD,OAAAY,EAAG,QAAQjB,CAAE,EACN,IAAMiB,EAAG,WAAW,CAC7B,EAAG,CAACrF,EAAamE,EAAkBM,CAAY,CAAC,EAGhDpI,EAAM,UAAU,IAAM,CAYtB,EAAG,CAAC,CAAC,EAKL,MAAMkJ,EAAclJ,EAAM,YACvBmG,GAAU,CACLtE,GAAYC,KACXL,IAAa,SAAWA,IAAa,SAAW,CAACgC,GAAMgE,EAAQ,EAAI,EACxER,IAAUd,CAAK,EACjB,EACA,CAACtE,EAAUC,EAAUL,EAAUgC,EAAMgE,EAASR,CAAO,CACvD,EAEMkC,GAAenJ,EAAM,YACxBmG,GAAU,CACT,MAAM4B,EAAK5B,EAAM,cACXiD,EAAYrB,EAAG,MACrBL,EAAS0B,CAAS,GAEb3H,IAAa,YAAcA,IAAa,SAAW,CAACgC,IACvDsE,EAAG,MAAM,OAAS,OAEdF,EAAiB,UAAY,GAC/BC,EAAiB,EAEEC,EAAG,aAAeF,EAAiB,QAAU,IAEhEJ,EAAQ,EAAI,EAEZW,EAAa,EAAI,EACjB,sBAAsB,IAAMA,EAAa,EAAI,CAAC,IAKlD,sBAAsB,IAAMA,EAAa,CAAC,EAC1CjB,IAAWhB,CAAK,CAClB,EACA,CAAC1E,EAAUgC,EAAMgE,EAASC,EAAUP,EAAUiB,EAAcN,CAAgB,CAC9E,EAEMuB,EAAcrJ,EAAM,YACvBmG,GAAU,CAET,GAAIvD,EAAO,CAET,MAAMsC,EADQ,MAAM,KAAKiB,EAAM,eAAe,OAAS,CAAC,CAAC,EAEtD,OAAQmD,GAAMA,EAAE,OAAS,MAAM,EAC/B,IAAKA,GAAMA,EAAE,UAAU,CAAC,EACxB,OAAQC,GAAiB,CAAC,CAACA,CAAC,EAC3BrE,EAAM,OAAS,GACjBU,EAAqBV,CAAK,CAE9B,CACA,WAAW,IAAM,CAEVzB,EAGH2E,EAAa,EAFbA,EAAa,EAAI,CAIrB,EAAG,CAAC,EACJhB,IAAUjB,CAAK,CACjB,EACA,CAACvD,EAAOa,EAAM2E,EAAchB,EAASxB,CAAoB,CAC3D,EAEM4D,GAAgBxJ,EAAM,YACzBmG,GAAU,CACT,GAAI,CAACmB,EAAe,CAClBD,IAAYlB,CAAK,EACjB,MACF,CACA,GACEA,EAAM,MAAQ,SACd,CAACA,EAAM,UACP,CAACA,EAAM,QACP,CAACA,EAAM,SACP,CAACA,EAAM,SACP,CAACA,EAAM,YAAY,YACnB,CACA,GAAItE,GAAYC,EAAU,CACxBuF,IAAYlB,CAAK,EACjB,MACF,CACA,GAAIvE,IAAa,QAAS,CACxByF,IAAYlB,CAAK,EACjB,MACF,CACA,MAAMsD,EAAUpG,EAAM,KAAK,EAC3B,GAAIzB,IAAa,aAAe6H,EAAQ,SAAW,EAAG,CACpDpC,IAAYlB,CAAK,EACjB,MACF,CACAA,EAAM,eAAe,EACrBtF,EAAI,WAAW,CAAE,MAAAwC,EAAO,YAAaxC,EAAI,WAAY,CAAC,EAClDA,EAAI,gBACDqC,IAAmBwE,EAAS,EAAE,EACnC7G,EAAI,eAAe,CAAC,CAAC,EAEzB,CACAwG,IAAYlB,CAAK,CACnB,EACA,CACEmB,EACAzF,EACAC,EACAF,EACAyB,EACAH,GACAwE,EACA7G,EACAwG,CACF,CACF,EAEMpB,GAAO7D,EAAU,OAAQ,WAC/B,OACEpC,EAAA,cAAC,OAAI,aAAW,EAAAgH,SAAW,kBAAmB,qBAAsBhG,CAAS,GAC3EhB,EAAA,cAACiG,GAAA,CACE,GAAGuB,EACJ,IAAMT,GAA8B,CAC9B,OAAOhG,GAAiB,WAAYA,EAAagG,CAAI,EAChDhG,IACNA,EAAoE,QAAUgG,GAChFpD,EAAmE,QAAUoD,CAChF,EACA,UAAU,kBACV,MAAO1D,EACP,QAAS6D,EACT,SAAUiC,GACV,QAASD,EACT,QAASG,EACT,UAAWG,GACX,SAAU3H,EACV,SAAUC,EACV,KAAM2B,EAAO/B,EAAW,EACxB,WAAY8F,EAAc,YAAc,GACxC,YAAaA,EAAc,aAAe,KAC1C,MAAOvG,EACT,CACF,CAEJ,CAAC,EACDnB,GAAS,YAAc,mBAOvB,MAAMN,GAAcQ,EAAM,WAA4C,CAACc,EAAOC,IAAiB,CAC7F,KAAM,CAAE,SAAAG,EAAU,QAAAkB,EAAS,MAAAnB,EAAO,UAAAD,EAAW,GAAGiC,CAAS,EAAInC,EAE7D,OADYF,EAAkB,EACtB,KAAa,KAGnBZ,EAAA,cAFWoC,EAAU,OAAQ,MAE5B,CACE,GAAGa,EACJ,IAAKlC,EACL,aAAW,EAAAiG,SAAW,wBAAyBhG,CAAS,EACxD,MAAOC,GAENC,CACH,CAEJ,CAAC,EACD1B,GAAY,YAAc,sBAE1B,MAAMD,GAAYS,EAAM,WAA4C,CAACc,EAAOC,IAAiB,CAC3F,KAAM,CAAE,SAAAG,EAAU,QAAAkB,EAAS,MAAAnB,EAAO,UAAAD,EAAW,GAAGiC,CAAS,EAAInC,EAE7D,OADYF,EAAkB,EACtB,KAAa,KAGnBZ,EAAA,cAFWoC,EAAU,OAAQ,MAE5B,CACE,GAAGa,EACJ,IAAKlC,EACL,aAAW,EAAAiG,SAAW,sBAAuBhG,CAAS,EACtD,MAAOC,GAENC,CACH,CAEJ,CAAC,EACD3B,GAAU,YAAc,oBAaxB,MAAMD,GAAiBU,EAAM,WAC3B,CAACc,EAAOC,IAAiB,CACvB,KAAM,CAAE,QAAAqB,EAAS,WAAAsH,EAAY,iBAAAC,EAAkB,UAAA3I,EAAW,MAAAC,EAAO,GAAGgC,CAAS,EAAInC,EAC3ED,EAAMD,EAAkB,EAE9B,MAAI,EADaC,EAAI,YAAY,OAAS,IACzB,CAAC6I,EAAmB,KAGnC1J,EAAA,cAFWoC,EAAU,OAAQ,MAE5B,CACE,GAAGa,EACJ,IAAKlC,EACL,aAAW,EAAAiG,SAAW,2BAA4BhG,CAAS,EAC3D,MAAOC,EACP,KAAK,OACL,aAAYgC,EAAS,YAAY,GAAK,eAEtCjD,EAAA,cAAC,eAAW,UAAU,uBAAuB,WAAW,aAAa,KAAK,KACxEA,EAAA,cAAC,SAAK,MAAM,SAAS,IAAI,IAAI,MAAO,CAAE,SAAU,aAAc,GAC3Da,EAAI,YAAY,IAAK+I,GACpB5J,EAAA,cAACX,GAAA,CAAW,IAAKuK,EAAI,GAAI,WAAYA,EAAK,QAAS,CAAC,CAACD,GAClDA,IAAmBC,CAAG,CACzB,CACD,CACH,CACF,CACF,CAEJ,CACF,EACAtK,GAAe,YAAc,yBAQ7B,MAAMD,GAAaW,EAAM,WAA4C,CAACc,EAAOC,IAAiB,CAC5F,KAAM,CAAE,WAAA8I,EAAY,QAAAzH,EAAS,UAAApB,EAAW,MAAAC,EAAO,SAAAC,EAAU,GAAG+B,CAAS,EAAInC,EACnED,EAAMD,EAAkB,EACxBqF,EAAO7D,EAAU,OAAQ,MACzB0H,EAAU,CAAC,CAACD,EAAW,KAAOA,EAAW,KAAK,WAAW,QAAQ,EACvE,OACE7J,EAAA,cAACiG,EAAA,CACE,GAAGhD,EACJ,IAAKlC,EACL,aAAW,EAAAiG,SAAW,uBAAwBhG,CAAS,EACvD,MAAOC,EACP,KAAK,WACL,YAAW6I,EAAU,QAAU,OAC/B,MAAOD,EAAW,MAEjB3I,GACClB,EAAA,cAAC,SAAK,KAAMa,EAAI,KAAM,QAAQ,QAC5Bb,EAAA,cAAC,SAAK,MAAM,SAAS,IAAI,IAAI,GAAK8J,EAAgB,OAAN,KAC1C9J,EAAA,cAAC,OAAI,UAAU,8BAA8B,cAAW,IACrD8J,EACC9J,EAAA,cAAC,OAAI,UAAU,4BAA4B,IAAK6J,EAAW,IAAK,IAAI,GAAG,EAEvE7J,EAAA,cAAC,oBAAa,CAElB,EACC,CAAC8J,GACA9J,EAAA,cAAC,SAAK,UAAU,SAAS,IAAI,IAAI,MAAO,CAAE,SAAU,CAAE,GACpDA,EAAA,cAAC,SACC,KAAMa,EAAI,KACV,OAAO,SACP,MAAO,CAAE,WAAY,SAAU,SAAU,SAAU,aAAc,UAAW,GAE3EgJ,EAAW,IACd,EACA7J,EAAA,cAAC,SAAK,KAAK,IAAI,MAAM,QAClB,KAAK,KAAK6J,EAAW,KAAO,IAAI,EAAE,KACrC,CACF,EAEF7J,EAAA,cAAC,eACC,UAAU,6BACV,aAAY,UAAU6J,EAAW,IAAI,GACrC,KAAK,IAEL,QAAQ,UACR,aAAY,GACZ,MAAM,OACN,QAAS,IACPhJ,EAAI,eAAeA,EAAI,YAAY,OAAQmF,GAAMA,EAAE,KAAO6D,EAAW,EAAE,CAAC,GAG1E7J,EAAA,cAAC,iBAAU,CACb,CACF,CACF,CAEJ,CAEJ,CAAC,EACDX,GAAW,YAAc,qBAQzB,MAAMD,GAAgBY,EAAM,WAC1B,CAACc,EAAOC,IAAiB,CACvB,KAAM,CAAE,QAAAqB,EAAS,OAAAI,EAAQ,SAAAC,EAAU,UAAAzB,EAAW,MAAAC,EAAO,GAAG8I,CAAY,EAAIjJ,EAClED,EAAMD,EAAkB,EACxBoJ,EAAWhK,EAAM,OAAgC,IAAI,EACrDiG,EAAO7D,EAAU,OAAQ,SACzB6H,GAAgB,MAAM,QAAQzH,CAAM,EAAIA,EAAUA,GAAQ,MAAM,GAAG,GAAK,CAAC,GAAI,KAAK,GAAG,EAC3F,OACExC,EAAA,cAAAA,EAAA,cACEA,EAAA,cAACiG,EAAA,CACE,GAAI8D,EACL,IAAKhJ,EACL,aAAW,EAAAiG,SAAW,0BAA2BhG,CAAS,EAC1D,MAAOC,EACP,KAAM8I,EAAY,MAAQ,SAC1B,aAAYA,EAAY,YAAY,GAAK,kBACzC,QAAUG,GAAW,CAEfF,EAAS,SACXA,EAAS,QAAQ,MAAM,EAGzBD,EAAY,UAAUG,CAAC,CACzB,EACF,EACAlK,EAAA,cAAC,SACC,IAAKgK,EACL,KAAK,OACL,OAAQC,EACR,SAAUxH,GAAY5B,EAAI,SAC1B,SAAU,GACV,MAAO,CAAE,QAAS,MAAO,EACzB,SAAWqJ,GAAM,CACf,MAAMhF,EAAQ,MAAM,KAAKgF,EAAE,cAAc,OAAS,CAAC,CAAC,EAChDhF,EAAM,OAAS,GACjBrE,EAAI,YAAYqE,CAAK,EAGvBgF,EAAE,cAAc,MAAQ,EAC1B,EACF,CACF,CAEJ,CACF,EACA9K,GAAc,YAAc,wBAM5B,MAAMM,GAAMM,EAAM,WAAqC,CAACc,EAAOC,IAAiB,CAC9E,KAAM,CAAE,QAAAqB,EAAS,SAAAlB,EAAU,UAAAF,EAAW,MAAAC,EAAO,GAAGgC,CAAS,EAAInC,EAE7D,OADYF,EAAkB,EACrB,KAGPZ,EAAA,cAFWoC,EAAU,OAAQ,MAE5B,CACE,GAAGa,EACJ,IAAKlC,EACL,aAAW,EAAAiG,SAAW,gBAAiBhG,CAAS,EAChD,MAAOC,GAEPjB,EAAA,cAAC,SAAK,MAAM,SAAS,QAAQ,UAAU,MAAM,QAC1CkB,CACH,CACF,EAZoB,IAcxB,CAAC,EACDxB,GAAI,YAAc,cAElB,MAAME,GAAWI,EAAM,WACrB,CAACc,EAAOC,IAAiB,CACvB,KAAM,CAAE,UAAAC,EAAW,MAAAC,EAAO,GAAGgC,CAAS,EAAInC,EAC1C,OACEd,EAAA,cAAC,OACE,GAAGiD,EACJ,IAAKlC,EACL,aAAW,EAAAiG,SAAW,qBAAsBhG,CAAS,EACrD,MAAOC,EACT,CAEJ,CACF,EACArB,GAAS,YAAc,mBAEvB,MAAMD,GAASK,EAAM,WACnB,CAACc,EAAOC,IAAiB,CACvB,KAAM,CAAE,UAAAC,EAAW,MAAAC,EAAO,GAAGgC,CAAS,EAAInC,EAC1C,OACEd,EAAA,cAAC,OACE,GAAGiD,EACJ,IAAKlC,EACL,aAAW,EAAAiG,SAAW,mBAAoBhG,CAAS,EACnD,MAAOC,EACT,CAEJ,CACF,EACAtB,GAAO,YAAc,iBAOrB,MAAME,GAAOG,EAAM,WAAyC,CAACc,EAAOC,IAAiB,CACnF,KAAM,CACJ,QAAAqB,EACA,YAAA+H,EAAc,GACd,SAAAtI,EACA,SAAAX,EACA,UAAAF,EACA,MAAAC,EACA,GAAG8I,CACL,EAAIjJ,EACED,EAAMD,EAAkB,EAExB6I,EAAU5I,EAAI,MAAM,KAAK,EACzBuJ,EAAUvJ,EAAI,WAAa,UAAaA,EAAI,WAAa,aAAe4I,EAAQ,OAAS,EAC/F,GAAI5I,EAAI,WAAa,QAAS,OAAO,KAErC,MAAMwJ,EAAelE,GAA+C,CAC9DtF,EAAI,UAAYA,EAAI,WACxBA,EAAI,WAAW,CAAE,MAAOA,EAAI,MAAO,YAAaA,EAAI,WAAY,CAAC,EAC7DsJ,IACGtJ,EAAI,mBAAmBA,EAAI,SAAS,EAAE,EACvCA,EAAI,eAAeA,EAAI,eAAe,CAAC,CAAC,GAE9CkJ,EAAY,UAAU5D,CAAK,EAC7B,EAEA,OACEnG,EAAA,cAAC,eACE,GAAI+J,EACL,IAAKhJ,EACL,KAAMF,EAAI,KACV,QAASA,EAAI,KAAO,QAAU,QAC9B,SAAUgB,GAAYhB,EAAI,UAAYA,EAAI,SAC1C,aAAW,EAAAmG,SAAW,iBAAkBhG,CAAS,EACjD,MAAO,CACL,QAASoJ,EAAU,EAAI,EACvB,cAAeA,EAAU,OAAS,OAClC,GAAGnJ,CACL,EACA,QAASmB,EACT,QAASiI,EACT,aAAYN,EAAY,YAAY,GAAK,QAExC7I,GAAY,MACf,CAEJ,CAAC,EACDrB,GAAK,YAAc",
6
- "names": ["chatbar_exports", "__export", "AttachTrigger", "Attachment", "AttachmentsRow", "InlineEnd", "InlineStart", "Root", "Row", "RowEnd", "RowStart", "Send", "Textarea", "__toCommonJS", "React", "import_classnames", "import_icon_button", "import_icons", "import_flex", "import_scroll_area", "import_slot", "import_card", "import_text", "import_react_dropzone", "useIsomorphicLayoutEffect", "ChatbarContext", "useChatbarContext", "ctx", "props", "forwardedRef", "className", "style", "children", "valueProp", "defaultValue", "onValueChangeProp", "openProp", "defaultOpen", "onOpenChangeProp", "expandOn", "minLines", "maxLines", "sendMode", "disabled", "readOnly", "onSubmit", "size", "variant", "width", "maxWidth", "asChild", "attachmentsProp", "defaultAttachments", "onAttachmentsChange", "accept", "multiple", "maxAttachments", "maxFileSize", "paste", "pasteAccept", "clearOnSubmit", "onAttachmentReject", "dropzone", "divProps", "isValueControlled", "valueUncontrolled", "setValueUncontrolled", "value", "isOpenControlled", "openUncontrolled", "setOpenUncontrolled", "open", "rootRef", "textareaRef", "isAttachmentsControlled", "attachmentsUncontrolled", "setAttachmentsUncontrolled", "attachments", "generatedUrlSetRef", "toArray", "val", "s", "accepts", "pasteAccepts", "matchesAccept", "file", "patterns", "mime", "name", "patRaw", "pat", "type", "subtype", "fmType", "fmSubtype", "mapFilesToAttachments", "files", "next", "rejected", "remainingSlots", "id", "looksLikeImageByExt", "url", "appendFiles", "accepted", "merged", "appendFilesFromPaste", "matches", "acceptedFiles", "currentUrls", "a", "Comp", "handleBlurCapture", "event", "nextTarget", "rootEl", "getRootProps", "getInputProps", "isDragActive", "rejectedFiles", "rejections", "errors", "reason", "acc", "pattern", "node", "classNames", "onFocus", "onInput", "onChange", "onPaste", "onKeyDown", "submitOnEnter", "rows", "textareaProps", "setOpen", "setValue", "lineHeightRef", "paddingRef", "compactHeightRef", "recomputeMetrics", "el", "computedStyle", "lineHeight", "paddingTop", "paddingBottom", "updateHeight", "forceOpen", "textarea", "padding", "isOpen", "effectiveMinLines", "effectiveMaxLines", "minHeight", "maxHeight", "contentHeight", "finalHeight", "prevLineHeight", "ro", "lh", "handleFocus", "handleChange", "nextValue", "handlePaste", "i", "f", "handleKeyDown", "trimmed", "forceMount", "renderAttachment", "att", "attachment", "isImage", "buttonProps", "inputRef", "actualAccept", "e", "clearOnSend", "visible", "handleClick"]
4
+ "sourcesContent": ["import * as React from 'react';\nimport classNames from 'classnames';\n\nimport { IconButton, type IconButtonProps } from './icon-button.js';\nimport { CloseIcon, FileTextIcon } from './icons.js';\nimport { Flex } from './flex.js';\n\nimport { ScrollArea } from './scroll-area.js';\nimport { Slot } from './slot.js';\nimport { Card } from './card.js';\nimport { Text } from './text.js';\nimport { useDropzone } from 'react-dropzone';\nimport type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js';\n\n// Avoid SSR warnings by using an isomorphic layout effect\nconst useIsomorphicLayoutEffect =\n typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;\n\ntype ExpandOn = 'none' | 'focus' | 'overflow' | 'both';\ntype SendMode = 'always' | 'whenDirty' | 'never';\n\n// Attachments\n/** Status flag for attachment lifecycle. */\ntype AttachmentStatus = 'idle' | 'uploading' | 'error' | 'done';\n/**\n * Attachment data model used by Chatbar.\n * - `file` exposes the original File object for uploads and processing.\n * - `url` is an object URL used for image previews and is revoked on removal.\n */\ninterface ChatbarAttachment {\n id: string;\n name: string;\n size: number;\n type: string;\n /** Original File object for uploads and processing */\n file: File;\n url?: string;\n status?: AttachmentStatus;\n progress?: number;\n meta?: Record<string, unknown>;\n}\n\ninterface ChatbarContextValue {\n open: boolean;\n setOpen(next: boolean): void;\n isOpenControlled: boolean;\n\n value: string;\n setValue(next: string): void;\n isValueControlled: boolean;\n\n size: '1' | '2' | '3';\n expandOn: ExpandOn;\n minLines: number;\n maxLines: number;\n sendMode: SendMode;\n disabled?: boolean;\n readOnly?: boolean;\n\n // Submit returns both message and attachments\n onSubmit?: (payload: { value: string; attachments: ChatbarAttachment[] }) => void;\n\n rootRef: React.RefObject<HTMLDivElement | null>;\n textareaRef: React.RefObject<HTMLTextAreaElement | null>;\n\n // Attachments state\n attachments: ChatbarAttachment[];\n setAttachments(next: ChatbarAttachment[]): void;\n isAttachmentsControlled: boolean;\n\n // Config\n accept?: string | string[];\n multiple: boolean;\n maxAttachments?: number;\n maxFileSize?: number;\n paste: boolean;\n pasteAccept?: string | string[];\n clearOnSubmit: boolean;\n\n // Dropzone\n dropzone: boolean;\n\n // Events\n onAttachmentReject?: (rejections: { file: File; reason: 'type' | 'size' | 'count' }[]) => void;\n\n // Helpers\n appendFiles(files: File[]): void;\n appendFilesFromPaste(files: File[]): void;\n}\n\nconst ChatbarContext = React.createContext<ChatbarContextValue | null>(null);\nconst useChatbarContext = () => {\n const ctx = React.useContext(ChatbarContext);\n if (!ctx) throw new Error('Chatbar context not found. Wrap parts in <Chatbar.Root>.');\n return ctx;\n};\n\n/**\n * Chatbar container and state provider.\n *\n * Value & Open\n * - Supports controlled/uncontrolled `value` and `open`.\n *\n * Attachments\n * - Controlled/uncontrolled attachments with client-side filtering.\n * - Filters by `accept`/`pasteAccept`, `maxAttachments`, and `maxFileSize`.\n * - Rejections are reported via `onAttachmentReject`.\n *\n * Submit\n * - `onSubmit({ value, attachments })` emits both message and attachments.\n * - `clearOnSubmit` clears message and attachments by default.\n */\ninterface ChatbarRootBaseProps {\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n\n expandOn?: ExpandOn;\n\n /** Minimum number of lines in compact state (default: 1) */\n minLines?: number;\n /** Maximum number of lines before scrolling (default: 6) */\n maxLines?: number;\n\n sendMode?: SendMode;\n\n disabled?: boolean;\n readOnly?: boolean;\n\n /** Combined submit payload */\n onSubmit?: (payload: { value: string; attachments: ChatbarAttachment[] }) => void;\n\n size?: '1' | '2' | '3';\n variant?: 'surface' | 'outline' | 'classic' | 'ghost' | 'soft';\n\n width?: React.CSSProperties['width'];\n maxWidth?: React.CSSProperties['maxWidth'];\n asChild?: boolean;\n\n // Attachments API\n attachments?: ChatbarAttachment[];\n defaultAttachments?: ChatbarAttachment[];\n onAttachmentsChange?: (attachments: ChatbarAttachment[]) => void;\n accept?: string | string[];\n multiple?: boolean;\n maxAttachments?: number;\n maxFileSize?: number;\n paste?: boolean;\n pasteAccept?: string | string[];\n clearOnSubmit?: boolean;\n onAttachmentReject?: (rejections: { file: File; reason: 'type' | 'size' | 'count' }[]) => void;\n\n /**\n * Enables drag-and-drop file uploads when true.\n *\n * When enabled:\n * - Files can be dropped anywhere on the chatbar\n * - Same validation rules apply (accept, maxFileSize, maxAttachments)\n * - Visual feedback shows during drag operations\n * - Rejected files trigger onAttachmentReject\n *\n * @default true\n */\n dropzone?: boolean;\n}\n\ntype RootElement = React.ElementRef<'div'>;\n/**\n * Chatbar container and state provider.\n *\n * Behavior\n * - Supports controlled and uncontrolled `value` and `open` states via props.\n * - Provides context to subcomponents like `Textarea`, `Row`, and `Send`.\n * - Exposes `data-state`, `data-disabled`, and `data-readonly` attributes for styling.\n * - Sets `aria-expanded` to reflect open/closed state for assistive technologies.\n *\n * Attachments\n * - Controlled/uncontrolled attachments with client-side filtering.\n * - Filters by `accept`/`pasteAccept`, `maxAttachments`, and `maxFileSize`.\n * - Rejections are reported via `onAttachmentReject`.\n * - Paste-to-attach: when `paste` is enabled, pasting files adds attachments.\n *\n * Dropzone\n * - When `dropzone` is true, enables drag-and-drop file uploads.\n * - Files are validated using the same rules as paste and file picker.\n * - Visual feedback via `data-drop-active` attribute during drag operations.\n * - Rejected files trigger `onAttachmentReject` with appropriate reasons.\n *\n * Submit\n * - `onSubmit` receives both message text and attachments array.\n * - `clearOnSubmit` controls whether attachments are cleared after submission.\n *\n * Accessibility\n * - Consumers should label the `Textarea` via `aria-label`/`aria-labelledby`.\n * - `aria-expanded` on the root reflects the disclosure state of the input area.\n * - Dropzone provides proper ARIA attributes for drag and drop operations.\n */\ninterface RootProps\n extends ComponentPropsWithout<'div', RemovedProps | 'onSubmit'>,\n ChatbarRootBaseProps {}\n\nconst Root = React.forwardRef<RootElement, RootProps>((props, forwardedRef) => {\n const {\n className,\n style,\n children,\n value: valueProp,\n defaultValue = '',\n onValueChange: onValueChangeProp,\n open: openProp,\n defaultOpen = false,\n onOpenChange: onOpenChangeProp,\n expandOn = 'both',\n minLines = 1,\n maxLines = 6,\n sendMode = 'whenDirty',\n disabled,\n readOnly,\n onSubmit,\n size = '2',\n variant,\n width,\n maxWidth,\n asChild,\n attachments: attachmentsProp,\n defaultAttachments = [],\n onAttachmentsChange,\n accept,\n multiple = true,\n maxAttachments,\n maxFileSize,\n paste = true,\n pasteAccept,\n clearOnSubmit = true,\n onAttachmentReject,\n dropzone = true,\n ...divProps\n } = props;\n\n const isValueControlled = valueProp != null;\n const [valueUncontrolled, setValueUncontrolled] = React.useState<string>(defaultValue);\n const value = isValueControlled ? (valueProp as string) : valueUncontrolled;\n\n const isOpenControlled = openProp != null;\n const [openUncontrolled, setOpenUncontrolled] = React.useState<boolean>(defaultOpen);\n const open = isOpenControlled ? (openProp as boolean) : openUncontrolled;\n\n const rootRef = React.useRef<HTMLDivElement>(null);\n const textareaRef = React.useRef<HTMLTextAreaElement>(null);\n\n // Attachments state\n const isAttachmentsControlled = attachmentsProp != null;\n const [attachmentsUncontrolled, setAttachmentsUncontrolled] =\n React.useState<ChatbarAttachment[]>(defaultAttachments);\n const attachments = isAttachmentsControlled\n ? (attachmentsProp as ChatbarAttachment[])\n : attachmentsUncontrolled;\n\n // Track generated object URLs for cleanup\n const generatedUrlSetRef = React.useRef<Set<string>>(new Set());\n\n const toArray = (val: string | string[] | undefined) =>\n Array.isArray(val) ? val : typeof val === 'string' ? val.split(',').map((s) => s.trim()) : [];\n\n const accepts = toArray(accept);\n const pasteAccepts = toArray(pasteAccept).length > 0 ? toArray(pasteAccept) : accepts;\n\n const matchesAccept = (file: File, patterns: string[]) => {\n if (patterns.length === 0) return true;\n const mime = file.type.toLowerCase();\n const name = file.name.toLowerCase();\n for (const patRaw of patterns) {\n const pat = patRaw.toLowerCase();\n if (pat.includes('/')) {\n // MIME pattern\n const [type, subtype] = pat.split('/');\n const [fmType, fmSubtype] = mime.split('/');\n if (type === '*' || (type === fmType && (subtype === '*' || subtype === fmSubtype)))\n return true;\n } else if (pat.startsWith('.')) {\n if (name.endsWith(pat)) return true;\n }\n }\n return false;\n };\n\n /**\n * Maps File objects to attachments with validation and preview URL generation.\n */\n const mapFilesToAttachments = (\n files: File[],\n ): {\n accepted: ChatbarAttachment[];\n rejected: { file: File; reason: 'type' | 'size' | 'count' }[];\n } => {\n const next: ChatbarAttachment[] = [];\n const rejected: { file: File; reason: 'type' | 'size' | 'count' }[] = [];\n\n const remainingSlots =\n typeof maxAttachments === 'number'\n ? Math.max(maxAttachments - attachments.length, 0)\n : Infinity;\n\n for (const file of files) {\n if (next.length >= remainingSlots) {\n rejected.push({ file, reason: 'count' });\n continue;\n }\n if (typeof maxFileSize === 'number' && file.size > maxFileSize) {\n rejected.push({ file, reason: 'size' });\n continue;\n }\n if (!matchesAccept(file, accepts)) {\n rejected.push({ file, reason: 'type' });\n continue;\n }\n const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n const looksLikeImageByExt = /\\.(png|jpe?g|gif|webp|bmp|svg)$/i.test(file.name);\n const isImageType = (file.type || '').toLowerCase().startsWith('image/');\n const url = isImageType || looksLikeImageByExt ? URL.createObjectURL(file) : undefined;\n if (url) generatedUrlSetRef.current.add(url);\n next.push({\n id,\n name: file.name,\n size: file.size,\n type: file.type,\n file,\n url,\n status: 'idle',\n });\n }\n return { accepted: next, rejected };\n };\n\n const appendFiles = (files: File[]) => {\n const { accepted, rejected } = mapFilesToAttachments(files);\n if (accepted.length > 0) {\n const merged = attachments.concat(accepted);\n if (!isAttachmentsControlled) setAttachmentsUncontrolled(merged);\n onAttachmentsChange?.(merged);\n }\n if (rejected.length > 0) onAttachmentReject?.(rejected);\n };\n\n const appendFilesFromPaste = (files: File[]) => {\n // Use pasteAccepts for type filtering\n const matches = (file: File) => {\n if (pasteAccepts.length === 0) return matchesAccept(file, accepts);\n return matchesAccept(file, pasteAccepts);\n };\n const acceptedFiles: File[] = [];\n const rejected: { file: File; reason: 'type' | 'size' | 'count' }[] = [];\n\n // Enforce maxAttachments and maxFileSize\n const remainingSlots =\n typeof maxAttachments === 'number'\n ? Math.max(maxAttachments - attachments.length, 0)\n : Infinity;\n for (const file of files) {\n if (acceptedFiles.length >= remainingSlots) {\n rejected.push({ file, reason: 'count' });\n continue;\n }\n if (typeof maxFileSize === 'number' && file.size > maxFileSize) {\n rejected.push({ file, reason: 'size' });\n continue;\n }\n if (!matches(file)) {\n rejected.push({ file, reason: 'type' });\n continue;\n }\n acceptedFiles.push(file);\n }\n if (acceptedFiles.length > 0) appendFiles(acceptedFiles);\n if (rejected.length > 0) onAttachmentReject?.(rejected);\n };\n\n // Revoke object URLs that are no longer referenced by current attachments\n React.useEffect(() => {\n const currentUrls = new Set(attachments.map((a) => a.url).filter(Boolean) as string[]);\n for (const url of Array.from(generatedUrlSetRef.current)) {\n if (!currentUrls.has(url)) {\n URL.revokeObjectURL(url);\n generatedUrlSetRef.current.delete(url);\n }\n }\n }, [attachments]);\n\n // Revoke any remaining generated URLs on unmount\n React.useEffect(() => {\n return () => {\n for (const url of Array.from(generatedUrlSetRef.current)) {\n URL.revokeObjectURL(url);\n }\n generatedUrlSetRef.current.clear();\n };\n }, []);\n\n const Comp = asChild ? Slot : ('div' as any);\n\n const handleBlurCapture = React.useCallback(\n (event: React.FocusEvent) => {\n const nextTarget = event.relatedTarget as Node | null;\n const rootEl = rootRef.current;\n if (!rootEl) return;\n // If focus remains within root, ignore\n if (nextTarget && rootEl.contains(nextTarget)) return;\n // Collapse when leaving the root if the value is empty\n if ((value?.trim?.() ?? '').length === 0) {\n if (!isOpenControlled) setOpenUncontrolled(false);\n onOpenChangeProp?.(false);\n }\n },\n [isOpenControlled, onOpenChangeProp, value],\n );\n\n // Dropzone functionality\n const { getRootProps, getInputProps, isDragActive } = useDropzone({\n onDrop: (acceptedFiles, rejectedFiles) => {\n if (acceptedFiles.length > 0) {\n appendFiles(acceptedFiles);\n }\n if (rejectedFiles.length > 0 && onAttachmentReject) {\n const rejections = rejectedFiles.map(({ file, errors }) => {\n const reason =\n errors[0]?.code === 'file-too-large'\n ? 'size'\n : errors[0]?.code === 'file-invalid-type'\n ? 'type'\n : 'count';\n return { file, reason: reason as 'type' | 'size' | 'count' };\n });\n onAttachmentReject(rejections);\n }\n },\n accept:\n accepts.length > 0\n ? accepts.reduce(\n (acc, pattern) => {\n if (pattern.includes('/')) {\n // MIME type pattern\n acc[pattern] = [];\n } else if (pattern.startsWith('.')) {\n // File extension pattern\n acc[pattern] = [];\n }\n return acc;\n },\n {} as Record<string, string[]>,\n )\n : undefined,\n multiple,\n maxSize: maxFileSize,\n noClick: true,\n noKeyboard: true,\n disabled: !dropzone || disabled,\n });\n\n return (\n <ChatbarContext.Provider\n value={{\n open,\n setOpen: (next) => {\n if (!isOpenControlled) setOpenUncontrolled(next);\n onOpenChangeProp?.(next);\n },\n isOpenControlled,\n value,\n setValue: (next) => {\n if (!isValueControlled) setValueUncontrolled(next);\n onValueChangeProp?.(next);\n },\n isValueControlled,\n size,\n expandOn,\n minLines,\n maxLines,\n sendMode,\n disabled,\n readOnly,\n onSubmit,\n rootRef,\n textareaRef,\n attachments,\n setAttachments: (next) => {\n if (!isAttachmentsControlled) setAttachmentsUncontrolled(next);\n onAttachmentsChange?.(next);\n },\n isAttachmentsControlled,\n accept,\n multiple,\n maxAttachments,\n maxFileSize,\n paste,\n pasteAccept,\n clearOnSubmit,\n onAttachmentReject,\n dropzone,\n appendFiles,\n appendFilesFromPaste,\n }}\n >\n <Comp\n {...divProps}\n ref={(node: HTMLDivElement) => {\n if (typeof forwardedRef === 'function') forwardedRef(node);\n else if (forwardedRef)\n (forwardedRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n (rootRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n }}\n className={classNames('rt-ChatbarRoot', `rt-r-size-${size}`, className)}\n style={{ position: 'relative', width, maxWidth, ...style }}\n data-state={open ? 'open' : 'closed'}\n data-disabled={disabled ? '' : undefined}\n data-readonly={readOnly ? '' : undefined}\n data-drop-active={dropzone && isDragActive ? '' : undefined}\n aria-expanded={open}\n onBlurCapture={handleBlurCapture}\n >\n {dropzone && <input {...getInputProps()} />}\n <div {...(dropzone ? getRootProps() : {})} style={{ width: '100%', height: '100%' }}>\n <Card\n className=\"rt-ChatbarCard\"\n size={Math.min(3, Number(size) + 1).toString() as '1' | '2' | '3'}\n variant={variant as any}\n style={{ position: 'relative' }}\n >\n <div className=\"rt-ChatbarGrid\">{children}</div>\n {dropzone && isDragActive && (\n <div className=\"rt-ChatbarDropOverlay\">\n <div className=\"rt-ChatbarDropContent\">\n <Text color=\"gray\" size={size} weight=\"medium\">\n Drop files here to attach\n </Text>\n </div>\n </div>\n )}\n </Card>\n </div>\n </Comp>\n </ChatbarContext.Provider>\n );\n});\nRoot.displayName = 'Chatbar.Root';\n\n/**\n * Multi-line text input for Chatbar.\n * - Uses onChange to control value and avoid duplicate updates.\n * - Auto-resizes between minLines and maxLines.\n * - Expands on focus/overflow per `expandOn`.\n * - Paste-to-attach: when `paste` is enabled on Root, pasting files adds attachments.\n * - Provide `aria-label` or `aria-labelledby` for an accessible name.\n */\ninterface TextareaProps extends Omit<React.ComponentPropsWithoutRef<'textarea'>, 'size'> {\n asChild?: boolean;\n /**\n * Handler for paste events. This is forwarded to the underlying <textarea>.\n */\n onPaste?: React.ClipboardEventHandler<HTMLTextAreaElement>;\n /**\n * When true, pressing Enter submits via onSend (Shift+Enter inserts newline).\n * Defaults to false.\n */\n submitOnEnter?: boolean;\n}\n\n/**\n * Chatbar multi-line text input.\n *\n * Behavior\n * - Controls the Chatbar value via React onChange. We intentionally do not\n * update state in onInput to avoid duplicate updates per keystroke.\n * - Auto-resizes between minLines and maxLines using layout measurements.\n * - When expandOn is `overflow` or `both`, the Chatbar opens as soon as the\n * content exceeds the compact height.\n * - Height recalculations occur on change, paste, and whenever `value` or `open`\n * changes via an isomorphic layout effect to avoid SSR warnings.\n *\n * Accessibility\n * - Consumers should provide labeling via aria-label or aria-labelledby\n * on this component, as no implicit label is rendered.\n */\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>((props, forwardedRef) => {\n const {\n className,\n style,\n asChild,\n onFocus,\n onInput,\n onChange,\n onPaste,\n onKeyDown,\n submitOnEnter = false,\n rows,\n ...textareaProps\n } = props;\n const ctx = useChatbarContext();\n const {\n open,\n minLines,\n maxLines,\n expandOn,\n disabled,\n readOnly,\n setOpen,\n setValue,\n textareaRef,\n value,\n isValueControlled,\n sendMode,\n paste,\n appendFilesFromPaste,\n size,\n } = ctx;\n\n // Cached metrics to avoid repeated getComputedStyle calls\n const lineHeightRef = React.useRef<number>(0);\n const paddingRef = React.useRef<number>(0);\n const compactHeightRef = React.useRef<number>(0);\n\n const recomputeMetrics = React.useCallback(() => {\n const el = textareaRef.current;\n if (!el) return;\n const computedStyle = window.getComputedStyle(el);\n const lineHeight = parseFloat(computedStyle.lineHeight) || 20;\n const paddingTop = parseFloat(computedStyle.paddingTop) || 0;\n const paddingBottom = parseFloat(computedStyle.paddingBottom) || 0;\n lineHeightRef.current = lineHeight;\n paddingRef.current = paddingTop + paddingBottom;\n compactHeightRef.current = Math.ceil(1 * lineHeight) + paddingTop + paddingBottom;\n }, [textareaRef]);\n\n // Auto-resize logic - optimized for fixed widths\n const updateHeight = React.useCallback(\n (forceOpen?: boolean) => {\n const textarea = textareaRef.current;\n if (!textarea) return;\n\n textarea.style.height = 'auto';\n\n if (lineHeightRef.current === 0) {\n recomputeMetrics();\n }\n const lineHeight = lineHeightRef.current;\n const padding = paddingRef.current;\n\n const isOpen = forceOpen ?? open;\n const effectiveMinLines = isOpen ? minLines : 1;\n const effectiveMaxLines = isOpen ? maxLines : 1;\n\n const minHeight = Math.ceil(effectiveMinLines * lineHeight) + padding;\n const maxHeight = Math.ceil(effectiveMaxLines * lineHeight) + padding;\n\n const contentHeight = Math.max(textarea.scrollHeight, minHeight);\n const finalHeight = Math.min(contentHeight, maxHeight);\n\n textarea.style.height = `${finalHeight}px`;\n\n if (contentHeight > maxHeight) {\n textarea.style.overflowY = 'auto';\n textarea.style.maxHeight = `${maxHeight}px`;\n } else {\n textarea.style.overflowY = 'hidden';\n textarea.style.maxHeight = 'none';\n }\n },\n [open, minLines, maxLines, textareaRef, recomputeMetrics],\n );\n\n // Update height when value or open state changes\n useIsomorphicLayoutEffect(() => {\n updateHeight();\n }, [updateHeight, value, open]);\n\n // Recompute metrics on mount and when size changes may affect typography\n useIsomorphicLayoutEffect(() => {\n recomputeMetrics();\n updateHeight();\n }, [recomputeMetrics, updateHeight, size]);\n\n // Observe responsive changes that alter line-height\n React.useEffect(() => {\n const el = textareaRef.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n let prevLineHeight = lineHeightRef.current;\n const ro = new ResizeObserver(() => {\n const computedStyle = window.getComputedStyle(el);\n const lh = parseFloat(computedStyle.lineHeight) || 20;\n if (lh !== prevLineHeight) {\n prevLineHeight = lh;\n recomputeMetrics();\n requestAnimationFrame(() => updateHeight());\n }\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, [textareaRef, recomputeMetrics, updateHeight]);\n\n // Dev-only warning if no accessible name is provided\n React.useEffect(() => {\n if (process.env.NODE_ENV === 'production') return;\n const hasLabel =\n textareaProps['aria-label'] != null || textareaProps['aria-labelledby'] != null;\n if (!hasLabel) {\n // eslint-disable-next-line no-console\n console.warn(\n '[Chatbar.Textarea] Provide aria-label or aria-labelledby to ensure the control has an accessible name.',\n );\n }\n // warn only on mount\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Note: No MutationObserver is used because <textarea> value changes are not\n // reflected in DOM text nodes. Height updates are handled by effects and events.\n\n const handleFocus = React.useCallback<React.FocusEventHandler<HTMLTextAreaElement>>(\n (event) => {\n if (disabled || readOnly) return;\n if ((expandOn === 'focus' || expandOn === 'both') && !open) setOpen(true);\n onFocus?.(event);\n },\n [disabled, readOnly, expandOn, open, setOpen, onFocus],\n );\n\n const handleChange = React.useCallback<React.ChangeEventHandler<HTMLTextAreaElement>>(\n (event) => {\n const el = event.currentTarget;\n const nextValue = el.value;\n setValue(nextValue);\n\n if ((expandOn === 'overflow' || expandOn === 'both') && !open) {\n el.style.height = 'auto';\n\n if (compactHeightRef.current === 0) {\n recomputeMetrics();\n }\n const shouldExpand = el.scrollHeight > compactHeightRef.current + 1;\n if (shouldExpand) {\n setOpen(true);\n // Immediately size for open state to avoid 1-line + scrollbar flash\n updateHeight(true);\n requestAnimationFrame(() => updateHeight(true));\n }\n }\n\n // Always recalc after any input\n requestAnimationFrame(() => updateHeight());\n onChange?.(event);\n },\n [expandOn, open, setOpen, setValue, onChange, updateHeight, recomputeMetrics],\n );\n\n const handlePaste = React.useCallback<React.ClipboardEventHandler<HTMLTextAreaElement>>(\n (event) => {\n // Attach files from clipboard if enabled\n if (paste) {\n const items = Array.from(event.clipboardData?.items ?? []);\n const files = items\n .filter((i) => i.kind === 'file')\n .map((i) => i.getAsFile())\n .filter((f): f is File => !!f);\n if (files.length > 0) {\n appendFilesFromPaste(files);\n }\n }\n setTimeout(() => {\n // If pasting in compact mode, force sizing as open if content overflowed\n if (!open) {\n updateHeight(true);\n } else {\n updateHeight();\n }\n }, 0);\n onPaste?.(event);\n },\n [paste, open, updateHeight, onPaste, appendFilesFromPaste],\n );\n\n const handleKeyDown = React.useCallback<React.KeyboardEventHandler<HTMLTextAreaElement>>(\n (event) => {\n if (!submitOnEnter) {\n onKeyDown?.(event);\n return;\n }\n if (\n event.key === 'Enter' &&\n !event.shiftKey &&\n !event.altKey &&\n !event.ctrlKey &&\n !event.metaKey &&\n !event.nativeEvent.isComposing\n ) {\n if (disabled || readOnly) {\n onKeyDown?.(event);\n return;\n }\n if (sendMode === 'never') {\n onKeyDown?.(event);\n return;\n }\n const trimmed = value.trim();\n const hasContent = trimmed.length > 0 || ctx.attachments.length > 0;\n if (sendMode === 'whenDirty' && !hasContent) {\n onKeyDown?.(event);\n return;\n }\n event.preventDefault();\n ctx.onSubmit?.({ value, attachments: ctx.attachments });\n if (ctx.clearOnSubmit) {\n if (!isValueControlled) setValue('');\n ctx.setAttachments([]);\n }\n }\n onKeyDown?.(event);\n },\n [\n submitOnEnter,\n disabled,\n readOnly,\n sendMode,\n value,\n isValueControlled,\n setValue,\n ctx,\n onKeyDown,\n ],\n );\n\n const Comp = asChild ? Slot : ('textarea' as any);\n return (\n <div className={classNames('rt-ChatbarField', 'rt-ChatbarTextarea', className)}>\n <Comp\n {...textareaProps}\n ref={(node: HTMLTextAreaElement) => {\n if (typeof forwardedRef === 'function') forwardedRef(node);\n else if (forwardedRef)\n (forwardedRef as React.MutableRefObject<HTMLTextAreaElement | null>).current = node;\n (textareaRef as React.MutableRefObject<HTMLTextAreaElement | null>).current = node;\n }}\n className=\"rt-ChatbarInput\"\n value={value}\n onInput={onInput}\n onChange={handleChange}\n onFocus={handleFocus}\n onPaste={handlePaste}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n readOnly={readOnly}\n rows={open ? minLines : 1}\n spellCheck={textareaProps.spellCheck ?? true}\n autoCorrect={textareaProps.autoCorrect ?? 'on'}\n style={style}\n />\n </div>\n );\n});\nTextarea.displayName = 'Chatbar.Textarea';\n\ninterface InlineSlotProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'children'> {\n asChild?: boolean;\n children?: React.ReactNode;\n}\n\nconst InlineStart = React.forwardRef<HTMLDivElement, InlineSlotProps>((props, forwardedRef) => {\n const { children, asChild, style, className, ...divProps } = props;\n const ctx = useChatbarContext();\n if (ctx.open) return null;\n const Comp = asChild ? Slot : ('div' as any);\n return (\n <Comp\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarInlineStart', className)}\n style={style}\n >\n {children}\n </Comp>\n );\n});\nInlineStart.displayName = 'Chatbar.InlineStart';\n\nconst InlineEnd = React.forwardRef<HTMLDivElement, InlineSlotProps>((props, forwardedRef) => {\n const { children, asChild, style, className, ...divProps } = props;\n const ctx = useChatbarContext();\n if (ctx.open) return null;\n const Comp = asChild ? Slot : ('div' as any);\n return (\n <Comp\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarInlineEnd', className)}\n style={style}\n >\n {children}\n </Comp>\n );\n});\nInlineEnd.displayName = 'Chatbar.InlineEnd';\n\n/**\n * Renders a horizontally scrollable list of attachments above the inline row.\n * Hidden when empty unless `forceMount`. Override per-item with `renderAttachment`.\n */\ninterface AttachmentsRowProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'children'> {\n asChild?: boolean;\n forceMount?: boolean;\n /** If provided, custom-render a tile; otherwise default tile is used */\n renderAttachment?: (attachment: ChatbarAttachment) => React.ReactNode;\n}\n\nconst AttachmentsRow = React.forwardRef<HTMLDivElement, AttachmentsRowProps>(\n (props, forwardedRef) => {\n const { asChild, forceMount, renderAttachment, className, style, ...divProps } = props;\n const ctx = useChatbarContext();\n const hasItems = ctx.attachments.length > 0;\n if (!hasItems && !forceMount) return null;\n const Comp = asChild ? Slot : ('div' as any);\n return (\n <Comp\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarAttachmentsRow', className)}\n style={style}\n role=\"list\"\n aria-label={divProps['aria-label'] ?? 'Attachments'}\n >\n <ScrollArea className=\"rt-ChatbarScrollArea\" scrollbars=\"horizontal\" size=\"1\">\n <Flex align=\"center\" gap=\"2\" style={{ minWidth: 'fit-content' }}>\n {ctx.attachments.map((att) => (\n <Attachment key={att.id} attachment={att} asChild={!!renderAttachment}>\n {renderAttachment?.(att)}\n </Attachment>\n ))}\n </Flex>\n </ScrollArea>\n </Comp>\n );\n },\n);\nAttachmentsRow.displayName = 'Chatbar.AttachmentsRow';\n\n/** Default tile renderer for a single attachment. */\ninterface AttachmentProps extends React.ComponentPropsWithoutRef<'div'> {\n attachment: ChatbarAttachment;\n asChild?: boolean;\n}\n\nconst Attachment = React.forwardRef<HTMLDivElement, AttachmentProps>((props, forwardedRef) => {\n const { attachment, asChild, className, style, children, ...divProps } = props;\n const ctx = useChatbarContext();\n const Comp = asChild ? Slot : ('div' as any);\n const isImage = !!attachment.url && attachment.type.startsWith('image/');\n return (\n <Comp\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarAttachment', className)}\n style={style}\n role=\"listitem\"\n data-kind={isImage ? 'image' : 'file'}\n title={attachment.name}\n >\n {children ?? (\n <Card size={ctx.size} variant=\"soft\">\n <Flex align=\"center\" gap=\"3\" pr={!isImage ? '6' : undefined}>\n <div className=\"rt-ChatbarAttachmentPreview\" aria-hidden>\n {isImage ? (\n <img className=\"rt-ChatbarAttachmentImage\" src={attachment.url} alt=\"\" />\n ) : (\n <FileTextIcon />\n )}\n </div>\n {!isImage && (\n <Flex direction=\"column\" gap=\"0\" style={{ minWidth: 0 }}>\n <Text\n size={ctx.size}\n weight=\"medium\"\n style={{ whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}\n >\n {attachment.name}\n </Text>\n <Text size=\"1\" color=\"gray\">\n {Math.ceil(attachment.size / 1024)} KB\n </Text>\n </Flex>\n )}\n <IconButton\n className=\"rt-ChatbarAttachmentRemove\"\n aria-label={`Remove ${attachment.name}`}\n size=\"1\"\n // size={ctx.size}\n variant=\"classic\"\n highContrast\n color=\"gray\"\n onClick={() =>\n ctx.setAttachments(ctx.attachments.filter((a) => a.id !== attachment.id))\n }\n >\n <CloseIcon />\n </IconButton>\n </Flex>\n </Card>\n )}\n </Comp>\n );\n});\nAttachment.displayName = 'Chatbar.Attachment';\n\ninterface AttachTriggerProps extends React.ComponentPropsWithoutRef<'button'> {\n asChild?: boolean;\n accept?: string | string[];\n multiple?: boolean;\n}\n\nconst AttachTrigger = React.forwardRef<HTMLButtonElement, AttachTriggerProps>(\n (props, forwardedRef) => {\n const { asChild, accept, multiple, className, style, ...buttonProps } = props;\n const ctx = useChatbarContext();\n const inputRef = React.useRef<HTMLInputElement | null>(null);\n const Comp = asChild ? Slot : ('button' as any);\n const actualAccept = (Array.isArray(accept) ? accept : (accept?.split(',') ?? [])).join(',');\n return (\n <>\n <Comp\n {...(buttonProps as any)}\n ref={forwardedRef as any}\n className={classNames('rt-ChatbarAttachTrigger', className)}\n style={style}\n type={buttonProps.type ?? 'button'}\n aria-label={buttonProps['aria-label'] ?? 'Add attachments'}\n onClick={(e: any) => {\n // Ensure file input opens reliably by clicking it first\n if (inputRef.current) {\n inputRef.current.click();\n }\n // Then call user's onClick if provided\n buttonProps.onClick?.(e);\n }}\n />\n <input\n ref={inputRef}\n type=\"file\"\n accept={actualAccept}\n multiple={multiple ?? ctx.multiple}\n tabIndex={-1}\n style={{ display: 'none' }}\n onChange={(e) => {\n const files = Array.from(e.currentTarget.files ?? []);\n if (files.length > 0) {\n ctx.appendFiles(files);\n }\n // Reset input value to allow selecting the same file again\n e.currentTarget.value = '';\n }}\n />\n </>\n );\n },\n);\nAttachTrigger.displayName = 'Chatbar.AttachTrigger';\ninterface RowProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'children'> {\n asChild?: boolean;\n children?: React.ReactNode;\n}\n\nconst Row = React.forwardRef<HTMLDivElement, RowProps>((props, forwardedRef) => {\n const { asChild, children, className, style, ...divProps } = props;\n const ctx = useChatbarContext();\n if (!ctx.open) return null;\n const Comp = asChild ? Slot : ('div' as any);\n return (\n <Comp\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarRow', className)}\n style={style}\n >\n <Flex align=\"center\" justify=\"between\" width=\"100%\">\n {children}\n </Flex>\n </Comp>\n );\n});\nRow.displayName = 'Chatbar.Row';\n\nconst RowStart = React.forwardRef<HTMLDivElement, React.ComponentPropsWithoutRef<'div'>>(\n (props, forwardedRef) => {\n const { className, style, ...divProps } = props;\n return (\n <div\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarRowStart', className)}\n style={style}\n />\n );\n },\n);\nRowStart.displayName = 'Chatbar.RowStart';\n\nconst RowEnd = React.forwardRef<HTMLDivElement, React.ComponentPropsWithoutRef<'div'>>(\n (props, forwardedRef) => {\n const { className, style, ...divProps } = props;\n return (\n <div\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarRowEnd', className)}\n style={style}\n />\n );\n },\n);\nRowEnd.displayName = 'Chatbar.RowEnd';\n\ninterface SendProps extends Omit<IconButtonProps, 'size'> {\n asChild?: boolean;\n clearOnSend?: boolean;\n}\n\nconst Send = React.forwardRef<HTMLButtonElement, SendProps>((props, forwardedRef) => {\n const {\n asChild,\n clearOnSend = true,\n disabled,\n children,\n className,\n style,\n ...buttonProps\n } = props;\n const ctx = useChatbarContext();\n\n const trimmed = ctx.value.trim();\n const hasContent = trimmed.length > 0 || ctx.attachments.length > 0;\n const visible = ctx.sendMode === 'always' || (ctx.sendMode === 'whenDirty' && hasContent);\n if (ctx.sendMode === 'never') return null;\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n if (ctx.disabled || ctx.readOnly) return;\n ctx.onSubmit?.({ value: ctx.value, attachments: ctx.attachments });\n if (clearOnSend) {\n if (!ctx.isValueControlled) ctx.setValue('');\n if (ctx.clearOnSubmit) ctx.setAttachments([]);\n }\n buttonProps.onClick?.(event);\n };\n\n return (\n <IconButton\n {...(buttonProps as any)}\n ref={forwardedRef as any}\n size={ctx.size}\n variant={ctx.open ? 'solid' : 'ghost'}\n disabled={disabled || ctx.disabled || ctx.readOnly}\n className={classNames('rt-ChatbarSend', className)}\n style={{\n opacity: visible ? 1 : 0,\n pointerEvents: visible ? 'auto' : 'none',\n ...style,\n }}\n asChild={asChild}\n onClick={handleClick}\n aria-label={buttonProps['aria-label'] ?? 'Send'}\n >\n {children ?? 'Send'}\n </IconButton>\n );\n});\nSend.displayName = 'Chatbar.Send';\n\nexport {\n Root,\n Textarea,\n InlineStart,\n InlineEnd,\n AttachmentsRow,\n Attachment,\n AttachTrigger,\n Row,\n RowStart,\n RowEnd,\n Send,\n};\nexport type {\n RootProps as ChatbarRootProps,\n TextareaProps as ChatbarTextareaProps,\n RowProps as ChatbarRowProps,\n SendProps as ChatbarSendProps,\n ChatbarAttachment,\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["chatbar_exports", "__export", "AttachTrigger", "Attachment", "AttachmentsRow", "InlineEnd", "InlineStart", "Root", "Row", "RowEnd", "RowStart", "Send", "Textarea", "__toCommonJS", "React", "import_classnames", "import_icon_button", "import_icons", "import_flex", "import_scroll_area", "import_slot", "import_card", "import_text", "import_react_dropzone", "useIsomorphicLayoutEffect", "ChatbarContext", "useChatbarContext", "ctx", "props", "forwardedRef", "className", "style", "children", "valueProp", "defaultValue", "onValueChangeProp", "openProp", "defaultOpen", "onOpenChangeProp", "expandOn", "minLines", "maxLines", "sendMode", "disabled", "readOnly", "onSubmit", "size", "variant", "width", "maxWidth", "asChild", "attachmentsProp", "defaultAttachments", "onAttachmentsChange", "accept", "multiple", "maxAttachments", "maxFileSize", "paste", "pasteAccept", "clearOnSubmit", "onAttachmentReject", "dropzone", "divProps", "isValueControlled", "valueUncontrolled", "setValueUncontrolled", "value", "isOpenControlled", "openUncontrolled", "setOpenUncontrolled", "open", "rootRef", "textareaRef", "isAttachmentsControlled", "attachmentsUncontrolled", "setAttachmentsUncontrolled", "attachments", "generatedUrlSetRef", "toArray", "val", "s", "accepts", "pasteAccepts", "matchesAccept", "file", "patterns", "mime", "name", "patRaw", "pat", "type", "subtype", "fmType", "fmSubtype", "mapFilesToAttachments", "files", "next", "rejected", "remainingSlots", "id", "looksLikeImageByExt", "url", "appendFiles", "accepted", "merged", "appendFilesFromPaste", "matches", "acceptedFiles", "currentUrls", "a", "Comp", "handleBlurCapture", "event", "nextTarget", "rootEl", "getRootProps", "getInputProps", "isDragActive", "rejectedFiles", "rejections", "errors", "reason", "acc", "pattern", "node", "classNames", "onFocus", "onInput", "onChange", "onPaste", "onKeyDown", "submitOnEnter", "rows", "textareaProps", "setOpen", "setValue", "lineHeightRef", "paddingRef", "compactHeightRef", "recomputeMetrics", "el", "computedStyle", "lineHeight", "paddingTop", "paddingBottom", "updateHeight", "forceOpen", "textarea", "padding", "isOpen", "effectiveMinLines", "effectiveMaxLines", "minHeight", "maxHeight", "contentHeight", "finalHeight", "prevLineHeight", "ro", "lh", "handleFocus", "handleChange", "nextValue", "handlePaste", "i", "f", "handleKeyDown", "hasContent", "forceMount", "renderAttachment", "att", "attachment", "isImage", "buttonProps", "inputRef", "actualAccept", "e", "clearOnSend", "visible", "handleClick"]
7
7
  }
@@ -7,6 +7,7 @@ type SendMode = 'always' | 'whenDirty' | 'never';
7
7
  type AttachmentStatus = 'idle' | 'uploading' | 'error' | 'done';
8
8
  /**
9
9
  * Attachment data model used by Chatbar.
10
+ * - `file` exposes the original File object for uploads and processing.
10
11
  * - `url` is an object URL used for image previews and is revoked on removal.
11
12
  */
12
13
  interface ChatbarAttachment {
@@ -14,6 +15,8 @@ interface ChatbarAttachment {
14
15
  name: string;
15
16
  size: number;
16
17
  type: string;
18
+ /** Original File object for uploads and processing */
19
+ file: File;
17
20
  url?: string;
18
21
  status?: AttachmentStatus;
19
22
  progress?: number;
@@ -198,5 +201,5 @@ interface SendProps extends Omit<IconButtonProps, 'size'> {
198
201
  }
199
202
  declare const Send: React.ForwardRefExoticComponent<SendProps & React.RefAttributes<HTMLButtonElement>>;
200
203
  export { Root, Textarea, InlineStart, InlineEnd, AttachmentsRow, Attachment, AttachTrigger, Row, RowStart, RowEnd, Send, };
201
- export type { RootProps as ChatbarRootProps, TextareaProps as ChatbarTextareaProps, RowProps as ChatbarRowProps, SendProps as ChatbarSendProps, };
204
+ export type { RootProps as ChatbarRootProps, TextareaProps as ChatbarTextareaProps, RowProps as ChatbarRowProps, SendProps as ChatbarSendProps, ChatbarAttachment, };
202
205
  //# sourceMappingURL=chatbar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chatbar.d.ts","sourceRoot":"","sources":["../../../src/components/chatbar.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chatbar.d.ts","sourceRoot":"","sources":["../../../src/components/chatbar.tsx"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import*as e from"react";import M from"classnames";import{IconButton as ge}from"./icon-button.js";import{CloseIcon as We,FileTextIcon as Ve}from"./icons.js";import{Flex as re}from"./flex.js";import{ScrollArea as Be}from"./scroll-area.js";import{Slot as D}from"./slot.js";import{Card as ve}from"./card.js";import{Text as fe}from"./text.js";import{useDropzone as Ue}from"react-dropzone";const xe=typeof window<"u"?e.useLayoutEffect:e.useEffect,Ae=e.createContext(null),k=()=>{const l=e.useContext(Ae);if(!l)throw new Error("Chatbar context not found. Wrap parts in <Chatbar.Root>.");return l},Re=e.forwardRef((l,i)=>{const{className:s,style:c,children:d,value:u,defaultValue:y="",onValueChange:p,open:m,defaultOpen:a=!1,onOpenChange:v,expandOn:P="both",minLines:A=1,maxLines:w=6,sendMode:T="whenDirty",disabled:j,readOnly:Y,onSubmit:H,size:O="2",variant:W,width:U,maxWidth:K,asChild:N,attachments:z,defaultAttachments:ae=[],onAttachmentsChange:$,accept:G,multiple:_=!0,maxAttachments:V,maxFileSize:S,paste:oe=!0,pasteAccept:B,clearOnSubmit:L=!0,onAttachmentReject:h,dropzone:F=!0,...ie}=l,J=u!=null,[le,ce]=e.useState(y),t=J?u:le,r=m!=null,[x,g]=e.useState(a),E=r?m:x,Q=e.useRef(null),me=e.useRef(null),q=z!=null,[X,Z]=e.useState(ae),I=q?z:X,ee=e.useRef(new Set),de=n=>Array.isArray(n)?n:typeof n=="string"?n.split(",").map(o=>o.trim()):[],te=de(G),Ce=de(B).length>0?de(B):te,ue=(n,o)=>{if(o.length===0)return!0;const f=n.type.toLowerCase(),R=n.name.toLowerCase();for(const b of o){const C=b.toLowerCase();if(C.includes("/")){const[se,he]=C.split("/"),[ne,je]=f.split("/");if(se==="*"||se===ne&&(he==="*"||he===je))return!0}else if(C.startsWith(".")&&R.endsWith(C))return!0}return!1},He=n=>{const o=[],f=[],R=typeof V=="number"?Math.max(V-I.length,0):1/0;for(const b of n){if(o.length>=R){f.push({file:b,reason:"count"});continue}if(typeof S=="number"&&b.size>S){f.push({file:b,reason:"size"});continue}if(!ue(b,te)){f.push({file:b,reason:"type"});continue}const C=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,se=/\.(png|jpe?g|gif|webp|bmp|svg)$/i.test(b.name),ne=(b.type||"").toLowerCase().startsWith("image/")||se?URL.createObjectURL(b):void 0;ne&&ee.current.add(ne),o.push({id:C,name:b.name,size:b.size,type:b.type,url:ne,status:"idle"})}return{accepted:o,rejected:f}},pe=n=>{const{accepted:o,rejected:f}=He(n);if(o.length>0){const R=I.concat(o);q||Z(R),$?.(R)}f.length>0&&h?.(f)},ze=n=>{const o=C=>Ce.length===0?ue(C,te):ue(C,Ce),f=[],R=[],b=typeof V=="number"?Math.max(V-I.length,0):1/0;for(const C of n){if(f.length>=b){R.push({file:C,reason:"count"});continue}if(typeof S=="number"&&C.size>S){R.push({file:C,reason:"size"});continue}if(!o(C)){R.push({file:C,reason:"type"});continue}f.push(C)}f.length>0&&pe(f),R.length>0&&h?.(R)};e.useEffect(()=>{const n=new Set(I.map(o=>o.url).filter(Boolean));for(const o of Array.from(ee.current))n.has(o)||(URL.revokeObjectURL(o),ee.current.delete(o))},[I]),e.useEffect(()=>()=>{for(const n of Array.from(ee.current))URL.revokeObjectURL(n);ee.current.clear()},[]);const Fe=N?D:"div",Ie=e.useCallback(n=>{const o=n.relatedTarget,f=Q.current;f&&(o&&f.contains(o)||(t?.trim?.()??"").length===0&&(r||g(!1),v?.(!1)))},[r,v,t]),{getRootProps:De,getInputProps:ke,isDragActive:ye}=Ue({onDrop:(n,o)=>{if(n.length>0&&pe(n),o.length>0&&h){const f=o.map(({file:R,errors:b})=>{const C=b[0]?.code==="file-too-large"?"size":b[0]?.code==="file-invalid-type"?"type":"count";return{file:R,reason:C}});h(f)}},accept:te.length>0?te.reduce((n,o)=>(o.includes("/")?n[o]=[]:o.startsWith(".")&&(n[o]=[]),n),{}):void 0,multiple:_,maxSize:S,noClick:!0,noKeyboard:!0,disabled:!F||j});return e.createElement(Ae.Provider,{value:{open:E,setOpen:n=>{r||g(n),v?.(n)},isOpenControlled:r,value:t,setValue:n=>{J||ce(n),p?.(n)},isValueControlled:J,size:O,expandOn:P,minLines:A,maxLines:w,sendMode:T,disabled:j,readOnly:Y,onSubmit:H,rootRef:Q,textareaRef:me,attachments:I,setAttachments:n=>{q||Z(n),$?.(n)},isAttachmentsControlled:q,accept:G,multiple:_,maxAttachments:V,maxFileSize:S,paste:oe,pasteAccept:B,clearOnSubmit:L,onAttachmentReject:h,dropzone:F,appendFiles:pe,appendFilesFromPaste:ze}},e.createElement(Fe,{...ie,ref:n=>{typeof i=="function"?i(n):i&&(i.current=n),Q.current=n},className:M("rt-ChatbarRoot",`rt-r-size-${O}`,s),style:{position:"relative",width:U,maxWidth:K,...c},"data-state":E?"open":"closed","data-disabled":j?"":void 0,"data-readonly":Y?"":void 0,"data-drop-active":F&&ye?"":void 0,"aria-expanded":E,onBlurCapture:Ie},F&&e.createElement("input",{...ke()}),e.createElement("div",{...F?De():{},style:{width:"100%",height:"100%"}},e.createElement(ve,{className:"rt-ChatbarCard",size:Math.min(3,Number(O)+1).toString(),variant:W,style:{position:"relative"}},e.createElement("div",{className:"rt-ChatbarGrid"},d),F&&ye&&e.createElement("div",{className:"rt-ChatbarDropOverlay"},e.createElement("div",{className:"rt-ChatbarDropContent"},e.createElement(fe,{color:"gray",size:O,weight:"medium"},"Drop files here to attach")))))))});Re.displayName="Chatbar.Root";const Pe=e.forwardRef((l,i)=>{const{className:s,style:c,asChild:d,onFocus:u,onInput:y,onChange:p,onPaste:m,onKeyDown:a,submitOnEnter:v=!1,rows:P,...A}=l,w=k(),{open:T,minLines:j,maxLines:Y,expandOn:H,disabled:O,readOnly:W,setOpen:U,setValue:K,textareaRef:N,value:z,isValueControlled:ae,sendMode:$,paste:G,appendFilesFromPaste:_,size:V}=w,S=e.useRef(0),oe=e.useRef(0),B=e.useRef(0),L=e.useCallback(()=>{const t=N.current;if(!t)return;const r=window.getComputedStyle(t),x=parseFloat(r.lineHeight)||20,g=parseFloat(r.paddingTop)||0,E=parseFloat(r.paddingBottom)||0;S.current=x,oe.current=g+E,B.current=Math.ceil(1*x)+g+E},[N]),h=e.useCallback(t=>{const r=N.current;if(!r)return;r.style.height="auto",S.current===0&&L();const x=S.current,g=oe.current,E=t??T,Q=E?j:1,me=E?Y:1,q=Math.ceil(Q*x)+g,X=Math.ceil(me*x)+g,Z=Math.max(r.scrollHeight,q),I=Math.min(Z,X);r.style.height=`${I}px`,Z>X?(r.style.overflowY="auto",r.style.maxHeight=`${X}px`):(r.style.overflowY="hidden",r.style.maxHeight="none")},[T,j,Y,N,L]);xe(()=>{h()},[h,z,T]),xe(()=>{L(),h()},[L,h,V]),e.useEffect(()=>{const t=N.current;if(!t||typeof ResizeObserver>"u")return;let r=S.current;const x=new ResizeObserver(()=>{const g=window.getComputedStyle(t),E=parseFloat(g.lineHeight)||20;E!==r&&(r=E,L(),requestAnimationFrame(()=>h()))});return x.observe(t),()=>x.disconnect()},[N,L,h]),e.useEffect(()=>{},[]);const F=e.useCallback(t=>{O||W||((H==="focus"||H==="both")&&!T&&U(!0),u?.(t))},[O,W,H,T,U,u]),ie=e.useCallback(t=>{const r=t.currentTarget,x=r.value;K(x),(H==="overflow"||H==="both")&&!T&&(r.style.height="auto",B.current===0&&L(),r.scrollHeight>B.current+1&&(U(!0),h(!0),requestAnimationFrame(()=>h(!0)))),requestAnimationFrame(()=>h()),p?.(t)},[H,T,U,K,p,h,L]),J=e.useCallback(t=>{if(G){const x=Array.from(t.clipboardData?.items??[]).filter(g=>g.kind==="file").map(g=>g.getAsFile()).filter(g=>!!g);x.length>0&&_(x)}setTimeout(()=>{T?h():h(!0)},0),m?.(t)},[G,T,h,m,_]),le=e.useCallback(t=>{if(!v){a?.(t);return}if(t.key==="Enter"&&!t.shiftKey&&!t.altKey&&!t.ctrlKey&&!t.metaKey&&!t.nativeEvent.isComposing){if(O||W){a?.(t);return}if($==="never"){a?.(t);return}const r=z.trim();if($==="whenDirty"&&r.length===0){a?.(t);return}t.preventDefault(),w.onSubmit?.({value:z,attachments:w.attachments}),w.clearOnSubmit&&(ae||K(""),w.setAttachments([]))}a?.(t)},[v,O,W,$,z,ae,K,w,a]),ce=d?D:"textarea";return e.createElement("div",{className:M("rt-ChatbarField","rt-ChatbarTextarea",s)},e.createElement(ce,{...A,ref:t=>{typeof i=="function"?i(t):i&&(i.current=t),N.current=t},className:"rt-ChatbarInput",value:z,onInput:y,onChange:ie,onFocus:F,onPaste:J,onKeyDown:le,disabled:O,readOnly:W,rows:T?j:1,spellCheck:A.spellCheck??!0,autoCorrect:A.autoCorrect??"on",style:c}))});Pe.displayName="Chatbar.Textarea";const we=e.forwardRef((l,i)=>{const{children:s,asChild:c,style:d,className:u,...y}=l;return k().open?null:e.createElement(c?D:"div",{...y,ref:i,className:M("rt-ChatbarInlineStart",u),style:d},s)});we.displayName="Chatbar.InlineStart";const Te=e.forwardRef((l,i)=>{const{children:s,asChild:c,style:d,className:u,...y}=l;return k().open?null:e.createElement(c?D:"div",{...y,ref:i,className:M("rt-ChatbarInlineEnd",u),style:d},s)});Te.displayName="Chatbar.InlineEnd";const Ee=e.forwardRef((l,i)=>{const{asChild:s,forceMount:c,renderAttachment:d,className:u,style:y,...p}=l,m=k();return!(m.attachments.length>0)&&!c?null:e.createElement(s?D:"div",{...p,ref:i,className:M("rt-ChatbarAttachmentsRow",u),style:y,role:"list","aria-label":p["aria-label"]??"Attachments"},e.createElement(Be,{className:"rt-ChatbarScrollArea",scrollbars:"horizontal",size:"1"},e.createElement(re,{align:"center",gap:"2",style:{minWidth:"fit-content"}},m.attachments.map(P=>e.createElement(be,{key:P.id,attachment:P,asChild:!!d},d?.(P))))))});Ee.displayName="Chatbar.AttachmentsRow";const be=e.forwardRef((l,i)=>{const{attachment:s,asChild:c,className:d,style:u,children:y,...p}=l,m=k(),a=c?D:"div",v=!!s.url&&s.type.startsWith("image/");return e.createElement(a,{...p,ref:i,className:M("rt-ChatbarAttachment",d),style:u,role:"listitem","data-kind":v?"image":"file",title:s.name},y??e.createElement(ve,{size:m.size,variant:"soft"},e.createElement(re,{align:"center",gap:"3",pr:v?void 0:"6"},e.createElement("div",{className:"rt-ChatbarAttachmentPreview","aria-hidden":!0},v?e.createElement("img",{className:"rt-ChatbarAttachmentImage",src:s.url,alt:""}):e.createElement(Ve,null)),!v&&e.createElement(re,{direction:"column",gap:"0",style:{minWidth:0}},e.createElement(fe,{size:m.size,weight:"medium",style:{whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"}},s.name),e.createElement(fe,{size:"1",color:"gray"},Math.ceil(s.size/1024)," KB")),e.createElement(ge,{className:"rt-ChatbarAttachmentRemove","aria-label":`Remove ${s.name}`,size:"1",variant:"classic",highContrast:!0,color:"gray",onClick:()=>m.setAttachments(m.attachments.filter(P=>P.id!==s.id))},e.createElement(We,null)))))});be.displayName="Chatbar.Attachment";const Se=e.forwardRef((l,i)=>{const{asChild:s,accept:c,multiple:d,className:u,style:y,...p}=l,m=k(),a=e.useRef(null),v=s?D:"button",P=(Array.isArray(c)?c:c?.split(",")??[]).join(",");return e.createElement(e.Fragment,null,e.createElement(v,{...p,ref:i,className:M("rt-ChatbarAttachTrigger",u),style:y,type:p.type??"button","aria-label":p["aria-label"]??"Add attachments",onClick:A=>{a.current&&a.current.click(),p.onClick?.(A)}}),e.createElement("input",{ref:a,type:"file",accept:P,multiple:d??m.multiple,tabIndex:-1,style:{display:"none"},onChange:A=>{const w=Array.from(A.currentTarget.files??[]);w.length>0&&m.appendFiles(w),A.currentTarget.value=""}}))});Se.displayName="Chatbar.AttachTrigger";const Me=e.forwardRef((l,i)=>{const{asChild:s,children:c,className:d,style:u,...y}=l;return k().open?e.createElement(s?D:"div",{...y,ref:i,className:M("rt-ChatbarRow",d),style:u},e.createElement(re,{align:"center",justify:"between",width:"100%"},c)):null});Me.displayName="Chatbar.Row";const Oe=e.forwardRef((l,i)=>{const{className:s,style:c,...d}=l;return e.createElement("div",{...d,ref:i,className:M("rt-ChatbarRowStart",s),style:c})});Oe.displayName="Chatbar.RowStart";const Le=e.forwardRef((l,i)=>{const{className:s,style:c,...d}=l;return e.createElement("div",{...d,ref:i,className:M("rt-ChatbarRowEnd",s),style:c})});Le.displayName="Chatbar.RowEnd";const Ne=e.forwardRef((l,i)=>{const{asChild:s,clearOnSend:c=!0,disabled:d,children:u,className:y,style:p,...m}=l,a=k(),v=a.value.trim(),P=a.sendMode==="always"||a.sendMode==="whenDirty"&&v.length>0;if(a.sendMode==="never")return null;const A=w=>{a.disabled||a.readOnly||(a.onSubmit?.({value:a.value,attachments:a.attachments}),c&&(a.isValueControlled||a.setValue(""),a.clearOnSubmit&&a.setAttachments([])),m.onClick?.(w))};return e.createElement(ge,{...m,ref:i,size:a.size,variant:a.open?"solid":"ghost",disabled:d||a.disabled||a.readOnly,className:M("rt-ChatbarSend",y),style:{opacity:P?1:0,pointerEvents:P?"auto":"none",...p},asChild:s,onClick:A,"aria-label":m["aria-label"]??"Send"},u??"Send")});Ne.displayName="Chatbar.Send";export{Se as AttachTrigger,be as Attachment,Ee as AttachmentsRow,Te as InlineEnd,we as InlineStart,Re as Root,Me as Row,Le as RowEnd,Oe as RowStart,Ne as Send,Pe as Textarea};
1
+ import*as e from"react";import M from"classnames";import{IconButton as ge}from"./icon-button.js";import{CloseIcon as We,FileTextIcon as Ve}from"./icons.js";import{Flex as re}from"./flex.js";import{ScrollArea as Be}from"./scroll-area.js";import{Slot as D}from"./slot.js";import{Card as ve}from"./card.js";import{Text as fe}from"./text.js";import{useDropzone as Ue}from"react-dropzone";const xe=typeof window<"u"?e.useLayoutEffect:e.useEffect,Ae=e.createContext(null),k=()=>{const l=e.useContext(Ae);if(!l)throw new Error("Chatbar context not found. Wrap parts in <Chatbar.Root>.");return l},Re=e.forwardRef((l,r)=>{const{className:s,style:c,children:d,value:u,defaultValue:y="",onValueChange:p,open:m,defaultOpen:a=!1,onOpenChange:x,expandOn:T="both",minLines:A=1,maxLines:R=6,sendMode:P="whenDirty",disabled:j,readOnly:Y,onSubmit:H,size:O="2",variant:W,width:U,maxWidth:K,asChild:N,attachments:F,defaultAttachments:ae=[],onAttachmentsChange:$,accept:G,multiple:_=!0,maxAttachments:V,maxFileSize:S,paste:oe=!0,pasteAccept:B,clearOnSubmit:L=!0,onAttachmentReject:h,dropzone:z=!0,...ie}=l,J=u!=null,[le,ce]=e.useState(y),t=J?u:le,i=m!=null,[g,v]=e.useState(a),E=i?m:g,Q=e.useRef(null),me=e.useRef(null),q=F!=null,[X,Z]=e.useState(ae),I=q?F:X,ee=e.useRef(new Set),de=n=>Array.isArray(n)?n:typeof n=="string"?n.split(",").map(o=>o.trim()):[],te=de(G),Ce=de(B).length>0?de(B):te,ue=(n,o)=>{if(o.length===0)return!0;const f=n.type.toLowerCase(),w=n.name.toLowerCase();for(const b of o){const C=b.toLowerCase();if(C.includes("/")){const[se,he]=C.split("/"),[ne,je]=f.split("/");if(se==="*"||se===ne&&(he==="*"||he===je))return!0}else if(C.startsWith(".")&&w.endsWith(C))return!0}return!1},He=n=>{const o=[],f=[],w=typeof V=="number"?Math.max(V-I.length,0):1/0;for(const b of n){if(o.length>=w){f.push({file:b,reason:"count"});continue}if(typeof S=="number"&&b.size>S){f.push({file:b,reason:"size"});continue}if(!ue(b,te)){f.push({file:b,reason:"type"});continue}const C=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,se=/\.(png|jpe?g|gif|webp|bmp|svg)$/i.test(b.name),ne=(b.type||"").toLowerCase().startsWith("image/")||se?URL.createObjectURL(b):void 0;ne&&ee.current.add(ne),o.push({id:C,name:b.name,size:b.size,type:b.type,file:b,url:ne,status:"idle"})}return{accepted:o,rejected:f}},pe=n=>{const{accepted:o,rejected:f}=He(n);if(o.length>0){const w=I.concat(o);q||Z(w),$?.(w)}f.length>0&&h?.(f)},Fe=n=>{const o=C=>Ce.length===0?ue(C,te):ue(C,Ce),f=[],w=[],b=typeof V=="number"?Math.max(V-I.length,0):1/0;for(const C of n){if(f.length>=b){w.push({file:C,reason:"count"});continue}if(typeof S=="number"&&C.size>S){w.push({file:C,reason:"size"});continue}if(!o(C)){w.push({file:C,reason:"type"});continue}f.push(C)}f.length>0&&pe(f),w.length>0&&h?.(w)};e.useEffect(()=>{const n=new Set(I.map(o=>o.url).filter(Boolean));for(const o of Array.from(ee.current))n.has(o)||(URL.revokeObjectURL(o),ee.current.delete(o))},[I]),e.useEffect(()=>()=>{for(const n of Array.from(ee.current))URL.revokeObjectURL(n);ee.current.clear()},[]);const ze=N?D:"div",Ie=e.useCallback(n=>{const o=n.relatedTarget,f=Q.current;f&&(o&&f.contains(o)||(t?.trim?.()??"").length===0&&(i||v(!1),x?.(!1)))},[i,x,t]),{getRootProps:De,getInputProps:ke,isDragActive:ye}=Ue({onDrop:(n,o)=>{if(n.length>0&&pe(n),o.length>0&&h){const f=o.map(({file:w,errors:b})=>{const C=b[0]?.code==="file-too-large"?"size":b[0]?.code==="file-invalid-type"?"type":"count";return{file:w,reason:C}});h(f)}},accept:te.length>0?te.reduce((n,o)=>(o.includes("/")?n[o]=[]:o.startsWith(".")&&(n[o]=[]),n),{}):void 0,multiple:_,maxSize:S,noClick:!0,noKeyboard:!0,disabled:!z||j});return e.createElement(Ae.Provider,{value:{open:E,setOpen:n=>{i||v(n),x?.(n)},isOpenControlled:i,value:t,setValue:n=>{J||ce(n),p?.(n)},isValueControlled:J,size:O,expandOn:T,minLines:A,maxLines:R,sendMode:P,disabled:j,readOnly:Y,onSubmit:H,rootRef:Q,textareaRef:me,attachments:I,setAttachments:n=>{q||Z(n),$?.(n)},isAttachmentsControlled:q,accept:G,multiple:_,maxAttachments:V,maxFileSize:S,paste:oe,pasteAccept:B,clearOnSubmit:L,onAttachmentReject:h,dropzone:z,appendFiles:pe,appendFilesFromPaste:Fe}},e.createElement(ze,{...ie,ref:n=>{typeof r=="function"?r(n):r&&(r.current=n),Q.current=n},className:M("rt-ChatbarRoot",`rt-r-size-${O}`,s),style:{position:"relative",width:U,maxWidth:K,...c},"data-state":E?"open":"closed","data-disabled":j?"":void 0,"data-readonly":Y?"":void 0,"data-drop-active":z&&ye?"":void 0,"aria-expanded":E,onBlurCapture:Ie},z&&e.createElement("input",{...ke()}),e.createElement("div",{...z?De():{},style:{width:"100%",height:"100%"}},e.createElement(ve,{className:"rt-ChatbarCard",size:Math.min(3,Number(O)+1).toString(),variant:W,style:{position:"relative"}},e.createElement("div",{className:"rt-ChatbarGrid"},d),z&&ye&&e.createElement("div",{className:"rt-ChatbarDropOverlay"},e.createElement("div",{className:"rt-ChatbarDropContent"},e.createElement(fe,{color:"gray",size:O,weight:"medium"},"Drop files here to attach")))))))});Re.displayName="Chatbar.Root";const Pe=e.forwardRef((l,r)=>{const{className:s,style:c,asChild:d,onFocus:u,onInput:y,onChange:p,onPaste:m,onKeyDown:a,submitOnEnter:x=!1,rows:T,...A}=l,R=k(),{open:P,minLines:j,maxLines:Y,expandOn:H,disabled:O,readOnly:W,setOpen:U,setValue:K,textareaRef:N,value:F,isValueControlled:ae,sendMode:$,paste:G,appendFilesFromPaste:_,size:V}=R,S=e.useRef(0),oe=e.useRef(0),B=e.useRef(0),L=e.useCallback(()=>{const t=N.current;if(!t)return;const i=window.getComputedStyle(t),g=parseFloat(i.lineHeight)||20,v=parseFloat(i.paddingTop)||0,E=parseFloat(i.paddingBottom)||0;S.current=g,oe.current=v+E,B.current=Math.ceil(1*g)+v+E},[N]),h=e.useCallback(t=>{const i=N.current;if(!i)return;i.style.height="auto",S.current===0&&L();const g=S.current,v=oe.current,E=t??P,Q=E?j:1,me=E?Y:1,q=Math.ceil(Q*g)+v,X=Math.ceil(me*g)+v,Z=Math.max(i.scrollHeight,q),I=Math.min(Z,X);i.style.height=`${I}px`,Z>X?(i.style.overflowY="auto",i.style.maxHeight=`${X}px`):(i.style.overflowY="hidden",i.style.maxHeight="none")},[P,j,Y,N,L]);xe(()=>{h()},[h,F,P]),xe(()=>{L(),h()},[L,h,V]),e.useEffect(()=>{const t=N.current;if(!t||typeof ResizeObserver>"u")return;let i=S.current;const g=new ResizeObserver(()=>{const v=window.getComputedStyle(t),E=parseFloat(v.lineHeight)||20;E!==i&&(i=E,L(),requestAnimationFrame(()=>h()))});return g.observe(t),()=>g.disconnect()},[N,L,h]),e.useEffect(()=>{},[]);const z=e.useCallback(t=>{O||W||((H==="focus"||H==="both")&&!P&&U(!0),u?.(t))},[O,W,H,P,U,u]),ie=e.useCallback(t=>{const i=t.currentTarget,g=i.value;K(g),(H==="overflow"||H==="both")&&!P&&(i.style.height="auto",B.current===0&&L(),i.scrollHeight>B.current+1&&(U(!0),h(!0),requestAnimationFrame(()=>h(!0)))),requestAnimationFrame(()=>h()),p?.(t)},[H,P,U,K,p,h,L]),J=e.useCallback(t=>{if(G){const g=Array.from(t.clipboardData?.items??[]).filter(v=>v.kind==="file").map(v=>v.getAsFile()).filter(v=>!!v);g.length>0&&_(g)}setTimeout(()=>{P?h():h(!0)},0),m?.(t)},[G,P,h,m,_]),le=e.useCallback(t=>{if(!x){a?.(t);return}if(t.key==="Enter"&&!t.shiftKey&&!t.altKey&&!t.ctrlKey&&!t.metaKey&&!t.nativeEvent.isComposing){if(O||W){a?.(t);return}if($==="never"){a?.(t);return}const g=F.trim().length>0||R.attachments.length>0;if($==="whenDirty"&&!g){a?.(t);return}t.preventDefault(),R.onSubmit?.({value:F,attachments:R.attachments}),R.clearOnSubmit&&(ae||K(""),R.setAttachments([]))}a?.(t)},[x,O,W,$,F,ae,K,R,a]),ce=d?D:"textarea";return e.createElement("div",{className:M("rt-ChatbarField","rt-ChatbarTextarea",s)},e.createElement(ce,{...A,ref:t=>{typeof r=="function"?r(t):r&&(r.current=t),N.current=t},className:"rt-ChatbarInput",value:F,onInput:y,onChange:ie,onFocus:z,onPaste:J,onKeyDown:le,disabled:O,readOnly:W,rows:P?j:1,spellCheck:A.spellCheck??!0,autoCorrect:A.autoCorrect??"on",style:c}))});Pe.displayName="Chatbar.Textarea";const we=e.forwardRef((l,r)=>{const{children:s,asChild:c,style:d,className:u,...y}=l;return k().open?null:e.createElement(c?D:"div",{...y,ref:r,className:M("rt-ChatbarInlineStart",u),style:d},s)});we.displayName="Chatbar.InlineStart";const Te=e.forwardRef((l,r)=>{const{children:s,asChild:c,style:d,className:u,...y}=l;return k().open?null:e.createElement(c?D:"div",{...y,ref:r,className:M("rt-ChatbarInlineEnd",u),style:d},s)});Te.displayName="Chatbar.InlineEnd";const Ee=e.forwardRef((l,r)=>{const{asChild:s,forceMount:c,renderAttachment:d,className:u,style:y,...p}=l,m=k();return!(m.attachments.length>0)&&!c?null:e.createElement(s?D:"div",{...p,ref:r,className:M("rt-ChatbarAttachmentsRow",u),style:y,role:"list","aria-label":p["aria-label"]??"Attachments"},e.createElement(Be,{className:"rt-ChatbarScrollArea",scrollbars:"horizontal",size:"1"},e.createElement(re,{align:"center",gap:"2",style:{minWidth:"fit-content"}},m.attachments.map(T=>e.createElement(be,{key:T.id,attachment:T,asChild:!!d},d?.(T))))))});Ee.displayName="Chatbar.AttachmentsRow";const be=e.forwardRef((l,r)=>{const{attachment:s,asChild:c,className:d,style:u,children:y,...p}=l,m=k(),a=c?D:"div",x=!!s.url&&s.type.startsWith("image/");return e.createElement(a,{...p,ref:r,className:M("rt-ChatbarAttachment",d),style:u,role:"listitem","data-kind":x?"image":"file",title:s.name},y??e.createElement(ve,{size:m.size,variant:"soft"},e.createElement(re,{align:"center",gap:"3",pr:x?void 0:"6"},e.createElement("div",{className:"rt-ChatbarAttachmentPreview","aria-hidden":!0},x?e.createElement("img",{className:"rt-ChatbarAttachmentImage",src:s.url,alt:""}):e.createElement(Ve,null)),!x&&e.createElement(re,{direction:"column",gap:"0",style:{minWidth:0}},e.createElement(fe,{size:m.size,weight:"medium",style:{whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"}},s.name),e.createElement(fe,{size:"1",color:"gray"},Math.ceil(s.size/1024)," KB")),e.createElement(ge,{className:"rt-ChatbarAttachmentRemove","aria-label":`Remove ${s.name}`,size:"1",variant:"classic",highContrast:!0,color:"gray",onClick:()=>m.setAttachments(m.attachments.filter(T=>T.id!==s.id))},e.createElement(We,null)))))});be.displayName="Chatbar.Attachment";const Se=e.forwardRef((l,r)=>{const{asChild:s,accept:c,multiple:d,className:u,style:y,...p}=l,m=k(),a=e.useRef(null),x=s?D:"button",T=(Array.isArray(c)?c:c?.split(",")??[]).join(",");return e.createElement(e.Fragment,null,e.createElement(x,{...p,ref:r,className:M("rt-ChatbarAttachTrigger",u),style:y,type:p.type??"button","aria-label":p["aria-label"]??"Add attachments",onClick:A=>{a.current&&a.current.click(),p.onClick?.(A)}}),e.createElement("input",{ref:a,type:"file",accept:T,multiple:d??m.multiple,tabIndex:-1,style:{display:"none"},onChange:A=>{const R=Array.from(A.currentTarget.files??[]);R.length>0&&m.appendFiles(R),A.currentTarget.value=""}}))});Se.displayName="Chatbar.AttachTrigger";const Me=e.forwardRef((l,r)=>{const{asChild:s,children:c,className:d,style:u,...y}=l;return k().open?e.createElement(s?D:"div",{...y,ref:r,className:M("rt-ChatbarRow",d),style:u},e.createElement(re,{align:"center",justify:"between",width:"100%"},c)):null});Me.displayName="Chatbar.Row";const Oe=e.forwardRef((l,r)=>{const{className:s,style:c,...d}=l;return e.createElement("div",{...d,ref:r,className:M("rt-ChatbarRowStart",s),style:c})});Oe.displayName="Chatbar.RowStart";const Le=e.forwardRef((l,r)=>{const{className:s,style:c,...d}=l;return e.createElement("div",{...d,ref:r,className:M("rt-ChatbarRowEnd",s),style:c})});Le.displayName="Chatbar.RowEnd";const Ne=e.forwardRef((l,r)=>{const{asChild:s,clearOnSend:c=!0,disabled:d,children:u,className:y,style:p,...m}=l,a=k(),T=a.value.trim().length>0||a.attachments.length>0,A=a.sendMode==="always"||a.sendMode==="whenDirty"&&T;if(a.sendMode==="never")return null;const R=P=>{a.disabled||a.readOnly||(a.onSubmit?.({value:a.value,attachments:a.attachments}),c&&(a.isValueControlled||a.setValue(""),a.clearOnSubmit&&a.setAttachments([])),m.onClick?.(P))};return e.createElement(ge,{...m,ref:r,size:a.size,variant:a.open?"solid":"ghost",disabled:d||a.disabled||a.readOnly,className:M("rt-ChatbarSend",y),style:{opacity:A?1:0,pointerEvents:A?"auto":"none",...p},asChild:s,onClick:R,"aria-label":m["aria-label"]??"Send"},u??"Send")});Ne.displayName="Chatbar.Send";export{Se as AttachTrigger,be as Attachment,Ee as AttachmentsRow,Te as InlineEnd,we as InlineStart,Re as Root,Me as Row,Le as RowEnd,Oe as RowStart,Ne as Send,Pe as Textarea};
2
2
  //# sourceMappingURL=chatbar.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/chatbar.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nimport classNames from 'classnames';\n\nimport { IconButton, type IconButtonProps } from './icon-button.js';\nimport { CloseIcon, FileTextIcon } from './icons.js';\nimport { Flex } from './flex.js';\n\nimport { ScrollArea } from './scroll-area.js';\nimport { Slot } from './slot.js';\nimport { Card } from './card.js';\nimport { Text } from './text.js';\nimport { useDropzone } from 'react-dropzone';\nimport type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js';\n\n// Avoid SSR warnings by using an isomorphic layout effect\nconst useIsomorphicLayoutEffect =\n typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;\n\ntype ExpandOn = 'none' | 'focus' | 'overflow' | 'both';\ntype SendMode = 'always' | 'whenDirty' | 'never';\n\n// Attachments\n/** Status flag for attachment lifecycle. */\ntype AttachmentStatus = 'idle' | 'uploading' | 'error' | 'done';\n/**\n * Attachment data model used by Chatbar.\n * - `url` is an object URL used for image previews and is revoked on removal.\n */\ninterface ChatbarAttachment {\n id: string;\n name: string;\n size: number;\n type: string;\n url?: string;\n status?: AttachmentStatus;\n progress?: number;\n meta?: Record<string, unknown>;\n}\n\ninterface ChatbarContextValue {\n open: boolean;\n setOpen(next: boolean): void;\n isOpenControlled: boolean;\n\n value: string;\n setValue(next: string): void;\n isValueControlled: boolean;\n\n size: '1' | '2' | '3';\n expandOn: ExpandOn;\n minLines: number;\n maxLines: number;\n sendMode: SendMode;\n disabled?: boolean;\n readOnly?: boolean;\n\n // Submit returns both message and attachments\n onSubmit?: (payload: { value: string; attachments: ChatbarAttachment[] }) => void;\n\n rootRef: React.RefObject<HTMLDivElement | null>;\n textareaRef: React.RefObject<HTMLTextAreaElement | null>;\n\n // Attachments state\n attachments: ChatbarAttachment[];\n setAttachments(next: ChatbarAttachment[]): void;\n isAttachmentsControlled: boolean;\n\n // Config\n accept?: string | string[];\n multiple: boolean;\n maxAttachments?: number;\n maxFileSize?: number;\n paste: boolean;\n pasteAccept?: string | string[];\n clearOnSubmit: boolean;\n\n // Dropzone\n dropzone: boolean;\n\n // Events\n onAttachmentReject?: (rejections: { file: File; reason: 'type' | 'size' | 'count' }[]) => void;\n\n // Helpers\n appendFiles(files: File[]): void;\n appendFilesFromPaste(files: File[]): void;\n}\n\nconst ChatbarContext = React.createContext<ChatbarContextValue | null>(null);\nconst useChatbarContext = () => {\n const ctx = React.useContext(ChatbarContext);\n if (!ctx) throw new Error('Chatbar context not found. Wrap parts in <Chatbar.Root>.');\n return ctx;\n};\n\n/**\n * Chatbar container and state provider.\n *\n * Value & Open\n * - Supports controlled/uncontrolled `value` and `open`.\n *\n * Attachments\n * - Controlled/uncontrolled attachments with client-side filtering.\n * - Filters by `accept`/`pasteAccept`, `maxAttachments`, and `maxFileSize`.\n * - Rejections are reported via `onAttachmentReject`.\n *\n * Submit\n * - `onSubmit({ value, attachments })` emits both message and attachments.\n * - `clearOnSubmit` clears message and attachments by default.\n */\ninterface ChatbarRootBaseProps {\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n\n expandOn?: ExpandOn;\n\n /** Minimum number of lines in compact state (default: 1) */\n minLines?: number;\n /** Maximum number of lines before scrolling (default: 6) */\n maxLines?: number;\n\n sendMode?: SendMode;\n\n disabled?: boolean;\n readOnly?: boolean;\n\n /** Combined submit payload */\n onSubmit?: (payload: { value: string; attachments: ChatbarAttachment[] }) => void;\n\n size?: '1' | '2' | '3';\n variant?: 'surface' | 'outline' | 'classic' | 'ghost' | 'soft';\n\n width?: React.CSSProperties['width'];\n maxWidth?: React.CSSProperties['maxWidth'];\n asChild?: boolean;\n\n // Attachments API\n attachments?: ChatbarAttachment[];\n defaultAttachments?: ChatbarAttachment[];\n onAttachmentsChange?: (attachments: ChatbarAttachment[]) => void;\n accept?: string | string[];\n multiple?: boolean;\n maxAttachments?: number;\n maxFileSize?: number;\n paste?: boolean;\n pasteAccept?: string | string[];\n clearOnSubmit?: boolean;\n onAttachmentReject?: (rejections: { file: File; reason: 'type' | 'size' | 'count' }[]) => void;\n\n /**\n * Enables drag-and-drop file uploads when true.\n *\n * When enabled:\n * - Files can be dropped anywhere on the chatbar\n * - Same validation rules apply (accept, maxFileSize, maxAttachments)\n * - Visual feedback shows during drag operations\n * - Rejected files trigger onAttachmentReject\n *\n * @default true\n */\n dropzone?: boolean;\n}\n\ntype RootElement = React.ElementRef<'div'>;\n/**\n * Chatbar container and state provider.\n *\n * Behavior\n * - Supports controlled and uncontrolled `value` and `open` states via props.\n * - Provides context to subcomponents like `Textarea`, `Row`, and `Send`.\n * - Exposes `data-state`, `data-disabled`, and `data-readonly` attributes for styling.\n * - Sets `aria-expanded` to reflect open/closed state for assistive technologies.\n *\n * Attachments\n * - Controlled/uncontrolled attachments with client-side filtering.\n * - Filters by `accept`/`pasteAccept`, `maxAttachments`, and `maxFileSize`.\n * - Rejections are reported via `onAttachmentReject`.\n * - Paste-to-attach: when `paste` is enabled, pasting files adds attachments.\n *\n * Dropzone\n * - When `dropzone` is true, enables drag-and-drop file uploads.\n * - Files are validated using the same rules as paste and file picker.\n * - Visual feedback via `data-drop-active` attribute during drag operations.\n * - Rejected files trigger `onAttachmentReject` with appropriate reasons.\n *\n * Submit\n * - `onSubmit` receives both message text and attachments array.\n * - `clearOnSubmit` controls whether attachments are cleared after submission.\n *\n * Accessibility\n * - Consumers should label the `Textarea` via `aria-label`/`aria-labelledby`.\n * - `aria-expanded` on the root reflects the disclosure state of the input area.\n * - Dropzone provides proper ARIA attributes for drag and drop operations.\n */\ninterface RootProps\n extends ComponentPropsWithout<'div', RemovedProps | 'onSubmit'>,\n ChatbarRootBaseProps {}\n\nconst Root = React.forwardRef<RootElement, RootProps>((props, forwardedRef) => {\n const {\n className,\n style,\n children,\n value: valueProp,\n defaultValue = '',\n onValueChange: onValueChangeProp,\n open: openProp,\n defaultOpen = false,\n onOpenChange: onOpenChangeProp,\n expandOn = 'both',\n minLines = 1,\n maxLines = 6,\n sendMode = 'whenDirty',\n disabled,\n readOnly,\n onSubmit,\n size = '2',\n variant,\n width,\n maxWidth,\n asChild,\n attachments: attachmentsProp,\n defaultAttachments = [],\n onAttachmentsChange,\n accept,\n multiple = true,\n maxAttachments,\n maxFileSize,\n paste = true,\n pasteAccept,\n clearOnSubmit = true,\n onAttachmentReject,\n dropzone = true,\n ...divProps\n } = props;\n\n const isValueControlled = valueProp != null;\n const [valueUncontrolled, setValueUncontrolled] = React.useState<string>(defaultValue);\n const value = isValueControlled ? (valueProp as string) : valueUncontrolled;\n\n const isOpenControlled = openProp != null;\n const [openUncontrolled, setOpenUncontrolled] = React.useState<boolean>(defaultOpen);\n const open = isOpenControlled ? (openProp as boolean) : openUncontrolled;\n\n const rootRef = React.useRef<HTMLDivElement>(null);\n const textareaRef = React.useRef<HTMLTextAreaElement>(null);\n\n // Attachments state\n const isAttachmentsControlled = attachmentsProp != null;\n const [attachmentsUncontrolled, setAttachmentsUncontrolled] =\n React.useState<ChatbarAttachment[]>(defaultAttachments);\n const attachments = isAttachmentsControlled\n ? (attachmentsProp as ChatbarAttachment[])\n : attachmentsUncontrolled;\n\n // Track generated object URLs for cleanup\n const generatedUrlSetRef = React.useRef<Set<string>>(new Set());\n\n const toArray = (val: string | string[] | undefined) =>\n Array.isArray(val) ? val : typeof val === 'string' ? val.split(',').map((s) => s.trim()) : [];\n\n const accepts = toArray(accept);\n const pasteAccepts = toArray(pasteAccept).length > 0 ? toArray(pasteAccept) : accepts;\n\n const matchesAccept = (file: File, patterns: string[]) => {\n if (patterns.length === 0) return true;\n const mime = file.type.toLowerCase();\n const name = file.name.toLowerCase();\n for (const patRaw of patterns) {\n const pat = patRaw.toLowerCase();\n if (pat.includes('/')) {\n // MIME pattern\n const [type, subtype] = pat.split('/');\n const [fmType, fmSubtype] = mime.split('/');\n if (type === '*' || (type === fmType && (subtype === '*' || subtype === fmSubtype)))\n return true;\n } else if (pat.startsWith('.')) {\n if (name.endsWith(pat)) return true;\n }\n }\n return false;\n };\n\n /**\n * Maps File objects to attachments with validation and preview URL generation.\n */\n const mapFilesToAttachments = (\n files: File[],\n ): {\n accepted: ChatbarAttachment[];\n rejected: { file: File; reason: 'type' | 'size' | 'count' }[];\n } => {\n const next: ChatbarAttachment[] = [];\n const rejected: { file: File; reason: 'type' | 'size' | 'count' }[] = [];\n\n const remainingSlots =\n typeof maxAttachments === 'number'\n ? Math.max(maxAttachments - attachments.length, 0)\n : Infinity;\n\n for (const file of files) {\n if (next.length >= remainingSlots) {\n rejected.push({ file, reason: 'count' });\n continue;\n }\n if (typeof maxFileSize === 'number' && file.size > maxFileSize) {\n rejected.push({ file, reason: 'size' });\n continue;\n }\n if (!matchesAccept(file, accepts)) {\n rejected.push({ file, reason: 'type' });\n continue;\n }\n const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n const looksLikeImageByExt = /\\.(png|jpe?g|gif|webp|bmp|svg)$/i.test(file.name);\n const isImageType = (file.type || '').toLowerCase().startsWith('image/');\n const url = isImageType || looksLikeImageByExt ? URL.createObjectURL(file) : undefined;\n if (url) generatedUrlSetRef.current.add(url);\n next.push({ id, name: file.name, size: file.size, type: file.type, url, status: 'idle' });\n }\n return { accepted: next, rejected };\n };\n\n const appendFiles = (files: File[]) => {\n const { accepted, rejected } = mapFilesToAttachments(files);\n if (accepted.length > 0) {\n const merged = attachments.concat(accepted);\n if (!isAttachmentsControlled) setAttachmentsUncontrolled(merged);\n onAttachmentsChange?.(merged);\n }\n if (rejected.length > 0) onAttachmentReject?.(rejected);\n };\n\n const appendFilesFromPaste = (files: File[]) => {\n // Use pasteAccepts for type filtering\n const matches = (file: File) => {\n if (pasteAccepts.length === 0) return matchesAccept(file, accepts);\n return matchesAccept(file, pasteAccepts);\n };\n const acceptedFiles: File[] = [];\n const rejected: { file: File; reason: 'type' | 'size' | 'count' }[] = [];\n\n // Enforce maxAttachments and maxFileSize\n const remainingSlots =\n typeof maxAttachments === 'number'\n ? Math.max(maxAttachments - attachments.length, 0)\n : Infinity;\n for (const file of files) {\n if (acceptedFiles.length >= remainingSlots) {\n rejected.push({ file, reason: 'count' });\n continue;\n }\n if (typeof maxFileSize === 'number' && file.size > maxFileSize) {\n rejected.push({ file, reason: 'size' });\n continue;\n }\n if (!matches(file)) {\n rejected.push({ file, reason: 'type' });\n continue;\n }\n acceptedFiles.push(file);\n }\n if (acceptedFiles.length > 0) appendFiles(acceptedFiles);\n if (rejected.length > 0) onAttachmentReject?.(rejected);\n };\n\n // Revoke object URLs that are no longer referenced by current attachments\n React.useEffect(() => {\n const currentUrls = new Set(attachments.map((a) => a.url).filter(Boolean) as string[]);\n for (const url of Array.from(generatedUrlSetRef.current)) {\n if (!currentUrls.has(url)) {\n URL.revokeObjectURL(url);\n generatedUrlSetRef.current.delete(url);\n }\n }\n }, [attachments]);\n\n // Revoke any remaining generated URLs on unmount\n React.useEffect(() => {\n return () => {\n for (const url of Array.from(generatedUrlSetRef.current)) {\n URL.revokeObjectURL(url);\n }\n generatedUrlSetRef.current.clear();\n };\n }, []);\n\n const Comp = asChild ? Slot : ('div' as any);\n\n const handleBlurCapture = React.useCallback(\n (event: React.FocusEvent) => {\n const nextTarget = event.relatedTarget as Node | null;\n const rootEl = rootRef.current;\n if (!rootEl) return;\n // If focus remains within root, ignore\n if (nextTarget && rootEl.contains(nextTarget)) return;\n // Collapse when leaving the root if the value is empty\n if ((value?.trim?.() ?? '').length === 0) {\n if (!isOpenControlled) setOpenUncontrolled(false);\n onOpenChangeProp?.(false);\n }\n },\n [isOpenControlled, onOpenChangeProp, value],\n );\n\n // Dropzone functionality\n const { getRootProps, getInputProps, isDragActive } = useDropzone({\n onDrop: (acceptedFiles, rejectedFiles) => {\n if (acceptedFiles.length > 0) {\n appendFiles(acceptedFiles);\n }\n if (rejectedFiles.length > 0 && onAttachmentReject) {\n const rejections = rejectedFiles.map(({ file, errors }) => {\n const reason =\n errors[0]?.code === 'file-too-large'\n ? 'size'\n : errors[0]?.code === 'file-invalid-type'\n ? 'type'\n : 'count';\n return { file, reason: reason as 'type' | 'size' | 'count' };\n });\n onAttachmentReject(rejections);\n }\n },\n accept:\n accepts.length > 0\n ? accepts.reduce(\n (acc, pattern) => {\n if (pattern.includes('/')) {\n // MIME type pattern\n acc[pattern] = [];\n } else if (pattern.startsWith('.')) {\n // File extension pattern\n acc[pattern] = [];\n }\n return acc;\n },\n {} as Record<string, string[]>,\n )\n : undefined,\n multiple,\n maxSize: maxFileSize,\n noClick: true,\n noKeyboard: true,\n disabled: !dropzone || disabled,\n });\n\n return (\n <ChatbarContext.Provider\n value={{\n open,\n setOpen: (next) => {\n if (!isOpenControlled) setOpenUncontrolled(next);\n onOpenChangeProp?.(next);\n },\n isOpenControlled,\n value,\n setValue: (next) => {\n if (!isValueControlled) setValueUncontrolled(next);\n onValueChangeProp?.(next);\n },\n isValueControlled,\n size,\n expandOn,\n minLines,\n maxLines,\n sendMode,\n disabled,\n readOnly,\n onSubmit,\n rootRef,\n textareaRef,\n attachments,\n setAttachments: (next) => {\n if (!isAttachmentsControlled) setAttachmentsUncontrolled(next);\n onAttachmentsChange?.(next);\n },\n isAttachmentsControlled,\n accept,\n multiple,\n maxAttachments,\n maxFileSize,\n paste,\n pasteAccept,\n clearOnSubmit,\n onAttachmentReject,\n dropzone,\n appendFiles,\n appendFilesFromPaste,\n }}\n >\n <Comp\n {...divProps}\n ref={(node: HTMLDivElement) => {\n if (typeof forwardedRef === 'function') forwardedRef(node);\n else if (forwardedRef)\n (forwardedRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n (rootRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n }}\n className={classNames('rt-ChatbarRoot', `rt-r-size-${size}`, className)}\n style={{ position: 'relative', width, maxWidth, ...style }}\n data-state={open ? 'open' : 'closed'}\n data-disabled={disabled ? '' : undefined}\n data-readonly={readOnly ? '' : undefined}\n data-drop-active={dropzone && isDragActive ? '' : undefined}\n aria-expanded={open}\n onBlurCapture={handleBlurCapture}\n >\n {dropzone && <input {...getInputProps()} />}\n <div {...(dropzone ? getRootProps() : {})} style={{ width: '100%', height: '100%' }}>\n <Card\n className=\"rt-ChatbarCard\"\n size={Math.min(3, Number(size) + 1).toString() as '1' | '2' | '3'}\n variant={variant as any}\n style={{ position: 'relative' }}\n >\n <div className=\"rt-ChatbarGrid\">{children}</div>\n {dropzone && isDragActive && (\n <div className=\"rt-ChatbarDropOverlay\">\n <div className=\"rt-ChatbarDropContent\">\n <Text color=\"gray\" size={size} weight=\"medium\">\n Drop files here to attach\n </Text>\n </div>\n </div>\n )}\n </Card>\n </div>\n </Comp>\n </ChatbarContext.Provider>\n );\n});\nRoot.displayName = 'Chatbar.Root';\n\n/**\n * Multi-line text input for Chatbar.\n * - Uses onChange to control value and avoid duplicate updates.\n * - Auto-resizes between minLines and maxLines.\n * - Expands on focus/overflow per `expandOn`.\n * - Paste-to-attach: when `paste` is enabled on Root, pasting files adds attachments.\n * - Provide `aria-label` or `aria-labelledby` for an accessible name.\n */\ninterface TextareaProps extends Omit<React.ComponentPropsWithoutRef<'textarea'>, 'size'> {\n asChild?: boolean;\n /**\n * Handler for paste events. This is forwarded to the underlying <textarea>.\n */\n onPaste?: React.ClipboardEventHandler<HTMLTextAreaElement>;\n /**\n * When true, pressing Enter submits via onSend (Shift+Enter inserts newline).\n * Defaults to false.\n */\n submitOnEnter?: boolean;\n}\n\n/**\n * Chatbar multi-line text input.\n *\n * Behavior\n * - Controls the Chatbar value via React onChange. We intentionally do not\n * update state in onInput to avoid duplicate updates per keystroke.\n * - Auto-resizes between minLines and maxLines using layout measurements.\n * - When expandOn is `overflow` or `both`, the Chatbar opens as soon as the\n * content exceeds the compact height.\n * - Height recalculations occur on change, paste, and whenever `value` or `open`\n * changes via an isomorphic layout effect to avoid SSR warnings.\n *\n * Accessibility\n * - Consumers should provide labeling via aria-label or aria-labelledby\n * on this component, as no implicit label is rendered.\n */\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>((props, forwardedRef) => {\n const {\n className,\n style,\n asChild,\n onFocus,\n onInput,\n onChange,\n onPaste,\n onKeyDown,\n submitOnEnter = false,\n rows,\n ...textareaProps\n } = props;\n const ctx = useChatbarContext();\n const {\n open,\n minLines,\n maxLines,\n expandOn,\n disabled,\n readOnly,\n setOpen,\n setValue,\n textareaRef,\n value,\n isValueControlled,\n sendMode,\n paste,\n appendFilesFromPaste,\n size,\n } = ctx;\n\n // Cached metrics to avoid repeated getComputedStyle calls\n const lineHeightRef = React.useRef<number>(0);\n const paddingRef = React.useRef<number>(0);\n const compactHeightRef = React.useRef<number>(0);\n\n const recomputeMetrics = React.useCallback(() => {\n const el = textareaRef.current;\n if (!el) return;\n const computedStyle = window.getComputedStyle(el);\n const lineHeight = parseFloat(computedStyle.lineHeight) || 20;\n const paddingTop = parseFloat(computedStyle.paddingTop) || 0;\n const paddingBottom = parseFloat(computedStyle.paddingBottom) || 0;\n lineHeightRef.current = lineHeight;\n paddingRef.current = paddingTop + paddingBottom;\n compactHeightRef.current = Math.ceil(1 * lineHeight) + paddingTop + paddingBottom;\n }, [textareaRef]);\n\n // Auto-resize logic - optimized for fixed widths\n const updateHeight = React.useCallback(\n (forceOpen?: boolean) => {\n const textarea = textareaRef.current;\n if (!textarea) return;\n\n textarea.style.height = 'auto';\n\n if (lineHeightRef.current === 0) {\n recomputeMetrics();\n }\n const lineHeight = lineHeightRef.current;\n const padding = paddingRef.current;\n\n const isOpen = forceOpen ?? open;\n const effectiveMinLines = isOpen ? minLines : 1;\n const effectiveMaxLines = isOpen ? maxLines : 1;\n\n const minHeight = Math.ceil(effectiveMinLines * lineHeight) + padding;\n const maxHeight = Math.ceil(effectiveMaxLines * lineHeight) + padding;\n\n const contentHeight = Math.max(textarea.scrollHeight, minHeight);\n const finalHeight = Math.min(contentHeight, maxHeight);\n\n textarea.style.height = `${finalHeight}px`;\n\n if (contentHeight > maxHeight) {\n textarea.style.overflowY = 'auto';\n textarea.style.maxHeight = `${maxHeight}px`;\n } else {\n textarea.style.overflowY = 'hidden';\n textarea.style.maxHeight = 'none';\n }\n },\n [open, minLines, maxLines, textareaRef, recomputeMetrics],\n );\n\n // Update height when value or open state changes\n useIsomorphicLayoutEffect(() => {\n updateHeight();\n }, [updateHeight, value, open]);\n\n // Recompute metrics on mount and when size changes may affect typography\n useIsomorphicLayoutEffect(() => {\n recomputeMetrics();\n updateHeight();\n }, [recomputeMetrics, updateHeight, size]);\n\n // Observe responsive changes that alter line-height\n React.useEffect(() => {\n const el = textareaRef.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n let prevLineHeight = lineHeightRef.current;\n const ro = new ResizeObserver(() => {\n const computedStyle = window.getComputedStyle(el);\n const lh = parseFloat(computedStyle.lineHeight) || 20;\n if (lh !== prevLineHeight) {\n prevLineHeight = lh;\n recomputeMetrics();\n requestAnimationFrame(() => updateHeight());\n }\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, [textareaRef, recomputeMetrics, updateHeight]);\n\n // Dev-only warning if no accessible name is provided\n React.useEffect(() => {\n if (process.env.NODE_ENV === 'production') return;\n const hasLabel =\n textareaProps['aria-label'] != null || textareaProps['aria-labelledby'] != null;\n if (!hasLabel) {\n // eslint-disable-next-line no-console\n console.warn(\n '[Chatbar.Textarea] Provide aria-label or aria-labelledby to ensure the control has an accessible name.',\n );\n }\n // warn only on mount\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Note: No MutationObserver is used because <textarea> value changes are not\n // reflected in DOM text nodes. Height updates are handled by effects and events.\n\n const handleFocus = React.useCallback<React.FocusEventHandler<HTMLTextAreaElement>>(\n (event) => {\n if (disabled || readOnly) return;\n if ((expandOn === 'focus' || expandOn === 'both') && !open) setOpen(true);\n onFocus?.(event);\n },\n [disabled, readOnly, expandOn, open, setOpen, onFocus],\n );\n\n const handleChange = React.useCallback<React.ChangeEventHandler<HTMLTextAreaElement>>(\n (event) => {\n const el = event.currentTarget;\n const nextValue = el.value;\n setValue(nextValue);\n\n if ((expandOn === 'overflow' || expandOn === 'both') && !open) {\n el.style.height = 'auto';\n\n if (compactHeightRef.current === 0) {\n recomputeMetrics();\n }\n const shouldExpand = el.scrollHeight > compactHeightRef.current + 1;\n if (shouldExpand) {\n setOpen(true);\n // Immediately size for open state to avoid 1-line + scrollbar flash\n updateHeight(true);\n requestAnimationFrame(() => updateHeight(true));\n }\n }\n\n // Always recalc after any input\n requestAnimationFrame(() => updateHeight());\n onChange?.(event);\n },\n [expandOn, open, setOpen, setValue, onChange, updateHeight, recomputeMetrics],\n );\n\n const handlePaste = React.useCallback<React.ClipboardEventHandler<HTMLTextAreaElement>>(\n (event) => {\n // Attach files from clipboard if enabled\n if (paste) {\n const items = Array.from(event.clipboardData?.items ?? []);\n const files = items\n .filter((i) => i.kind === 'file')\n .map((i) => i.getAsFile())\n .filter((f): f is File => !!f);\n if (files.length > 0) {\n appendFilesFromPaste(files);\n }\n }\n setTimeout(() => {\n // If pasting in compact mode, force sizing as open if content overflowed\n if (!open) {\n updateHeight(true);\n } else {\n updateHeight();\n }\n }, 0);\n onPaste?.(event);\n },\n [paste, open, updateHeight, onPaste, appendFilesFromPaste],\n );\n\n const handleKeyDown = React.useCallback<React.KeyboardEventHandler<HTMLTextAreaElement>>(\n (event) => {\n if (!submitOnEnter) {\n onKeyDown?.(event);\n return;\n }\n if (\n event.key === 'Enter' &&\n !event.shiftKey &&\n !event.altKey &&\n !event.ctrlKey &&\n !event.metaKey &&\n !event.nativeEvent.isComposing\n ) {\n if (disabled || readOnly) {\n onKeyDown?.(event);\n return;\n }\n if (sendMode === 'never') {\n onKeyDown?.(event);\n return;\n }\n const trimmed = value.trim();\n if (sendMode === 'whenDirty' && trimmed.length === 0) {\n onKeyDown?.(event);\n return;\n }\n event.preventDefault();\n ctx.onSubmit?.({ value, attachments: ctx.attachments });\n if (ctx.clearOnSubmit) {\n if (!isValueControlled) setValue('');\n ctx.setAttachments([]);\n }\n }\n onKeyDown?.(event);\n },\n [\n submitOnEnter,\n disabled,\n readOnly,\n sendMode,\n value,\n isValueControlled,\n setValue,\n ctx,\n onKeyDown,\n ],\n );\n\n const Comp = asChild ? Slot : ('textarea' as any);\n return (\n <div className={classNames('rt-ChatbarField', 'rt-ChatbarTextarea', className)}>\n <Comp\n {...textareaProps}\n ref={(node: HTMLTextAreaElement) => {\n if (typeof forwardedRef === 'function') forwardedRef(node);\n else if (forwardedRef)\n (forwardedRef as React.MutableRefObject<HTMLTextAreaElement | null>).current = node;\n (textareaRef as React.MutableRefObject<HTMLTextAreaElement | null>).current = node;\n }}\n className=\"rt-ChatbarInput\"\n value={value}\n onInput={onInput}\n onChange={handleChange}\n onFocus={handleFocus}\n onPaste={handlePaste}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n readOnly={readOnly}\n rows={open ? minLines : 1}\n spellCheck={textareaProps.spellCheck ?? true}\n autoCorrect={textareaProps.autoCorrect ?? 'on'}\n style={style}\n />\n </div>\n );\n});\nTextarea.displayName = 'Chatbar.Textarea';\n\ninterface InlineSlotProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'children'> {\n asChild?: boolean;\n children?: React.ReactNode;\n}\n\nconst InlineStart = React.forwardRef<HTMLDivElement, InlineSlotProps>((props, forwardedRef) => {\n const { children, asChild, style, className, ...divProps } = props;\n const ctx = useChatbarContext();\n if (ctx.open) return null;\n const Comp = asChild ? Slot : ('div' as any);\n return (\n <Comp\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarInlineStart', className)}\n style={style}\n >\n {children}\n </Comp>\n );\n});\nInlineStart.displayName = 'Chatbar.InlineStart';\n\nconst InlineEnd = React.forwardRef<HTMLDivElement, InlineSlotProps>((props, forwardedRef) => {\n const { children, asChild, style, className, ...divProps } = props;\n const ctx = useChatbarContext();\n if (ctx.open) return null;\n const Comp = asChild ? Slot : ('div' as any);\n return (\n <Comp\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarInlineEnd', className)}\n style={style}\n >\n {children}\n </Comp>\n );\n});\nInlineEnd.displayName = 'Chatbar.InlineEnd';\n\n/**\n * Renders a horizontally scrollable list of attachments above the inline row.\n * Hidden when empty unless `forceMount`. Override per-item with `renderAttachment`.\n */\ninterface AttachmentsRowProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'children'> {\n asChild?: boolean;\n forceMount?: boolean;\n /** If provided, custom-render a tile; otherwise default tile is used */\n renderAttachment?: (attachment: ChatbarAttachment) => React.ReactNode;\n}\n\nconst AttachmentsRow = React.forwardRef<HTMLDivElement, AttachmentsRowProps>(\n (props, forwardedRef) => {\n const { asChild, forceMount, renderAttachment, className, style, ...divProps } = props;\n const ctx = useChatbarContext();\n const hasItems = ctx.attachments.length > 0;\n if (!hasItems && !forceMount) return null;\n const Comp = asChild ? Slot : ('div' as any);\n return (\n <Comp\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarAttachmentsRow', className)}\n style={style}\n role=\"list\"\n aria-label={divProps['aria-label'] ?? 'Attachments'}\n >\n <ScrollArea className=\"rt-ChatbarScrollArea\" scrollbars=\"horizontal\" size=\"1\">\n <Flex align=\"center\" gap=\"2\" style={{ minWidth: 'fit-content' }}>\n {ctx.attachments.map((att) => (\n <Attachment key={att.id} attachment={att} asChild={!!renderAttachment}>\n {renderAttachment?.(att)}\n </Attachment>\n ))}\n </Flex>\n </ScrollArea>\n </Comp>\n );\n },\n);\nAttachmentsRow.displayName = 'Chatbar.AttachmentsRow';\n\n/** Default tile renderer for a single attachment. */\ninterface AttachmentProps extends React.ComponentPropsWithoutRef<'div'> {\n attachment: ChatbarAttachment;\n asChild?: boolean;\n}\n\nconst Attachment = React.forwardRef<HTMLDivElement, AttachmentProps>((props, forwardedRef) => {\n const { attachment, asChild, className, style, children, ...divProps } = props;\n const ctx = useChatbarContext();\n const Comp = asChild ? Slot : ('div' as any);\n const isImage = !!attachment.url && attachment.type.startsWith('image/');\n return (\n <Comp\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarAttachment', className)}\n style={style}\n role=\"listitem\"\n data-kind={isImage ? 'image' : 'file'}\n title={attachment.name}\n >\n {children ?? (\n <Card size={ctx.size} variant=\"soft\">\n <Flex align=\"center\" gap=\"3\" pr={!isImage ? '6' : undefined}>\n <div className=\"rt-ChatbarAttachmentPreview\" aria-hidden>\n {isImage ? (\n <img className=\"rt-ChatbarAttachmentImage\" src={attachment.url} alt=\"\" />\n ) : (\n <FileTextIcon />\n )}\n </div>\n {!isImage && (\n <Flex direction=\"column\" gap=\"0\" style={{ minWidth: 0 }}>\n <Text\n size={ctx.size}\n weight=\"medium\"\n style={{ whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}\n >\n {attachment.name}\n </Text>\n <Text size=\"1\" color=\"gray\">\n {Math.ceil(attachment.size / 1024)} KB\n </Text>\n </Flex>\n )}\n <IconButton\n className=\"rt-ChatbarAttachmentRemove\"\n aria-label={`Remove ${attachment.name}`}\n size=\"1\"\n // size={ctx.size}\n variant=\"classic\"\n highContrast\n color=\"gray\"\n onClick={() =>\n ctx.setAttachments(ctx.attachments.filter((a) => a.id !== attachment.id))\n }\n >\n <CloseIcon />\n </IconButton>\n </Flex>\n </Card>\n )}\n </Comp>\n );\n});\nAttachment.displayName = 'Chatbar.Attachment';\n\ninterface AttachTriggerProps extends React.ComponentPropsWithoutRef<'button'> {\n asChild?: boolean;\n accept?: string | string[];\n multiple?: boolean;\n}\n\nconst AttachTrigger = React.forwardRef<HTMLButtonElement, AttachTriggerProps>(\n (props, forwardedRef) => {\n const { asChild, accept, multiple, className, style, ...buttonProps } = props;\n const ctx = useChatbarContext();\n const inputRef = React.useRef<HTMLInputElement | null>(null);\n const Comp = asChild ? Slot : ('button' as any);\n const actualAccept = (Array.isArray(accept) ? accept : (accept?.split(',') ?? [])).join(',');\n return (\n <>\n <Comp\n {...(buttonProps as any)}\n ref={forwardedRef as any}\n className={classNames('rt-ChatbarAttachTrigger', className)}\n style={style}\n type={buttonProps.type ?? 'button'}\n aria-label={buttonProps['aria-label'] ?? 'Add attachments'}\n onClick={(e: any) => {\n // Ensure file input opens reliably by clicking it first\n if (inputRef.current) {\n inputRef.current.click();\n }\n // Then call user's onClick if provided\n buttonProps.onClick?.(e);\n }}\n />\n <input\n ref={inputRef}\n type=\"file\"\n accept={actualAccept}\n multiple={multiple ?? ctx.multiple}\n tabIndex={-1}\n style={{ display: 'none' }}\n onChange={(e) => {\n const files = Array.from(e.currentTarget.files ?? []);\n if (files.length > 0) {\n ctx.appendFiles(files);\n }\n // Reset input value to allow selecting the same file again\n e.currentTarget.value = '';\n }}\n />\n </>\n );\n },\n);\nAttachTrigger.displayName = 'Chatbar.AttachTrigger';\ninterface RowProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'children'> {\n asChild?: boolean;\n children?: React.ReactNode;\n}\n\nconst Row = React.forwardRef<HTMLDivElement, RowProps>((props, forwardedRef) => {\n const { asChild, children, className, style, ...divProps } = props;\n const ctx = useChatbarContext();\n if (!ctx.open) return null;\n const Comp = asChild ? Slot : ('div' as any);\n return (\n <Comp\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarRow', className)}\n style={style}\n >\n <Flex align=\"center\" justify=\"between\" width=\"100%\">\n {children}\n </Flex>\n </Comp>\n );\n});\nRow.displayName = 'Chatbar.Row';\n\nconst RowStart = React.forwardRef<HTMLDivElement, React.ComponentPropsWithoutRef<'div'>>(\n (props, forwardedRef) => {\n const { className, style, ...divProps } = props;\n return (\n <div\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarRowStart', className)}\n style={style}\n />\n );\n },\n);\nRowStart.displayName = 'Chatbar.RowStart';\n\nconst RowEnd = React.forwardRef<HTMLDivElement, React.ComponentPropsWithoutRef<'div'>>(\n (props, forwardedRef) => {\n const { className, style, ...divProps } = props;\n return (\n <div\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarRowEnd', className)}\n style={style}\n />\n );\n },\n);\nRowEnd.displayName = 'Chatbar.RowEnd';\n\ninterface SendProps extends Omit<IconButtonProps, 'size'> {\n asChild?: boolean;\n clearOnSend?: boolean;\n}\n\nconst Send = React.forwardRef<HTMLButtonElement, SendProps>((props, forwardedRef) => {\n const {\n asChild,\n clearOnSend = true,\n disabled,\n children,\n className,\n style,\n ...buttonProps\n } = props;\n const ctx = useChatbarContext();\n\n const trimmed = ctx.value.trim();\n const visible = ctx.sendMode === 'always' || (ctx.sendMode === 'whenDirty' && trimmed.length > 0);\n if (ctx.sendMode === 'never') return null;\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n if (ctx.disabled || ctx.readOnly) return;\n ctx.onSubmit?.({ value: ctx.value, attachments: ctx.attachments });\n if (clearOnSend) {\n if (!ctx.isValueControlled) ctx.setValue('');\n if (ctx.clearOnSubmit) ctx.setAttachments([]);\n }\n buttonProps.onClick?.(event);\n };\n\n return (\n <IconButton\n {...(buttonProps as any)}\n ref={forwardedRef as any}\n size={ctx.size}\n variant={ctx.open ? 'solid' : 'ghost'}\n disabled={disabled || ctx.disabled || ctx.readOnly}\n className={classNames('rt-ChatbarSend', className)}\n style={{\n opacity: visible ? 1 : 0,\n pointerEvents: visible ? 'auto' : 'none',\n ...style,\n }}\n asChild={asChild}\n onClick={handleClick}\n aria-label={buttonProps['aria-label'] ?? 'Send'}\n >\n {children ?? 'Send'}\n </IconButton>\n );\n});\nSend.displayName = 'Chatbar.Send';\n\nexport {\n Root,\n Textarea,\n InlineStart,\n InlineEnd,\n AttachmentsRow,\n Attachment,\n AttachTrigger,\n Row,\n RowStart,\n RowEnd,\n Send,\n};\nexport type {\n RootProps as ChatbarRootProps,\n TextareaProps as ChatbarTextareaProps,\n RowProps as ChatbarRowProps,\n SendProps as ChatbarSendProps,\n};\n"],
5
- "mappings": "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",
6
- "names": ["React", "classNames", "IconButton", "CloseIcon", "FileTextIcon", "Flex", "ScrollArea", "Slot", "Card", "Text", "useDropzone", "useIsomorphicLayoutEffect", "ChatbarContext", "useChatbarContext", "ctx", "Root", "props", "forwardedRef", "className", "style", "children", "valueProp", "defaultValue", "onValueChangeProp", "openProp", "defaultOpen", "onOpenChangeProp", "expandOn", "minLines", "maxLines", "sendMode", "disabled", "readOnly", "onSubmit", "size", "variant", "width", "maxWidth", "asChild", "attachmentsProp", "defaultAttachments", "onAttachmentsChange", "accept", "multiple", "maxAttachments", "maxFileSize", "paste", "pasteAccept", "clearOnSubmit", "onAttachmentReject", "dropzone", "divProps", "isValueControlled", "valueUncontrolled", "setValueUncontrolled", "value", "isOpenControlled", "openUncontrolled", "setOpenUncontrolled", "open", "rootRef", "textareaRef", "isAttachmentsControlled", "attachmentsUncontrolled", "setAttachmentsUncontrolled", "attachments", "generatedUrlSetRef", "toArray", "val", "s", "accepts", "pasteAccepts", "matchesAccept", "file", "patterns", "mime", "name", "patRaw", "pat", "type", "subtype", "fmType", "fmSubtype", "mapFilesToAttachments", "files", "next", "rejected", "remainingSlots", "id", "looksLikeImageByExt", "url", "appendFiles", "accepted", "merged", "appendFilesFromPaste", "matches", "acceptedFiles", "currentUrls", "a", "Comp", "handleBlurCapture", "event", "nextTarget", "rootEl", "getRootProps", "getInputProps", "isDragActive", "rejectedFiles", "rejections", "errors", "reason", "acc", "pattern", "node", "Textarea", "onFocus", "onInput", "onChange", "onPaste", "onKeyDown", "submitOnEnter", "rows", "textareaProps", "setOpen", "setValue", "lineHeightRef", "paddingRef", "compactHeightRef", "recomputeMetrics", "el", "computedStyle", "lineHeight", "paddingTop", "paddingBottom", "updateHeight", "forceOpen", "textarea", "padding", "isOpen", "effectiveMinLines", "effectiveMaxLines", "minHeight", "maxHeight", "contentHeight", "finalHeight", "prevLineHeight", "ro", "lh", "handleFocus", "handleChange", "nextValue", "handlePaste", "i", "f", "handleKeyDown", "trimmed", "InlineStart", "InlineEnd", "AttachmentsRow", "forceMount", "renderAttachment", "att", "Attachment", "attachment", "isImage", "AttachTrigger", "buttonProps", "inputRef", "actualAccept", "e", "Row", "RowStart", "RowEnd", "Send", "clearOnSend", "visible", "handleClick"]
4
+ "sourcesContent": ["import * as React from 'react';\nimport classNames from 'classnames';\n\nimport { IconButton, type IconButtonProps } from './icon-button.js';\nimport { CloseIcon, FileTextIcon } from './icons.js';\nimport { Flex } from './flex.js';\n\nimport { ScrollArea } from './scroll-area.js';\nimport { Slot } from './slot.js';\nimport { Card } from './card.js';\nimport { Text } from './text.js';\nimport { useDropzone } from 'react-dropzone';\nimport type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js';\n\n// Avoid SSR warnings by using an isomorphic layout effect\nconst useIsomorphicLayoutEffect =\n typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;\n\ntype ExpandOn = 'none' | 'focus' | 'overflow' | 'both';\ntype SendMode = 'always' | 'whenDirty' | 'never';\n\n// Attachments\n/** Status flag for attachment lifecycle. */\ntype AttachmentStatus = 'idle' | 'uploading' | 'error' | 'done';\n/**\n * Attachment data model used by Chatbar.\n * - `file` exposes the original File object for uploads and processing.\n * - `url` is an object URL used for image previews and is revoked on removal.\n */\ninterface ChatbarAttachment {\n id: string;\n name: string;\n size: number;\n type: string;\n /** Original File object for uploads and processing */\n file: File;\n url?: string;\n status?: AttachmentStatus;\n progress?: number;\n meta?: Record<string, unknown>;\n}\n\ninterface ChatbarContextValue {\n open: boolean;\n setOpen(next: boolean): void;\n isOpenControlled: boolean;\n\n value: string;\n setValue(next: string): void;\n isValueControlled: boolean;\n\n size: '1' | '2' | '3';\n expandOn: ExpandOn;\n minLines: number;\n maxLines: number;\n sendMode: SendMode;\n disabled?: boolean;\n readOnly?: boolean;\n\n // Submit returns both message and attachments\n onSubmit?: (payload: { value: string; attachments: ChatbarAttachment[] }) => void;\n\n rootRef: React.RefObject<HTMLDivElement | null>;\n textareaRef: React.RefObject<HTMLTextAreaElement | null>;\n\n // Attachments state\n attachments: ChatbarAttachment[];\n setAttachments(next: ChatbarAttachment[]): void;\n isAttachmentsControlled: boolean;\n\n // Config\n accept?: string | string[];\n multiple: boolean;\n maxAttachments?: number;\n maxFileSize?: number;\n paste: boolean;\n pasteAccept?: string | string[];\n clearOnSubmit: boolean;\n\n // Dropzone\n dropzone: boolean;\n\n // Events\n onAttachmentReject?: (rejections: { file: File; reason: 'type' | 'size' | 'count' }[]) => void;\n\n // Helpers\n appendFiles(files: File[]): void;\n appendFilesFromPaste(files: File[]): void;\n}\n\nconst ChatbarContext = React.createContext<ChatbarContextValue | null>(null);\nconst useChatbarContext = () => {\n const ctx = React.useContext(ChatbarContext);\n if (!ctx) throw new Error('Chatbar context not found. Wrap parts in <Chatbar.Root>.');\n return ctx;\n};\n\n/**\n * Chatbar container and state provider.\n *\n * Value & Open\n * - Supports controlled/uncontrolled `value` and `open`.\n *\n * Attachments\n * - Controlled/uncontrolled attachments with client-side filtering.\n * - Filters by `accept`/`pasteAccept`, `maxAttachments`, and `maxFileSize`.\n * - Rejections are reported via `onAttachmentReject`.\n *\n * Submit\n * - `onSubmit({ value, attachments })` emits both message and attachments.\n * - `clearOnSubmit` clears message and attachments by default.\n */\ninterface ChatbarRootBaseProps {\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n\n expandOn?: ExpandOn;\n\n /** Minimum number of lines in compact state (default: 1) */\n minLines?: number;\n /** Maximum number of lines before scrolling (default: 6) */\n maxLines?: number;\n\n sendMode?: SendMode;\n\n disabled?: boolean;\n readOnly?: boolean;\n\n /** Combined submit payload */\n onSubmit?: (payload: { value: string; attachments: ChatbarAttachment[] }) => void;\n\n size?: '1' | '2' | '3';\n variant?: 'surface' | 'outline' | 'classic' | 'ghost' | 'soft';\n\n width?: React.CSSProperties['width'];\n maxWidth?: React.CSSProperties['maxWidth'];\n asChild?: boolean;\n\n // Attachments API\n attachments?: ChatbarAttachment[];\n defaultAttachments?: ChatbarAttachment[];\n onAttachmentsChange?: (attachments: ChatbarAttachment[]) => void;\n accept?: string | string[];\n multiple?: boolean;\n maxAttachments?: number;\n maxFileSize?: number;\n paste?: boolean;\n pasteAccept?: string | string[];\n clearOnSubmit?: boolean;\n onAttachmentReject?: (rejections: { file: File; reason: 'type' | 'size' | 'count' }[]) => void;\n\n /**\n * Enables drag-and-drop file uploads when true.\n *\n * When enabled:\n * - Files can be dropped anywhere on the chatbar\n * - Same validation rules apply (accept, maxFileSize, maxAttachments)\n * - Visual feedback shows during drag operations\n * - Rejected files trigger onAttachmentReject\n *\n * @default true\n */\n dropzone?: boolean;\n}\n\ntype RootElement = React.ElementRef<'div'>;\n/**\n * Chatbar container and state provider.\n *\n * Behavior\n * - Supports controlled and uncontrolled `value` and `open` states via props.\n * - Provides context to subcomponents like `Textarea`, `Row`, and `Send`.\n * - Exposes `data-state`, `data-disabled`, and `data-readonly` attributes for styling.\n * - Sets `aria-expanded` to reflect open/closed state for assistive technologies.\n *\n * Attachments\n * - Controlled/uncontrolled attachments with client-side filtering.\n * - Filters by `accept`/`pasteAccept`, `maxAttachments`, and `maxFileSize`.\n * - Rejections are reported via `onAttachmentReject`.\n * - Paste-to-attach: when `paste` is enabled, pasting files adds attachments.\n *\n * Dropzone\n * - When `dropzone` is true, enables drag-and-drop file uploads.\n * - Files are validated using the same rules as paste and file picker.\n * - Visual feedback via `data-drop-active` attribute during drag operations.\n * - Rejected files trigger `onAttachmentReject` with appropriate reasons.\n *\n * Submit\n * - `onSubmit` receives both message text and attachments array.\n * - `clearOnSubmit` controls whether attachments are cleared after submission.\n *\n * Accessibility\n * - Consumers should label the `Textarea` via `aria-label`/`aria-labelledby`.\n * - `aria-expanded` on the root reflects the disclosure state of the input area.\n * - Dropzone provides proper ARIA attributes for drag and drop operations.\n */\ninterface RootProps\n extends ComponentPropsWithout<'div', RemovedProps | 'onSubmit'>,\n ChatbarRootBaseProps {}\n\nconst Root = React.forwardRef<RootElement, RootProps>((props, forwardedRef) => {\n const {\n className,\n style,\n children,\n value: valueProp,\n defaultValue = '',\n onValueChange: onValueChangeProp,\n open: openProp,\n defaultOpen = false,\n onOpenChange: onOpenChangeProp,\n expandOn = 'both',\n minLines = 1,\n maxLines = 6,\n sendMode = 'whenDirty',\n disabled,\n readOnly,\n onSubmit,\n size = '2',\n variant,\n width,\n maxWidth,\n asChild,\n attachments: attachmentsProp,\n defaultAttachments = [],\n onAttachmentsChange,\n accept,\n multiple = true,\n maxAttachments,\n maxFileSize,\n paste = true,\n pasteAccept,\n clearOnSubmit = true,\n onAttachmentReject,\n dropzone = true,\n ...divProps\n } = props;\n\n const isValueControlled = valueProp != null;\n const [valueUncontrolled, setValueUncontrolled] = React.useState<string>(defaultValue);\n const value = isValueControlled ? (valueProp as string) : valueUncontrolled;\n\n const isOpenControlled = openProp != null;\n const [openUncontrolled, setOpenUncontrolled] = React.useState<boolean>(defaultOpen);\n const open = isOpenControlled ? (openProp as boolean) : openUncontrolled;\n\n const rootRef = React.useRef<HTMLDivElement>(null);\n const textareaRef = React.useRef<HTMLTextAreaElement>(null);\n\n // Attachments state\n const isAttachmentsControlled = attachmentsProp != null;\n const [attachmentsUncontrolled, setAttachmentsUncontrolled] =\n React.useState<ChatbarAttachment[]>(defaultAttachments);\n const attachments = isAttachmentsControlled\n ? (attachmentsProp as ChatbarAttachment[])\n : attachmentsUncontrolled;\n\n // Track generated object URLs for cleanup\n const generatedUrlSetRef = React.useRef<Set<string>>(new Set());\n\n const toArray = (val: string | string[] | undefined) =>\n Array.isArray(val) ? val : typeof val === 'string' ? val.split(',').map((s) => s.trim()) : [];\n\n const accepts = toArray(accept);\n const pasteAccepts = toArray(pasteAccept).length > 0 ? toArray(pasteAccept) : accepts;\n\n const matchesAccept = (file: File, patterns: string[]) => {\n if (patterns.length === 0) return true;\n const mime = file.type.toLowerCase();\n const name = file.name.toLowerCase();\n for (const patRaw of patterns) {\n const pat = patRaw.toLowerCase();\n if (pat.includes('/')) {\n // MIME pattern\n const [type, subtype] = pat.split('/');\n const [fmType, fmSubtype] = mime.split('/');\n if (type === '*' || (type === fmType && (subtype === '*' || subtype === fmSubtype)))\n return true;\n } else if (pat.startsWith('.')) {\n if (name.endsWith(pat)) return true;\n }\n }\n return false;\n };\n\n /**\n * Maps File objects to attachments with validation and preview URL generation.\n */\n const mapFilesToAttachments = (\n files: File[],\n ): {\n accepted: ChatbarAttachment[];\n rejected: { file: File; reason: 'type' | 'size' | 'count' }[];\n } => {\n const next: ChatbarAttachment[] = [];\n const rejected: { file: File; reason: 'type' | 'size' | 'count' }[] = [];\n\n const remainingSlots =\n typeof maxAttachments === 'number'\n ? Math.max(maxAttachments - attachments.length, 0)\n : Infinity;\n\n for (const file of files) {\n if (next.length >= remainingSlots) {\n rejected.push({ file, reason: 'count' });\n continue;\n }\n if (typeof maxFileSize === 'number' && file.size > maxFileSize) {\n rejected.push({ file, reason: 'size' });\n continue;\n }\n if (!matchesAccept(file, accepts)) {\n rejected.push({ file, reason: 'type' });\n continue;\n }\n const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n const looksLikeImageByExt = /\\.(png|jpe?g|gif|webp|bmp|svg)$/i.test(file.name);\n const isImageType = (file.type || '').toLowerCase().startsWith('image/');\n const url = isImageType || looksLikeImageByExt ? URL.createObjectURL(file) : undefined;\n if (url) generatedUrlSetRef.current.add(url);\n next.push({\n id,\n name: file.name,\n size: file.size,\n type: file.type,\n file,\n url,\n status: 'idle',\n });\n }\n return { accepted: next, rejected };\n };\n\n const appendFiles = (files: File[]) => {\n const { accepted, rejected } = mapFilesToAttachments(files);\n if (accepted.length > 0) {\n const merged = attachments.concat(accepted);\n if (!isAttachmentsControlled) setAttachmentsUncontrolled(merged);\n onAttachmentsChange?.(merged);\n }\n if (rejected.length > 0) onAttachmentReject?.(rejected);\n };\n\n const appendFilesFromPaste = (files: File[]) => {\n // Use pasteAccepts for type filtering\n const matches = (file: File) => {\n if (pasteAccepts.length === 0) return matchesAccept(file, accepts);\n return matchesAccept(file, pasteAccepts);\n };\n const acceptedFiles: File[] = [];\n const rejected: { file: File; reason: 'type' | 'size' | 'count' }[] = [];\n\n // Enforce maxAttachments and maxFileSize\n const remainingSlots =\n typeof maxAttachments === 'number'\n ? Math.max(maxAttachments - attachments.length, 0)\n : Infinity;\n for (const file of files) {\n if (acceptedFiles.length >= remainingSlots) {\n rejected.push({ file, reason: 'count' });\n continue;\n }\n if (typeof maxFileSize === 'number' && file.size > maxFileSize) {\n rejected.push({ file, reason: 'size' });\n continue;\n }\n if (!matches(file)) {\n rejected.push({ file, reason: 'type' });\n continue;\n }\n acceptedFiles.push(file);\n }\n if (acceptedFiles.length > 0) appendFiles(acceptedFiles);\n if (rejected.length > 0) onAttachmentReject?.(rejected);\n };\n\n // Revoke object URLs that are no longer referenced by current attachments\n React.useEffect(() => {\n const currentUrls = new Set(attachments.map((a) => a.url).filter(Boolean) as string[]);\n for (const url of Array.from(generatedUrlSetRef.current)) {\n if (!currentUrls.has(url)) {\n URL.revokeObjectURL(url);\n generatedUrlSetRef.current.delete(url);\n }\n }\n }, [attachments]);\n\n // Revoke any remaining generated URLs on unmount\n React.useEffect(() => {\n return () => {\n for (const url of Array.from(generatedUrlSetRef.current)) {\n URL.revokeObjectURL(url);\n }\n generatedUrlSetRef.current.clear();\n };\n }, []);\n\n const Comp = asChild ? Slot : ('div' as any);\n\n const handleBlurCapture = React.useCallback(\n (event: React.FocusEvent) => {\n const nextTarget = event.relatedTarget as Node | null;\n const rootEl = rootRef.current;\n if (!rootEl) return;\n // If focus remains within root, ignore\n if (nextTarget && rootEl.contains(nextTarget)) return;\n // Collapse when leaving the root if the value is empty\n if ((value?.trim?.() ?? '').length === 0) {\n if (!isOpenControlled) setOpenUncontrolled(false);\n onOpenChangeProp?.(false);\n }\n },\n [isOpenControlled, onOpenChangeProp, value],\n );\n\n // Dropzone functionality\n const { getRootProps, getInputProps, isDragActive } = useDropzone({\n onDrop: (acceptedFiles, rejectedFiles) => {\n if (acceptedFiles.length > 0) {\n appendFiles(acceptedFiles);\n }\n if (rejectedFiles.length > 0 && onAttachmentReject) {\n const rejections = rejectedFiles.map(({ file, errors }) => {\n const reason =\n errors[0]?.code === 'file-too-large'\n ? 'size'\n : errors[0]?.code === 'file-invalid-type'\n ? 'type'\n : 'count';\n return { file, reason: reason as 'type' | 'size' | 'count' };\n });\n onAttachmentReject(rejections);\n }\n },\n accept:\n accepts.length > 0\n ? accepts.reduce(\n (acc, pattern) => {\n if (pattern.includes('/')) {\n // MIME type pattern\n acc[pattern] = [];\n } else if (pattern.startsWith('.')) {\n // File extension pattern\n acc[pattern] = [];\n }\n return acc;\n },\n {} as Record<string, string[]>,\n )\n : undefined,\n multiple,\n maxSize: maxFileSize,\n noClick: true,\n noKeyboard: true,\n disabled: !dropzone || disabled,\n });\n\n return (\n <ChatbarContext.Provider\n value={{\n open,\n setOpen: (next) => {\n if (!isOpenControlled) setOpenUncontrolled(next);\n onOpenChangeProp?.(next);\n },\n isOpenControlled,\n value,\n setValue: (next) => {\n if (!isValueControlled) setValueUncontrolled(next);\n onValueChangeProp?.(next);\n },\n isValueControlled,\n size,\n expandOn,\n minLines,\n maxLines,\n sendMode,\n disabled,\n readOnly,\n onSubmit,\n rootRef,\n textareaRef,\n attachments,\n setAttachments: (next) => {\n if (!isAttachmentsControlled) setAttachmentsUncontrolled(next);\n onAttachmentsChange?.(next);\n },\n isAttachmentsControlled,\n accept,\n multiple,\n maxAttachments,\n maxFileSize,\n paste,\n pasteAccept,\n clearOnSubmit,\n onAttachmentReject,\n dropzone,\n appendFiles,\n appendFilesFromPaste,\n }}\n >\n <Comp\n {...divProps}\n ref={(node: HTMLDivElement) => {\n if (typeof forwardedRef === 'function') forwardedRef(node);\n else if (forwardedRef)\n (forwardedRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n (rootRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n }}\n className={classNames('rt-ChatbarRoot', `rt-r-size-${size}`, className)}\n style={{ position: 'relative', width, maxWidth, ...style }}\n data-state={open ? 'open' : 'closed'}\n data-disabled={disabled ? '' : undefined}\n data-readonly={readOnly ? '' : undefined}\n data-drop-active={dropzone && isDragActive ? '' : undefined}\n aria-expanded={open}\n onBlurCapture={handleBlurCapture}\n >\n {dropzone && <input {...getInputProps()} />}\n <div {...(dropzone ? getRootProps() : {})} style={{ width: '100%', height: '100%' }}>\n <Card\n className=\"rt-ChatbarCard\"\n size={Math.min(3, Number(size) + 1).toString() as '1' | '2' | '3'}\n variant={variant as any}\n style={{ position: 'relative' }}\n >\n <div className=\"rt-ChatbarGrid\">{children}</div>\n {dropzone && isDragActive && (\n <div className=\"rt-ChatbarDropOverlay\">\n <div className=\"rt-ChatbarDropContent\">\n <Text color=\"gray\" size={size} weight=\"medium\">\n Drop files here to attach\n </Text>\n </div>\n </div>\n )}\n </Card>\n </div>\n </Comp>\n </ChatbarContext.Provider>\n );\n});\nRoot.displayName = 'Chatbar.Root';\n\n/**\n * Multi-line text input for Chatbar.\n * - Uses onChange to control value and avoid duplicate updates.\n * - Auto-resizes between minLines and maxLines.\n * - Expands on focus/overflow per `expandOn`.\n * - Paste-to-attach: when `paste` is enabled on Root, pasting files adds attachments.\n * - Provide `aria-label` or `aria-labelledby` for an accessible name.\n */\ninterface TextareaProps extends Omit<React.ComponentPropsWithoutRef<'textarea'>, 'size'> {\n asChild?: boolean;\n /**\n * Handler for paste events. This is forwarded to the underlying <textarea>.\n */\n onPaste?: React.ClipboardEventHandler<HTMLTextAreaElement>;\n /**\n * When true, pressing Enter submits via onSend (Shift+Enter inserts newline).\n * Defaults to false.\n */\n submitOnEnter?: boolean;\n}\n\n/**\n * Chatbar multi-line text input.\n *\n * Behavior\n * - Controls the Chatbar value via React onChange. We intentionally do not\n * update state in onInput to avoid duplicate updates per keystroke.\n * - Auto-resizes between minLines and maxLines using layout measurements.\n * - When expandOn is `overflow` or `both`, the Chatbar opens as soon as the\n * content exceeds the compact height.\n * - Height recalculations occur on change, paste, and whenever `value` or `open`\n * changes via an isomorphic layout effect to avoid SSR warnings.\n *\n * Accessibility\n * - Consumers should provide labeling via aria-label or aria-labelledby\n * on this component, as no implicit label is rendered.\n */\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>((props, forwardedRef) => {\n const {\n className,\n style,\n asChild,\n onFocus,\n onInput,\n onChange,\n onPaste,\n onKeyDown,\n submitOnEnter = false,\n rows,\n ...textareaProps\n } = props;\n const ctx = useChatbarContext();\n const {\n open,\n minLines,\n maxLines,\n expandOn,\n disabled,\n readOnly,\n setOpen,\n setValue,\n textareaRef,\n value,\n isValueControlled,\n sendMode,\n paste,\n appendFilesFromPaste,\n size,\n } = ctx;\n\n // Cached metrics to avoid repeated getComputedStyle calls\n const lineHeightRef = React.useRef<number>(0);\n const paddingRef = React.useRef<number>(0);\n const compactHeightRef = React.useRef<number>(0);\n\n const recomputeMetrics = React.useCallback(() => {\n const el = textareaRef.current;\n if (!el) return;\n const computedStyle = window.getComputedStyle(el);\n const lineHeight = parseFloat(computedStyle.lineHeight) || 20;\n const paddingTop = parseFloat(computedStyle.paddingTop) || 0;\n const paddingBottom = parseFloat(computedStyle.paddingBottom) || 0;\n lineHeightRef.current = lineHeight;\n paddingRef.current = paddingTop + paddingBottom;\n compactHeightRef.current = Math.ceil(1 * lineHeight) + paddingTop + paddingBottom;\n }, [textareaRef]);\n\n // Auto-resize logic - optimized for fixed widths\n const updateHeight = React.useCallback(\n (forceOpen?: boolean) => {\n const textarea = textareaRef.current;\n if (!textarea) return;\n\n textarea.style.height = 'auto';\n\n if (lineHeightRef.current === 0) {\n recomputeMetrics();\n }\n const lineHeight = lineHeightRef.current;\n const padding = paddingRef.current;\n\n const isOpen = forceOpen ?? open;\n const effectiveMinLines = isOpen ? minLines : 1;\n const effectiveMaxLines = isOpen ? maxLines : 1;\n\n const minHeight = Math.ceil(effectiveMinLines * lineHeight) + padding;\n const maxHeight = Math.ceil(effectiveMaxLines * lineHeight) + padding;\n\n const contentHeight = Math.max(textarea.scrollHeight, minHeight);\n const finalHeight = Math.min(contentHeight, maxHeight);\n\n textarea.style.height = `${finalHeight}px`;\n\n if (contentHeight > maxHeight) {\n textarea.style.overflowY = 'auto';\n textarea.style.maxHeight = `${maxHeight}px`;\n } else {\n textarea.style.overflowY = 'hidden';\n textarea.style.maxHeight = 'none';\n }\n },\n [open, minLines, maxLines, textareaRef, recomputeMetrics],\n );\n\n // Update height when value or open state changes\n useIsomorphicLayoutEffect(() => {\n updateHeight();\n }, [updateHeight, value, open]);\n\n // Recompute metrics on mount and when size changes may affect typography\n useIsomorphicLayoutEffect(() => {\n recomputeMetrics();\n updateHeight();\n }, [recomputeMetrics, updateHeight, size]);\n\n // Observe responsive changes that alter line-height\n React.useEffect(() => {\n const el = textareaRef.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n let prevLineHeight = lineHeightRef.current;\n const ro = new ResizeObserver(() => {\n const computedStyle = window.getComputedStyle(el);\n const lh = parseFloat(computedStyle.lineHeight) || 20;\n if (lh !== prevLineHeight) {\n prevLineHeight = lh;\n recomputeMetrics();\n requestAnimationFrame(() => updateHeight());\n }\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, [textareaRef, recomputeMetrics, updateHeight]);\n\n // Dev-only warning if no accessible name is provided\n React.useEffect(() => {\n if (process.env.NODE_ENV === 'production') return;\n const hasLabel =\n textareaProps['aria-label'] != null || textareaProps['aria-labelledby'] != null;\n if (!hasLabel) {\n // eslint-disable-next-line no-console\n console.warn(\n '[Chatbar.Textarea] Provide aria-label or aria-labelledby to ensure the control has an accessible name.',\n );\n }\n // warn only on mount\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Note: No MutationObserver is used because <textarea> value changes are not\n // reflected in DOM text nodes. Height updates are handled by effects and events.\n\n const handleFocus = React.useCallback<React.FocusEventHandler<HTMLTextAreaElement>>(\n (event) => {\n if (disabled || readOnly) return;\n if ((expandOn === 'focus' || expandOn === 'both') && !open) setOpen(true);\n onFocus?.(event);\n },\n [disabled, readOnly, expandOn, open, setOpen, onFocus],\n );\n\n const handleChange = React.useCallback<React.ChangeEventHandler<HTMLTextAreaElement>>(\n (event) => {\n const el = event.currentTarget;\n const nextValue = el.value;\n setValue(nextValue);\n\n if ((expandOn === 'overflow' || expandOn === 'both') && !open) {\n el.style.height = 'auto';\n\n if (compactHeightRef.current === 0) {\n recomputeMetrics();\n }\n const shouldExpand = el.scrollHeight > compactHeightRef.current + 1;\n if (shouldExpand) {\n setOpen(true);\n // Immediately size for open state to avoid 1-line + scrollbar flash\n updateHeight(true);\n requestAnimationFrame(() => updateHeight(true));\n }\n }\n\n // Always recalc after any input\n requestAnimationFrame(() => updateHeight());\n onChange?.(event);\n },\n [expandOn, open, setOpen, setValue, onChange, updateHeight, recomputeMetrics],\n );\n\n const handlePaste = React.useCallback<React.ClipboardEventHandler<HTMLTextAreaElement>>(\n (event) => {\n // Attach files from clipboard if enabled\n if (paste) {\n const items = Array.from(event.clipboardData?.items ?? []);\n const files = items\n .filter((i) => i.kind === 'file')\n .map((i) => i.getAsFile())\n .filter((f): f is File => !!f);\n if (files.length > 0) {\n appendFilesFromPaste(files);\n }\n }\n setTimeout(() => {\n // If pasting in compact mode, force sizing as open if content overflowed\n if (!open) {\n updateHeight(true);\n } else {\n updateHeight();\n }\n }, 0);\n onPaste?.(event);\n },\n [paste, open, updateHeight, onPaste, appendFilesFromPaste],\n );\n\n const handleKeyDown = React.useCallback<React.KeyboardEventHandler<HTMLTextAreaElement>>(\n (event) => {\n if (!submitOnEnter) {\n onKeyDown?.(event);\n return;\n }\n if (\n event.key === 'Enter' &&\n !event.shiftKey &&\n !event.altKey &&\n !event.ctrlKey &&\n !event.metaKey &&\n !event.nativeEvent.isComposing\n ) {\n if (disabled || readOnly) {\n onKeyDown?.(event);\n return;\n }\n if (sendMode === 'never') {\n onKeyDown?.(event);\n return;\n }\n const trimmed = value.trim();\n const hasContent = trimmed.length > 0 || ctx.attachments.length > 0;\n if (sendMode === 'whenDirty' && !hasContent) {\n onKeyDown?.(event);\n return;\n }\n event.preventDefault();\n ctx.onSubmit?.({ value, attachments: ctx.attachments });\n if (ctx.clearOnSubmit) {\n if (!isValueControlled) setValue('');\n ctx.setAttachments([]);\n }\n }\n onKeyDown?.(event);\n },\n [\n submitOnEnter,\n disabled,\n readOnly,\n sendMode,\n value,\n isValueControlled,\n setValue,\n ctx,\n onKeyDown,\n ],\n );\n\n const Comp = asChild ? Slot : ('textarea' as any);\n return (\n <div className={classNames('rt-ChatbarField', 'rt-ChatbarTextarea', className)}>\n <Comp\n {...textareaProps}\n ref={(node: HTMLTextAreaElement) => {\n if (typeof forwardedRef === 'function') forwardedRef(node);\n else if (forwardedRef)\n (forwardedRef as React.MutableRefObject<HTMLTextAreaElement | null>).current = node;\n (textareaRef as React.MutableRefObject<HTMLTextAreaElement | null>).current = node;\n }}\n className=\"rt-ChatbarInput\"\n value={value}\n onInput={onInput}\n onChange={handleChange}\n onFocus={handleFocus}\n onPaste={handlePaste}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n readOnly={readOnly}\n rows={open ? minLines : 1}\n spellCheck={textareaProps.spellCheck ?? true}\n autoCorrect={textareaProps.autoCorrect ?? 'on'}\n style={style}\n />\n </div>\n );\n});\nTextarea.displayName = 'Chatbar.Textarea';\n\ninterface InlineSlotProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'children'> {\n asChild?: boolean;\n children?: React.ReactNode;\n}\n\nconst InlineStart = React.forwardRef<HTMLDivElement, InlineSlotProps>((props, forwardedRef) => {\n const { children, asChild, style, className, ...divProps } = props;\n const ctx = useChatbarContext();\n if (ctx.open) return null;\n const Comp = asChild ? Slot : ('div' as any);\n return (\n <Comp\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarInlineStart', className)}\n style={style}\n >\n {children}\n </Comp>\n );\n});\nInlineStart.displayName = 'Chatbar.InlineStart';\n\nconst InlineEnd = React.forwardRef<HTMLDivElement, InlineSlotProps>((props, forwardedRef) => {\n const { children, asChild, style, className, ...divProps } = props;\n const ctx = useChatbarContext();\n if (ctx.open) return null;\n const Comp = asChild ? Slot : ('div' as any);\n return (\n <Comp\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarInlineEnd', className)}\n style={style}\n >\n {children}\n </Comp>\n );\n});\nInlineEnd.displayName = 'Chatbar.InlineEnd';\n\n/**\n * Renders a horizontally scrollable list of attachments above the inline row.\n * Hidden when empty unless `forceMount`. Override per-item with `renderAttachment`.\n */\ninterface AttachmentsRowProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'children'> {\n asChild?: boolean;\n forceMount?: boolean;\n /** If provided, custom-render a tile; otherwise default tile is used */\n renderAttachment?: (attachment: ChatbarAttachment) => React.ReactNode;\n}\n\nconst AttachmentsRow = React.forwardRef<HTMLDivElement, AttachmentsRowProps>(\n (props, forwardedRef) => {\n const { asChild, forceMount, renderAttachment, className, style, ...divProps } = props;\n const ctx = useChatbarContext();\n const hasItems = ctx.attachments.length > 0;\n if (!hasItems && !forceMount) return null;\n const Comp = asChild ? Slot : ('div' as any);\n return (\n <Comp\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarAttachmentsRow', className)}\n style={style}\n role=\"list\"\n aria-label={divProps['aria-label'] ?? 'Attachments'}\n >\n <ScrollArea className=\"rt-ChatbarScrollArea\" scrollbars=\"horizontal\" size=\"1\">\n <Flex align=\"center\" gap=\"2\" style={{ minWidth: 'fit-content' }}>\n {ctx.attachments.map((att) => (\n <Attachment key={att.id} attachment={att} asChild={!!renderAttachment}>\n {renderAttachment?.(att)}\n </Attachment>\n ))}\n </Flex>\n </ScrollArea>\n </Comp>\n );\n },\n);\nAttachmentsRow.displayName = 'Chatbar.AttachmentsRow';\n\n/** Default tile renderer for a single attachment. */\ninterface AttachmentProps extends React.ComponentPropsWithoutRef<'div'> {\n attachment: ChatbarAttachment;\n asChild?: boolean;\n}\n\nconst Attachment = React.forwardRef<HTMLDivElement, AttachmentProps>((props, forwardedRef) => {\n const { attachment, asChild, className, style, children, ...divProps } = props;\n const ctx = useChatbarContext();\n const Comp = asChild ? Slot : ('div' as any);\n const isImage = !!attachment.url && attachment.type.startsWith('image/');\n return (\n <Comp\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarAttachment', className)}\n style={style}\n role=\"listitem\"\n data-kind={isImage ? 'image' : 'file'}\n title={attachment.name}\n >\n {children ?? (\n <Card size={ctx.size} variant=\"soft\">\n <Flex align=\"center\" gap=\"3\" pr={!isImage ? '6' : undefined}>\n <div className=\"rt-ChatbarAttachmentPreview\" aria-hidden>\n {isImage ? (\n <img className=\"rt-ChatbarAttachmentImage\" src={attachment.url} alt=\"\" />\n ) : (\n <FileTextIcon />\n )}\n </div>\n {!isImage && (\n <Flex direction=\"column\" gap=\"0\" style={{ minWidth: 0 }}>\n <Text\n size={ctx.size}\n weight=\"medium\"\n style={{ whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}\n >\n {attachment.name}\n </Text>\n <Text size=\"1\" color=\"gray\">\n {Math.ceil(attachment.size / 1024)} KB\n </Text>\n </Flex>\n )}\n <IconButton\n className=\"rt-ChatbarAttachmentRemove\"\n aria-label={`Remove ${attachment.name}`}\n size=\"1\"\n // size={ctx.size}\n variant=\"classic\"\n highContrast\n color=\"gray\"\n onClick={() =>\n ctx.setAttachments(ctx.attachments.filter((a) => a.id !== attachment.id))\n }\n >\n <CloseIcon />\n </IconButton>\n </Flex>\n </Card>\n )}\n </Comp>\n );\n});\nAttachment.displayName = 'Chatbar.Attachment';\n\ninterface AttachTriggerProps extends React.ComponentPropsWithoutRef<'button'> {\n asChild?: boolean;\n accept?: string | string[];\n multiple?: boolean;\n}\n\nconst AttachTrigger = React.forwardRef<HTMLButtonElement, AttachTriggerProps>(\n (props, forwardedRef) => {\n const { asChild, accept, multiple, className, style, ...buttonProps } = props;\n const ctx = useChatbarContext();\n const inputRef = React.useRef<HTMLInputElement | null>(null);\n const Comp = asChild ? Slot : ('button' as any);\n const actualAccept = (Array.isArray(accept) ? accept : (accept?.split(',') ?? [])).join(',');\n return (\n <>\n <Comp\n {...(buttonProps as any)}\n ref={forwardedRef as any}\n className={classNames('rt-ChatbarAttachTrigger', className)}\n style={style}\n type={buttonProps.type ?? 'button'}\n aria-label={buttonProps['aria-label'] ?? 'Add attachments'}\n onClick={(e: any) => {\n // Ensure file input opens reliably by clicking it first\n if (inputRef.current) {\n inputRef.current.click();\n }\n // Then call user's onClick if provided\n buttonProps.onClick?.(e);\n }}\n />\n <input\n ref={inputRef}\n type=\"file\"\n accept={actualAccept}\n multiple={multiple ?? ctx.multiple}\n tabIndex={-1}\n style={{ display: 'none' }}\n onChange={(e) => {\n const files = Array.from(e.currentTarget.files ?? []);\n if (files.length > 0) {\n ctx.appendFiles(files);\n }\n // Reset input value to allow selecting the same file again\n e.currentTarget.value = '';\n }}\n />\n </>\n );\n },\n);\nAttachTrigger.displayName = 'Chatbar.AttachTrigger';\ninterface RowProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'children'> {\n asChild?: boolean;\n children?: React.ReactNode;\n}\n\nconst Row = React.forwardRef<HTMLDivElement, RowProps>((props, forwardedRef) => {\n const { asChild, children, className, style, ...divProps } = props;\n const ctx = useChatbarContext();\n if (!ctx.open) return null;\n const Comp = asChild ? Slot : ('div' as any);\n return (\n <Comp\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarRow', className)}\n style={style}\n >\n <Flex align=\"center\" justify=\"between\" width=\"100%\">\n {children}\n </Flex>\n </Comp>\n );\n});\nRow.displayName = 'Chatbar.Row';\n\nconst RowStart = React.forwardRef<HTMLDivElement, React.ComponentPropsWithoutRef<'div'>>(\n (props, forwardedRef) => {\n const { className, style, ...divProps } = props;\n return (\n <div\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarRowStart', className)}\n style={style}\n />\n );\n },\n);\nRowStart.displayName = 'Chatbar.RowStart';\n\nconst RowEnd = React.forwardRef<HTMLDivElement, React.ComponentPropsWithoutRef<'div'>>(\n (props, forwardedRef) => {\n const { className, style, ...divProps } = props;\n return (\n <div\n {...divProps}\n ref={forwardedRef}\n className={classNames('rt-ChatbarRowEnd', className)}\n style={style}\n />\n );\n },\n);\nRowEnd.displayName = 'Chatbar.RowEnd';\n\ninterface SendProps extends Omit<IconButtonProps, 'size'> {\n asChild?: boolean;\n clearOnSend?: boolean;\n}\n\nconst Send = React.forwardRef<HTMLButtonElement, SendProps>((props, forwardedRef) => {\n const {\n asChild,\n clearOnSend = true,\n disabled,\n children,\n className,\n style,\n ...buttonProps\n } = props;\n const ctx = useChatbarContext();\n\n const trimmed = ctx.value.trim();\n const hasContent = trimmed.length > 0 || ctx.attachments.length > 0;\n const visible = ctx.sendMode === 'always' || (ctx.sendMode === 'whenDirty' && hasContent);\n if (ctx.sendMode === 'never') return null;\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n if (ctx.disabled || ctx.readOnly) return;\n ctx.onSubmit?.({ value: ctx.value, attachments: ctx.attachments });\n if (clearOnSend) {\n if (!ctx.isValueControlled) ctx.setValue('');\n if (ctx.clearOnSubmit) ctx.setAttachments([]);\n }\n buttonProps.onClick?.(event);\n };\n\n return (\n <IconButton\n {...(buttonProps as any)}\n ref={forwardedRef as any}\n size={ctx.size}\n variant={ctx.open ? 'solid' : 'ghost'}\n disabled={disabled || ctx.disabled || ctx.readOnly}\n className={classNames('rt-ChatbarSend', className)}\n style={{\n opacity: visible ? 1 : 0,\n pointerEvents: visible ? 'auto' : 'none',\n ...style,\n }}\n asChild={asChild}\n onClick={handleClick}\n aria-label={buttonProps['aria-label'] ?? 'Send'}\n >\n {children ?? 'Send'}\n </IconButton>\n );\n});\nSend.displayName = 'Chatbar.Send';\n\nexport {\n Root,\n Textarea,\n InlineStart,\n InlineEnd,\n AttachmentsRow,\n Attachment,\n AttachTrigger,\n Row,\n RowStart,\n RowEnd,\n Send,\n};\nexport type {\n RootProps as ChatbarRootProps,\n TextareaProps as ChatbarTextareaProps,\n RowProps as ChatbarRowProps,\n SendProps as ChatbarSendProps,\n ChatbarAttachment,\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["React", "classNames", "IconButton", "CloseIcon", "FileTextIcon", "Flex", "ScrollArea", "Slot", "Card", "Text", "useDropzone", "useIsomorphicLayoutEffect", "ChatbarContext", "useChatbarContext", "ctx", "Root", "props", "forwardedRef", "className", "style", "children", "valueProp", "defaultValue", "onValueChangeProp", "openProp", "defaultOpen", "onOpenChangeProp", "expandOn", "minLines", "maxLines", "sendMode", "disabled", "readOnly", "onSubmit", "size", "variant", "width", "maxWidth", "asChild", "attachmentsProp", "defaultAttachments", "onAttachmentsChange", "accept", "multiple", "maxAttachments", "maxFileSize", "paste", "pasteAccept", "clearOnSubmit", "onAttachmentReject", "dropzone", "divProps", "isValueControlled", "valueUncontrolled", "setValueUncontrolled", "value", "isOpenControlled", "openUncontrolled", "setOpenUncontrolled", "open", "rootRef", "textareaRef", "isAttachmentsControlled", "attachmentsUncontrolled", "setAttachmentsUncontrolled", "attachments", "generatedUrlSetRef", "toArray", "val", "s", "accepts", "pasteAccepts", "matchesAccept", "file", "patterns", "mime", "name", "patRaw", "pat", "type", "subtype", "fmType", "fmSubtype", "mapFilesToAttachments", "files", "next", "rejected", "remainingSlots", "id", "looksLikeImageByExt", "url", "appendFiles", "accepted", "merged", "appendFilesFromPaste", "matches", "acceptedFiles", "currentUrls", "a", "Comp", "handleBlurCapture", "event", "nextTarget", "rootEl", "getRootProps", "getInputProps", "isDragActive", "rejectedFiles", "rejections", "errors", "reason", "acc", "pattern", "node", "Textarea", "onFocus", "onInput", "onChange", "onPaste", "onKeyDown", "submitOnEnter", "rows", "textareaProps", "setOpen", "setValue", "lineHeightRef", "paddingRef", "compactHeightRef", "recomputeMetrics", "el", "computedStyle", "lineHeight", "paddingTop", "paddingBottom", "updateHeight", "forceOpen", "textarea", "padding", "isOpen", "effectiveMinLines", "effectiveMaxLines", "minHeight", "maxHeight", "contentHeight", "finalHeight", "prevLineHeight", "ro", "lh", "handleFocus", "handleChange", "nextValue", "handlePaste", "i", "f", "handleKeyDown", "hasContent", "InlineStart", "InlineEnd", "AttachmentsRow", "forceMount", "renderAttachment", "att", "Attachment", "attachment", "isImage", "AttachTrigger", "buttonProps", "inputRef", "actualAccept", "e", "Row", "RowStart", "RowEnd", "Send", "clearOnSend", "visible", "handleClick"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kushagradhawan/kookie-ui",
3
- "version": "0.1.34",
3
+ "version": "0.1.35",
4
4
  "description": "A modern React component library with beautiful design tokens, flexible theming, and comprehensive docs",
5
5
  "keywords": [
6
6
  "react",
@@ -24,6 +24,7 @@ type SendMode = 'always' | 'whenDirty' | 'never';
24
24
  type AttachmentStatus = 'idle' | 'uploading' | 'error' | 'done';
25
25
  /**
26
26
  * Attachment data model used by Chatbar.
27
+ * - `file` exposes the original File object for uploads and processing.
27
28
  * - `url` is an object URL used for image previews and is revoked on removal.
28
29
  */
29
30
  interface ChatbarAttachment {
@@ -31,6 +32,8 @@ interface ChatbarAttachment {
31
32
  name: string;
32
33
  size: number;
33
34
  type: string;
35
+ /** Original File object for uploads and processing */
36
+ file: File;
34
37
  url?: string;
35
38
  status?: AttachmentStatus;
36
39
  progress?: number;
@@ -320,7 +323,15 @@ const Root = React.forwardRef<RootElement, RootProps>((props, forwardedRef) => {
320
323
  const isImageType = (file.type || '').toLowerCase().startsWith('image/');
321
324
  const url = isImageType || looksLikeImageByExt ? URL.createObjectURL(file) : undefined;
322
325
  if (url) generatedUrlSetRef.current.add(url);
323
- next.push({ id, name: file.name, size: file.size, type: file.type, url, status: 'idle' });
326
+ next.push({
327
+ id,
328
+ name: file.name,
329
+ size: file.size,
330
+ type: file.type,
331
+ file,
332
+ url,
333
+ status: 'idle',
334
+ });
324
335
  }
325
336
  return { accepted: next, rejected };
326
337
  };
@@ -793,7 +804,8 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>((props, fo
793
804
  return;
794
805
  }
795
806
  const trimmed = value.trim();
796
- if (sendMode === 'whenDirty' && trimmed.length === 0) {
807
+ const hasContent = trimmed.length > 0 || ctx.attachments.length > 0;
808
+ if (sendMode === 'whenDirty' && !hasContent) {
797
809
  onKeyDown?.(event);
798
810
  return;
799
811
  }
@@ -1124,7 +1136,8 @@ const Send = React.forwardRef<HTMLButtonElement, SendProps>((props, forwardedRef
1124
1136
  const ctx = useChatbarContext();
1125
1137
 
1126
1138
  const trimmed = ctx.value.trim();
1127
- const visible = ctx.sendMode === 'always' || (ctx.sendMode === 'whenDirty' && trimmed.length > 0);
1139
+ const hasContent = trimmed.length > 0 || ctx.attachments.length > 0;
1140
+ const visible = ctx.sendMode === 'always' || (ctx.sendMode === 'whenDirty' && hasContent);
1128
1141
  if (ctx.sendMode === 'never') return null;
1129
1142
 
1130
1143
  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
@@ -1178,4 +1191,5 @@ export type {
1178
1191
  TextareaProps as ChatbarTextareaProps,
1179
1192
  RowProps as ChatbarRowProps,
1180
1193
  SendProps as ChatbarSendProps,
1194
+ ChatbarAttachment,
1181
1195
  };