@kushagradhawan/kookie-ui 0.1.69 → 0.1.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/chatbar.d.ts +2 -2
- package/dist/cjs/components/chatbar.d.ts.map +1 -1
- package/dist/cjs/components/chatbar.js +1 -1
- package/dist/cjs/components/chatbar.js.map +3 -3
- package/dist/esm/components/chatbar.d.ts +2 -2
- package/dist/esm/components/chatbar.d.ts.map +1 -1
- package/dist/esm/components/chatbar.js +1 -1
- package/dist/esm/components/chatbar.js.map +3 -3
- package/package.json +1 -1
- package/schemas/base-button.json +1 -1
- package/schemas/button.json +1 -1
- package/schemas/icon-button.json +1 -1
- package/schemas/index.json +6 -6
- package/schemas/toggle-button.json +1 -1
- package/schemas/toggle-icon-button.json +1 -1
- package/src/components/chatbar.tsx +6 -6
|
@@ -214,10 +214,10 @@ interface RowProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'children
|
|
|
214
214
|
declare const Row: React.ForwardRefExoticComponent<RowProps & React.RefAttributes<HTMLDivElement>>;
|
|
215
215
|
declare const RowStart: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
216
216
|
declare const RowEnd: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
217
|
-
|
|
217
|
+
type SendProps = IconButtonProps & {
|
|
218
218
|
asChild?: boolean;
|
|
219
219
|
clearOnSend?: boolean;
|
|
220
|
-
}
|
|
220
|
+
};
|
|
221
221
|
declare const Send: React.ForwardRefExoticComponent<SendProps & React.RefAttributes<HTMLButtonElement>>;
|
|
222
222
|
export { Root, Textarea, InlineStart, InlineEnd, AttachmentsRow, Attachment, AttachTrigger, Row, RowStart, RowEnd, Send };
|
|
223
223
|
export type { RootProps as ChatbarRootProps, TextareaProps as ChatbarTextareaProps, RowProps as ChatbarRowProps, SendProps as ChatbarSendProps, ChatbarAttachment };
|
|
@@ -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 nt=Object.create;var ue=Object.defineProperty;var at=Object.getOwnPropertyDescriptor;var ot=Object.getOwnPropertyNames;var rt=Object.getPrototypeOf,st=Object.prototype.hasOwnProperty;var it=(a,o)=>{for(var r in o)ue(a,r,{get:o[r],enumerable:!0})},Ve=(a,o,r,u)=>{if(o&&typeof o=="object"||typeof o=="function")for(let c of ot(o))!st.call(a,c)&&c!==r&&ue(a,c,{get:()=>o[c],enumerable:!(u=at(o,c))||u.enumerable});return a};var Ue=(a,o,r)=>(r=a!=null?nt(rt(a)):{},Ve(o||!a||!a.__esModule?ue(r,"default",{value:a,enumerable:!0}):r,a)),lt=a=>Ve(ue({},"__esModule",{value:!0}),a);var ct={};it(ct,{AttachTrigger:()=>Le,Attachment:()=>me,AttachmentsRow:()=>Me,InlineEnd:()=>Oe,InlineStart:()=>Se,Root:()=>Ee,Row:()=>Fe,RowEnd:()=>Ne,RowStart:()=>He,Send:()=>De,Textarea:()=>Te});module.exports=lt(ct);var e=Ue(require("react")),T=Ue(require("classnames")),Pe=require("./icon-button.js"),pe=require("./icons.js"),oe=require("./flex.js"),$e=require("./scroll-area.js"),D=require("./slot.js"),qe=require("./box.js"),de=require("./text.js"),Ye=require("react-dropzone");const we=typeof window<"u"?e.useLayoutEffect:e.useEffect,Ke=e.createContext(null),W=()=>{const a=e.useContext(Ke);if(!a)throw new Error("Chatbar context not found. Wrap parts in <Chatbar.Root>.");return a},Ee=e.forwardRef((a,o)=>{const{className:r,style:u,children:c,value:b,defaultValue:A="",onValueChange:h,open:l,defaultOpen:i=!1,onOpenChange:R,expandOn:P="both",minLines:S=1,maxLines:m=6,sendMode:C="whenDirty",disabled:F,readOnly:Y,onSubmit:O,size:H="2",variant:V,color:N,radius:U,panelBackground:M,material:z,width:re,maxWidth:G,asChild:se,attachments:_,defaultAttachments:he=[],onAttachmentsChange:K,accept:J,multiple:k=!0,maxAttachments:w,maxFileSize:p,paste:fe=!0,pasteAccept:Q,clearOnSubmit:be=!0,onAttachmentReject:$,dropzone:I=!0,apiRef:n,...d}=a,f=z||M,v=b!=null,[L,Ce]=e.useState(A),X=v?b:L,j=l!=null,[Z,q]=e.useState(i),ee=j?l:Z,ge=e.useRef(null),ie=e.useRef(null),ye=e.useRef(!1),te="attachments"in a,[ze,ke]=e.useState(he),B=e.useMemo(()=>te?_??[]:ze,[te,_,ze]),le=e.useRef(new Set),ve=t=>Array.isArray(t)?t:typeof t=="string"?t.split(",").map(s=>s.trim()):[],ne=ve(J),Ie=ve(Q).length>0?ve(Q):ne,xe=(t,s)=>{if(s.length===0)return!0;const g=t.type.toLowerCase(),E=t.name.toLowerCase();for(const y of s){const x=y.toLowerCase();if(x.includes("/")){const[ce,Re]=x.split("/"),[ae,tt]=g.split("/");if(ce==="*"||ce===ae&&(Re==="*"||Re===tt))return!0}else if(x.startsWith(".")&&E.endsWith(x))return!0}return!1},Ge=t=>{const s=[],g=[],E=typeof w=="number"?Math.max(w-B.length,0):1/0;for(const y of t){if(s.length>=E){g.push({file:y,reason:"count"});continue}if(typeof p=="number"&&y.size>p){g.push({file:y,reason:"size"});continue}if(!xe(y,ne)){g.push({file:y,reason:"type"});continue}const x=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,ce=/\.(png|jpe?g|gif|webp|bmp|svg)$/i.test(y.name),ae=(y.type||"").toLowerCase().startsWith("image/")||ce?URL.createObjectURL(y):void 0;ae&&le.current.add(ae),s.push({id:x,name:y.name,size:y.size,type:y.type,file:y,url:ae,status:"idle"})}return{accepted:s,rejected:g}},Ae=t=>{const{accepted:s,rejected:g}=Ge(t);if(s.length>0){const E=B.concat(s);te||ke(E),K?.(E),j||q(!0),R?.(!0)}g.length>0&&$?.(g)},_e=t=>{const s=x=>Ie.length===0?xe(x,ne):xe(x,Ie),g=[],E=[],y=typeof w=="number"?Math.max(w-B.length,0):1/0;for(const x of t){if(g.length>=y){E.push({file:x,reason:"count"});continue}if(typeof p=="number"&&x.size>p){E.push({file:x,reason:"size"});continue}if(!s(x)){E.push({file:x,reason:"type"});continue}g.push(x)}g.length>0&&Ae(g),E.length>0&&$?.(E)};e.useEffect(()=>{const t=new Set(B.map(s=>s.url).filter(Boolean));for(const s of Array.from(le.current))t.has(s)||(URL.revokeObjectURL(s),le.current.delete(s))},[B]),e.useEffect(()=>{const t=le.current;return()=>{for(const s of Array.from(t))URL.revokeObjectURL(s);t.clear()}},[]);const Je=se?D.Slot:"div",Qe=e.useCallback(t=>{const s=t.relatedTarget,g=ge.current;g&&(s&&g.contains(s)||ye.current||(X?.trim?.()??"").length===0&&B.length===0&&(j||q(!1),R?.(!1)))},[j,R,X,B]),{getRootProps:Xe,getInputProps:Ze,isDragActive:je,open:Be}=(0,Ye.useDropzone)({onDrop:(t,s)=>{if(t.length>0&&Ae(t),s.length>0&&$){const g=s.map(({file:E,errors:y})=>{const x=y[0]?.code==="file-too-large"?"size":y[0]?.code==="file-invalid-type"?"type":"count";return{file:E,reason:x}});$(g)}},accept:ne.length>0?ne.reduce((t,s)=>(s.includes("/")?t[s]=[]:s.startsWith(".")&&(t[s]=[]),t),{}):void 0,multiple:k,maxSize:p,noClick:!0,noKeyboard:!0,disabled:!I||F});e.useImperativeHandle(n,()=>({focusTextarea:()=>ie.current?.focus({preventScroll:!0}),openFilePicker:()=>{ye.current=!0,Be()}}),[Be]);const We=e.useCallback(t=>{if(!(t instanceof Element))return!1;const s=t;return s.closest(".rt-ChatbarDropOverlay")?!0:!!s.closest('button, [role="button"], a[href], input, textarea, select, [contenteditable], [tabindex]:not([tabindex="-1"])')},[]),et=e.useCallback(t=>{F||We(t.target)||t.pointerType==="mouse"&&t.button!==0||(t.preventDefault(),ie.current?.focus({preventScroll:!0}))},[F,We,ie]);return e.createElement(Ke.Provider,{value:{open:ee,setOpen:t=>{j||q(t),R?.(t)},isOpenControlled:j,value:X,setValue:t=>{v||Ce(t),h?.(t)},isValueControlled:v,size:H,expandOn:P,minLines:S,maxLines:m,sendMode:C,disabled:F,readOnly:Y,onSubmit:O,rootRef:ge,textareaRef:ie,attachments:B,setAttachments:t=>{te||ke(t),K?.(t)},isAttachmentsControlled:te,accept:J,multiple:k,maxAttachments:w,maxFileSize:p,paste:fe,pasteAccept:Q,clearOnSubmit:be,onAttachmentReject:$,dropzone:I,appendFiles:Ae,appendFilesFromPaste:_e,fileDialogOpenRef:ye}},e.createElement(Je,{...d,ref:t=>{typeof o=="function"?o(t):o&&(o.current=t),ge.current=t},className:(0,T.default)("rt-ChatbarRoot",`rt-r-size-${H}`,r),style:{position:"relative",width:re,maxWidth:G,...u},"data-state":ee?"open":"closed","data-disabled":F?"":void 0,"data-readonly":Y?"":void 0,"data-drop-active":I&&je?"":void 0,"data-accent-color":N,"data-radius":U,"data-panel-background":f,"data-material":f,"aria-expanded":ee,onBlurCapture:Qe},I&&e.createElement("input",{...Ze()}),e.createElement("div",{...I?Xe():{},style:{width:"100%",height:"100%"},onPointerDown:et},e.createElement(qe.Box,{className:(0,T.default)("rt-ChatbarBox",`rt-variant-${V??"surface"}`),style:{position:"relative"},"data-accent-color":N,"data-radius":U,"data-panel-background":f,"data-material":f},e.createElement("div",{className:"rt-ChatbarGrid"},c),I&&je&&e.createElement("div",{className:"rt-ChatbarDropOverlay"},e.createElement("div",{className:"rt-ChatbarDropContent"},e.createElement(de.Text,{color:"gray",size:H,weight:"medium"},"Drop files here to attach")))))))});Ee.displayName="Chatbar.Root";const Te=e.forwardRef((a,o)=>{const{className:r,style:u,asChild:c,onFocus:b,onInput:A,onChange:h,onPaste:l,onKeyDown:i,submitOnEnter:R=!1,rows:P,...S}=a,m=W(),{open:C,minLines:F,maxLines:Y,expandOn:O,disabled:H,readOnly:V,setOpen:N,setValue:U,textareaRef:M,value:z,isValueControlled:re,sendMode:G,paste:se,appendFilesFromPaste:_,size:he}=m,K=e.useRef(0),J=e.useRef(0),k=e.useRef(0),w=e.useCallback(()=>{const n=M.current;if(!n)return;const d=window.getComputedStyle(n),f=parseFloat(d.lineHeight)||20,v=parseFloat(d.paddingTop)||0,L=parseFloat(d.paddingBottom)||0;K.current=f,J.current=v+L,k.current=Math.ceil(1*f)+v+L},[M]),p=e.useCallback(n=>{const d=M.current;if(!d)return;d.style.height="auto",K.current===0&&w();const f=K.current,v=J.current,L=n??C,Ce=L?F:1,X=L?Y:1,j=Math.ceil(Ce*f)+v,Z=Math.ceil(X*f)+v,q=Math.max(d.scrollHeight,j),ee=Math.min(q,Z);d.style.height=`${ee}px`,q>Z?(d.style.overflowY="auto",d.style.maxHeight=`${Z}px`):(d.style.overflowY="hidden",d.style.maxHeight="none")},[C,F,Y,M,w]);we(()=>{p()},[p,z,C]),we(()=>{if(!(O==="overflow"||O==="both")||C)return;const n=M.current;if(!n)return;n.style.height="auto",k.current===0&&w(),n.scrollHeight>k.current+1&&(N(!0),p(!0),requestAnimationFrame(()=>p(!0)))},[z,O,C,N,M,w,p]),we(()=>{w(),p()},[w,p,he]),e.useEffect(()=>{const n=M.current;if(!n||typeof ResizeObserver>"u")return;let d=K.current;const f=new ResizeObserver(()=>{const v=window.getComputedStyle(n),L=parseFloat(v.lineHeight)||20;L!==d&&(d=L,w(),requestAnimationFrame(()=>p()))});return f.observe(n),()=>f.disconnect()},[M,w,p]),e.useEffect(()=>{},[]);const fe=e.useCallback(n=>{H||V||((O==="focus"||O==="both")&&!C&&N(!0),b?.(n))},[H,V,O,C,N,b]),Q=e.useCallback(n=>{const d=n.currentTarget,f=d.value;U(f),(O==="overflow"||O==="both")&&!C&&(d.style.height="auto",k.current===0&&w(),d.scrollHeight>k.current+1&&(N(!0),p(!0),requestAnimationFrame(()=>p(!0)))),requestAnimationFrame(()=>p()),h?.(n)},[O,C,N,U,h,p,w]),be=e.useCallback(n=>{if(se){const f=Array.from(n.clipboardData?.items??[]).filter(v=>v.kind==="file").map(v=>v.getAsFile()).filter(v=>!!v);f.length>0&&(n.preventDefault(),_(f))}setTimeout(()=>{C?p():p(!0)},0),l?.(n)},[se,C,p,l,_]),$=e.useCallback(n=>{if(!R){i?.(n);return}if(n.key==="Enter"&&!n.shiftKey&&!n.altKey&&!n.ctrlKey&&!n.metaKey&&!n.nativeEvent.isComposing){if(H||V){i?.(n);return}if(G==="never"){i?.(n);return}const f=z.trim().length>0||m.attachments.length>0;if(G==="whenDirty"&&!f){i?.(n);return}n.preventDefault(),m.onSubmit?.({value:z,attachments:m.attachments}),m.clearOnSubmit&&(re||U(""),m.setAttachments([]))}i?.(n)},[R,H,V,G,z,re,U,m,i]),I=c?D.Slot:"textarea";return e.createElement("div",{className:(0,T.default)("rt-ChatbarField","rt-ChatbarTextarea",r)},e.createElement(I,{...S,ref:n=>{typeof o=="function"?o(n):o&&(o.current=n),M.current=n},className:"rt-ChatbarInput",value:z,onInput:A,onChange:Q,onFocus:fe,onPaste:be,onKeyDown:$,disabled:H,readOnly:V,rows:C?F:1,spellCheck:S.spellCheck??!0,autoCorrect:S.autoCorrect??"on",style:u}))});Te.displayName="Chatbar.Textarea";const Se=e.forwardRef((a,o)=>{const{children:r,asChild:u,style:c,className:b,...A}=a;return W().open?null:e.createElement(u?D.Slot:"div",{...A,ref:o,className:(0,T.default)("rt-ChatbarInlineStart",b),style:c},r)});Se.displayName="Chatbar.InlineStart";const Oe=e.forwardRef((a,o)=>{const{children:r,asChild:u,style:c,className:b,...A}=a;return W().open?null:e.createElement(u?D.Slot:"div",{...A,ref:o,className:(0,T.default)("rt-ChatbarInlineEnd",b),style:c},r)});Oe.displayName="Chatbar.InlineEnd";const Me=e.forwardRef((a,o)=>{const{asChild:r,forceMount:u,renderAttachment:c,className:b,style:A,...h}=a,l=W();return!(l.attachments.length>0)&&!u?null:e.createElement(r?D.Slot:"div",{...h,ref:o,className:(0,T.default)("rt-ChatbarAttachmentsRow",b),style:A,role:"list","aria-label":h["aria-label"]??"Attachments"},e.createElement($e.ScrollArea,{className:"rt-ChatbarScrollArea",scrollbars:"horizontal",size:"1"},e.createElement(oe.Flex,{align:"center",gap:"2",style:{minWidth:"fit-content"}},l.attachments.map(P=>e.createElement(me,{key:P.id,attachment:P,asChild:!!c},c?.(P))))))});Me.displayName="Chatbar.AttachmentsRow";const me=e.forwardRef((a,o)=>{const{attachment:r,asChild:u,className:c,style:b,children:A,...h}=a,l=W(),i=u?D.Slot:"div",R=!!r.url&&r.type.startsWith("image/");return e.createElement(i,{...h,ref:o,className:(0,T.default)("rt-ChatbarAttachment",c),style:b,role:"listitem","data-kind":R?"image":"file",title:r.name},A??e.createElement(oe.Flex,{align:"center",gap:"2",pr:R?void 0:"6"},e.createElement("div",{className:"rt-ChatbarAttachmentPreview","aria-hidden":!0},R?e.createElement("img",{className:"rt-ChatbarAttachmentImage",src:r.url,alt:""}):e.createElement(pe.FileTextIcon,null)),!R&&e.createElement(oe.Flex,{direction:"column",gap:"0",style:{minWidth:0}},e.createElement(de.Text,{size:l.size,weight:"medium",style:{whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"}},r.name),e.createElement(de.Text,{size:"1",color:"gray"},Math.ceil(r.size/1024)," KB")),e.createElement(Pe.IconButton,{className:"rt-ChatbarAttachmentRemove","aria-label":`Remove ${r.name}`,size:"1",variant:"classic",highContrast:!0,color:"gray",onClick:()=>l.setAttachments(l.attachments.filter(P=>P.id!==r.id))},e.createElement(pe.CloseIcon,null))))});me.displayName="Chatbar.Attachment";const Le=e.forwardRef((a,o)=>{const{asChild:r,accept:u,multiple:c,className:b,style:A,...h}=a,l=W(),i=e.useRef(null),R=r?D.Slot:"button",P=u??l.accept,S=(Array.isArray(P)?P:P?.split(",")??[]).join(",");return e.useEffect(()=>{const m=()=>{l.fileDialogOpenRef.current=!1};return window.addEventListener("focus",m),()=>window.removeEventListener("focus",m)},[l.fileDialogOpenRef]),e.createElement(e.Fragment,null,e.createElement(R,{...h,ref:o,className:(0,T.default)("rt-ChatbarAttachTrigger",b),style:A,type:h.type??"button","aria-label":h["aria-label"]??"Add attachments",onPointerDown:m=>{l.fileDialogOpenRef.current=!0,h.onPointerDown?.(m)},onMouseDown:m=>{l.fileDialogOpenRef.current=!0,h.onMouseDown?.(m)},onClick:m=>{l.fileDialogOpenRef.current=!0,i.current&&i.current.click(),h.onClick?.(m)}}),e.createElement("input",{ref:i,type:"file",accept:S,multiple:c??l.multiple,tabIndex:-1,style:{display:"none"},onChange:m=>{const C=Array.from(m.currentTarget.files??[]);C.length>0&&l.appendFiles(C),l.fileDialogOpenRef.current=!1,m.currentTarget.value=""}}))});Le.displayName="Chatbar.AttachTrigger";const Fe=e.forwardRef((a,o)=>{const{asChild:r,children:u,className:c,style:b,...A}=a;return W().open?e.createElement(r?D.Slot:"div",{...A,ref:o,className:(0,T.default)("rt-ChatbarRow",c),style:b},e.createElement(oe.Flex,{align:"center",justify:"between",width:"100%"},u)):null});Fe.displayName="Chatbar.Row";const He=e.forwardRef((a,o)=>{const{className:r,style:u,...c}=a;return e.createElement("div",{...c,ref:o,className:(0,T.default)("rt-ChatbarRowStart",r),style:u})});He.displayName="Chatbar.RowStart";const Ne=e.forwardRef((a,o)=>{const{className:r,style:u,...c}=a;return e.createElement("div",{...c,ref:o,className:(0,T.default)("rt-ChatbarRowEnd",r),style:u})});Ne.displayName="Chatbar.RowEnd";const De=e.forwardRef((a,o)=>{const{asChild:r,clearOnSend:u=!0,disabled:c,children:b,className:A,style:h,...l}=a,i=W(),P=i.value.trim().length>0||i.attachments.length>0,S=i.sendMode==="always"||i.sendMode==="whenDirty"&&P;if(i.sendMode==="never")return null;const m=C=>{i.disabled||i.readOnly||(i.onSubmit?.({value:i.value,attachments:i.attachments}),u&&(i.isValueControlled||i.setValue(""),i.clearOnSubmit&&i.setAttachments([])),l.onClick?.(C))};return e.createElement(Pe.IconButton,{...l,ref:o,size:i.size,variant:i.open?"solid":"ghost",disabled:c||i.disabled||i.readOnly,className:(0,T.default)("rt-ChatbarSend",A),style:{opacity:S?1:0,pointerEvents:S?"auto":"none",...h},asChild:r,onClick:m,"aria-label":l["aria-label"]??"Send"},b??e.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"lucide lucide-arrow-right-icon lucide-arrow-right"},e.createElement("path",{d:"M5 12h14"}),e.createElement("path",{d:"m12 5 7 7-7 7"})))});De.displayName="Chatbar.Send";
|
|
1
|
+
"use strict";var nt=Object.create;var ue=Object.defineProperty;var at=Object.getOwnPropertyDescriptor;var ot=Object.getOwnPropertyNames;var rt=Object.getPrototypeOf,st=Object.prototype.hasOwnProperty;var it=(a,o)=>{for(var r in o)ue(a,r,{get:o[r],enumerable:!0})},Ve=(a,o,r,u)=>{if(o&&typeof o=="object"||typeof o=="function")for(let l of ot(o))!st.call(a,l)&&l!==r&&ue(a,l,{get:()=>o[l],enumerable:!(u=at(o,l))||u.enumerable});return a};var Ue=(a,o,r)=>(r=a!=null?nt(rt(a)):{},Ve(o||!a||!a.__esModule?ue(r,"default",{value:a,enumerable:!0}):r,a)),lt=a=>Ve(ue({},"__esModule",{value:!0}),a);var ct={};it(ct,{AttachTrigger:()=>Le,Attachment:()=>me,AttachmentsRow:()=>Me,InlineEnd:()=>Oe,InlineStart:()=>Se,Root:()=>Ee,Row:()=>Fe,RowEnd:()=>Ne,RowStart:()=>He,Send:()=>De,Textarea:()=>Te});module.exports=lt(ct);var e=Ue(require("react")),T=Ue(require("classnames")),Pe=require("./icon-button.js"),pe=require("./icons.js"),oe=require("./flex.js"),$e=require("./scroll-area.js"),D=require("./slot.js"),qe=require("./box.js"),de=require("./text.js"),Ye=require("react-dropzone");const we=typeof window<"u"?e.useLayoutEffect:e.useEffect,Ke=e.createContext(null),W=()=>{const a=e.useContext(Ke);if(!a)throw new Error("Chatbar context not found. Wrap parts in <Chatbar.Root>.");return a},Ee=e.forwardRef((a,o)=>{const{className:r,style:u,children:l,value:C,defaultValue:R="",onValueChange:h,open:c,defaultOpen:w=!1,onOpenChange:g,expandOn:i="both",minLines:L=1,maxLines:m=6,sendMode:f="whenDirty",disabled:S,readOnly:V,onSubmit:O,size:H="2",variant:U,color:N,radius:K,panelBackground:M,material:z,width:re,maxWidth:G,asChild:se,attachments:_,defaultAttachments:he=[],onAttachmentsChange:$,accept:J,multiple:k=!0,maxAttachments:P,maxFileSize:p,paste:fe=!0,pasteAccept:Q,clearOnSubmit:be=!0,onAttachmentReject:q,dropzone:I=!0,apiRef:n,...d}=a,b=z||M,x=C!=null,[F,Ce]=e.useState(R),X=x?C:F,j=c!=null,[Z,Y]=e.useState(w),ee=j?c:Z,ge=e.useRef(null),ie=e.useRef(null),ye=e.useRef(!1),te="attachments"in a,[ze,ke]=e.useState(he),B=e.useMemo(()=>te?_??[]:ze,[te,_,ze]),le=e.useRef(new Set),ve=t=>Array.isArray(t)?t:typeof t=="string"?t.split(",").map(s=>s.trim()):[],ne=ve(J),Ie=ve(Q).length>0?ve(Q):ne,xe=(t,s)=>{if(s.length===0)return!0;const y=t.type.toLowerCase(),E=t.name.toLowerCase();for(const v of s){const A=v.toLowerCase();if(A.includes("/")){const[ce,Re]=A.split("/"),[ae,tt]=y.split("/");if(ce==="*"||ce===ae&&(Re==="*"||Re===tt))return!0}else if(A.startsWith(".")&&E.endsWith(A))return!0}return!1},Ge=t=>{const s=[],y=[],E=typeof P=="number"?Math.max(P-B.length,0):1/0;for(const v of t){if(s.length>=E){y.push({file:v,reason:"count"});continue}if(typeof p=="number"&&v.size>p){y.push({file:v,reason:"size"});continue}if(!xe(v,ne)){y.push({file:v,reason:"type"});continue}const A=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,ce=/\.(png|jpe?g|gif|webp|bmp|svg)$/i.test(v.name),ae=(v.type||"").toLowerCase().startsWith("image/")||ce?URL.createObjectURL(v):void 0;ae&&le.current.add(ae),s.push({id:A,name:v.name,size:v.size,type:v.type,file:v,url:ae,status:"idle"})}return{accepted:s,rejected:y}},Ae=t=>{const{accepted:s,rejected:y}=Ge(t);if(s.length>0){const E=B.concat(s);te||ke(E),$?.(E),j||Y(!0),g?.(!0)}y.length>0&&q?.(y)},_e=t=>{const s=A=>Ie.length===0?xe(A,ne):xe(A,Ie),y=[],E=[],v=typeof P=="number"?Math.max(P-B.length,0):1/0;for(const A of t){if(y.length>=v){E.push({file:A,reason:"count"});continue}if(typeof p=="number"&&A.size>p){E.push({file:A,reason:"size"});continue}if(!s(A)){E.push({file:A,reason:"type"});continue}y.push(A)}y.length>0&&Ae(y),E.length>0&&q?.(E)};e.useEffect(()=>{const t=new Set(B.map(s=>s.url).filter(Boolean));for(const s of Array.from(le.current))t.has(s)||(URL.revokeObjectURL(s),le.current.delete(s))},[B]),e.useEffect(()=>{const t=le.current;return()=>{for(const s of Array.from(t))URL.revokeObjectURL(s);t.clear()}},[]);const Je=se?D.Slot:"div",Qe=e.useCallback(t=>{const s=t.relatedTarget,y=ge.current;y&&(s&&y.contains(s)||ye.current||(X?.trim?.()??"").length===0&&B.length===0&&(j||Y(!1),g?.(!1)))},[j,g,X,B]),{getRootProps:Xe,getInputProps:Ze,isDragActive:je,open:Be}=(0,Ye.useDropzone)({onDrop:(t,s)=>{if(t.length>0&&Ae(t),s.length>0&&q){const y=s.map(({file:E,errors:v})=>{const A=v[0]?.code==="file-too-large"?"size":v[0]?.code==="file-invalid-type"?"type":"count";return{file:E,reason:A}});q(y)}},accept:ne.length>0?ne.reduce((t,s)=>(s.includes("/")?t[s]=[]:s.startsWith(".")&&(t[s]=[]),t),{}):void 0,multiple:k,maxSize:p,noClick:!0,noKeyboard:!0,disabled:!I||S});e.useImperativeHandle(n,()=>({focusTextarea:()=>ie.current?.focus({preventScroll:!0}),openFilePicker:()=>{ye.current=!0,Be()}}),[Be]);const We=e.useCallback(t=>{if(!(t instanceof Element))return!1;const s=t;return s.closest(".rt-ChatbarDropOverlay")?!0:!!s.closest('button, [role="button"], a[href], input, textarea, select, [contenteditable], [tabindex]:not([tabindex="-1"])')},[]),et=e.useCallback(t=>{S||We(t.target)||t.pointerType==="mouse"&&t.button!==0||(t.preventDefault(),ie.current?.focus({preventScroll:!0}))},[S,We,ie]);return e.createElement(Ke.Provider,{value:{open:ee,setOpen:t=>{j||Y(t),g?.(t)},isOpenControlled:j,value:X,setValue:t=>{x||Ce(t),h?.(t)},isValueControlled:x,size:H,expandOn:i,minLines:L,maxLines:m,sendMode:f,disabled:S,readOnly:V,onSubmit:O,rootRef:ge,textareaRef:ie,attachments:B,setAttachments:t=>{te||ke(t),$?.(t)},isAttachmentsControlled:te,accept:J,multiple:k,maxAttachments:P,maxFileSize:p,paste:fe,pasteAccept:Q,clearOnSubmit:be,onAttachmentReject:q,dropzone:I,appendFiles:Ae,appendFilesFromPaste:_e,fileDialogOpenRef:ye}},e.createElement(Je,{...d,ref:t=>{typeof o=="function"?o(t):o&&(o.current=t),ge.current=t},className:(0,T.default)("rt-ChatbarRoot",`rt-r-size-${H}`,r),style:{position:"relative",width:re,maxWidth:G,...u},"data-state":ee?"open":"closed","data-disabled":S?"":void 0,"data-readonly":V?"":void 0,"data-drop-active":I&&je?"":void 0,"data-accent-color":N,"data-radius":K,"data-panel-background":b,"data-material":b,"aria-expanded":ee,onBlurCapture:Qe},I&&e.createElement("input",{...Ze()}),e.createElement("div",{...I?Xe():{},style:{width:"100%",height:"100%"},onPointerDown:et},e.createElement(qe.Box,{className:(0,T.default)("rt-ChatbarBox",`rt-variant-${U??"surface"}`),style:{position:"relative"},"data-accent-color":N,"data-radius":K,"data-panel-background":b,"data-material":b},e.createElement("div",{className:"rt-ChatbarGrid"},l),I&&je&&e.createElement("div",{className:"rt-ChatbarDropOverlay"},e.createElement("div",{className:"rt-ChatbarDropContent"},e.createElement(de.Text,{color:"gray",size:H,weight:"medium"},"Drop files here to attach")))))))});Ee.displayName="Chatbar.Root";const Te=e.forwardRef((a,o)=>{const{className:r,style:u,asChild:l,onFocus:C,onInput:R,onChange:h,onPaste:c,onKeyDown:w,submitOnEnter:g=!1,rows:i,...L}=a,m=W(),{open:f,minLines:S,maxLines:V,expandOn:O,disabled:H,readOnly:U,setOpen:N,setValue:K,textareaRef:M,value:z,isValueControlled:re,sendMode:G,paste:se,appendFilesFromPaste:_,size:he}=m,$=e.useRef(0),J=e.useRef(0),k=e.useRef(0),P=e.useCallback(()=>{const n=M.current;if(!n)return;const d=window.getComputedStyle(n),b=parseFloat(d.lineHeight)||20,x=parseFloat(d.paddingTop)||0,F=parseFloat(d.paddingBottom)||0;$.current=b,J.current=x+F,k.current=Math.ceil(1*b)+x+F},[M]),p=e.useCallback(n=>{const d=M.current;if(!d)return;d.style.height="auto",$.current===0&&P();const b=$.current,x=J.current,F=n??f,Ce=F?S:1,X=F?V:1,j=Math.ceil(Ce*b)+x,Z=Math.ceil(X*b)+x,Y=Math.max(d.scrollHeight,j),ee=Math.min(Y,Z);d.style.height=`${ee}px`,Y>Z?(d.style.overflowY="auto",d.style.maxHeight=`${Z}px`):(d.style.overflowY="hidden",d.style.maxHeight="none")},[f,S,V,M,P]);we(()=>{p()},[p,z,f]),we(()=>{if(!(O==="overflow"||O==="both")||f)return;const n=M.current;if(!n)return;n.style.height="auto",k.current===0&&P(),n.scrollHeight>k.current+1&&(N(!0),p(!0),requestAnimationFrame(()=>p(!0)))},[z,O,f,N,M,P,p]),we(()=>{P(),p()},[P,p,he]),e.useEffect(()=>{const n=M.current;if(!n||typeof ResizeObserver>"u")return;let d=$.current;const b=new ResizeObserver(()=>{const x=window.getComputedStyle(n),F=parseFloat(x.lineHeight)||20;F!==d&&(d=F,P(),requestAnimationFrame(()=>p()))});return b.observe(n),()=>b.disconnect()},[M,P,p]),e.useEffect(()=>{},[]);const fe=e.useCallback(n=>{H||U||((O==="focus"||O==="both")&&!f&&N(!0),C?.(n))},[H,U,O,f,N,C]),Q=e.useCallback(n=>{const d=n.currentTarget,b=d.value;K(b),(O==="overflow"||O==="both")&&!f&&(d.style.height="auto",k.current===0&&P(),d.scrollHeight>k.current+1&&(N(!0),p(!0),requestAnimationFrame(()=>p(!0)))),requestAnimationFrame(()=>p()),h?.(n)},[O,f,N,K,h,p,P]),be=e.useCallback(n=>{if(se){const b=Array.from(n.clipboardData?.items??[]).filter(x=>x.kind==="file").map(x=>x.getAsFile()).filter(x=>!!x);b.length>0&&(n.preventDefault(),_(b))}setTimeout(()=>{f?p():p(!0)},0),c?.(n)},[se,f,p,c,_]),q=e.useCallback(n=>{if(!g){w?.(n);return}if(n.key==="Enter"&&!n.shiftKey&&!n.altKey&&!n.ctrlKey&&!n.metaKey&&!n.nativeEvent.isComposing){if(H||U){w?.(n);return}if(G==="never"){w?.(n);return}const b=z.trim().length>0||m.attachments.length>0;if(G==="whenDirty"&&!b){w?.(n);return}n.preventDefault(),m.onSubmit?.({value:z,attachments:m.attachments}),m.clearOnSubmit&&(re||K(""),m.setAttachments([]))}w?.(n)},[g,H,U,G,z,re,K,m,w]),I=l?D.Slot:"textarea";return e.createElement("div",{className:(0,T.default)("rt-ChatbarField","rt-ChatbarTextarea",r)},e.createElement(I,{...L,ref:n=>{typeof o=="function"?o(n):o&&(o.current=n),M.current=n},className:"rt-ChatbarInput",value:z,onInput:R,onChange:Q,onFocus:fe,onPaste:be,onKeyDown:q,disabled:H,readOnly:U,rows:f?S:1,spellCheck:L.spellCheck??!0,autoCorrect:L.autoCorrect??"on",style:u}))});Te.displayName="Chatbar.Textarea";const Se=e.forwardRef((a,o)=>{const{children:r,asChild:u,style:l,className:C,...R}=a;return W().open?null:e.createElement(u?D.Slot:"div",{...R,ref:o,className:(0,T.default)("rt-ChatbarInlineStart",C),style:l},r)});Se.displayName="Chatbar.InlineStart";const Oe=e.forwardRef((a,o)=>{const{children:r,asChild:u,style:l,className:C,...R}=a;return W().open?null:e.createElement(u?D.Slot:"div",{...R,ref:o,className:(0,T.default)("rt-ChatbarInlineEnd",C),style:l},r)});Oe.displayName="Chatbar.InlineEnd";const Me=e.forwardRef((a,o)=>{const{asChild:r,forceMount:u,renderAttachment:l,className:C,style:R,...h}=a,c=W();return!(c.attachments.length>0)&&!u?null:e.createElement(r?D.Slot:"div",{...h,ref:o,className:(0,T.default)("rt-ChatbarAttachmentsRow",C),style:R,role:"list","aria-label":h["aria-label"]??"Attachments"},e.createElement($e.ScrollArea,{className:"rt-ChatbarScrollArea",scrollbars:"horizontal",size:"1"},e.createElement(oe.Flex,{align:"center",gap:"2",style:{minWidth:"fit-content"}},c.attachments.map(i=>e.createElement(me,{key:i.id,attachment:i,asChild:!!l},l?.(i))))))});Me.displayName="Chatbar.AttachmentsRow";const me=e.forwardRef((a,o)=>{const{attachment:r,asChild:u,className:l,style:C,children:R,...h}=a,c=W(),w=u?D.Slot:"div",g=!!r.url&&r.type.startsWith("image/");return e.createElement(w,{...h,ref:o,className:(0,T.default)("rt-ChatbarAttachment",l),style:C,role:"listitem","data-kind":g?"image":"file",title:r.name},R??e.createElement(oe.Flex,{align:"center",gap:"2",pr:g?void 0:"6"},e.createElement("div",{className:"rt-ChatbarAttachmentPreview","aria-hidden":!0},g?e.createElement("img",{className:"rt-ChatbarAttachmentImage",src:r.url,alt:""}):e.createElement(pe.FileTextIcon,null)),!g&&e.createElement(oe.Flex,{direction:"column",gap:"0",style:{minWidth:0}},e.createElement(de.Text,{size:c.size,weight:"medium",style:{whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"}},r.name),e.createElement(de.Text,{size:"1",color:"gray"},Math.ceil(r.size/1024)," KB")),e.createElement(Pe.IconButton,{className:"rt-ChatbarAttachmentRemove","aria-label":`Remove ${r.name}`,size:"1",variant:"classic",highContrast:!0,color:"gray",onClick:()=>c.setAttachments(c.attachments.filter(i=>i.id!==r.id))},e.createElement(pe.CloseIcon,null))))});me.displayName="Chatbar.Attachment";const Le=e.forwardRef((a,o)=>{const{asChild:r,accept:u,multiple:l,className:C,style:R,...h}=a,c=W(),w=e.useRef(null),g=r?D.Slot:"button",i=u??c.accept,L=(Array.isArray(i)?i:i?.split(",")??[]).join(",");return e.useEffect(()=>{const m=()=>{c.fileDialogOpenRef.current=!1};return window.addEventListener("focus",m),()=>window.removeEventListener("focus",m)},[c.fileDialogOpenRef]),e.createElement(e.Fragment,null,e.createElement(g,{...h,ref:o,className:(0,T.default)("rt-ChatbarAttachTrigger",C),style:R,type:h.type??"button","aria-label":h["aria-label"]??"Add attachments",onPointerDown:m=>{c.fileDialogOpenRef.current=!0,h.onPointerDown?.(m)},onMouseDown:m=>{c.fileDialogOpenRef.current=!0,h.onMouseDown?.(m)},onClick:m=>{c.fileDialogOpenRef.current=!0,w.current&&w.current.click(),h.onClick?.(m)}}),e.createElement("input",{ref:w,type:"file",accept:L,multiple:l??c.multiple,tabIndex:-1,style:{display:"none"},onChange:m=>{const f=Array.from(m.currentTarget.files??[]);f.length>0&&c.appendFiles(f),c.fileDialogOpenRef.current=!1,m.currentTarget.value=""}}))});Le.displayName="Chatbar.AttachTrigger";const Fe=e.forwardRef((a,o)=>{const{asChild:r,children:u,className:l,style:C,...R}=a;return W().open?e.createElement(r?D.Slot:"div",{...R,ref:o,className:(0,T.default)("rt-ChatbarRow",l),style:C},e.createElement(oe.Flex,{align:"center",justify:"between",width:"100%"},u)):null});Fe.displayName="Chatbar.Row";const He=e.forwardRef((a,o)=>{const{className:r,style:u,...l}=a;return e.createElement("div",{...l,ref:o,className:(0,T.default)("rt-ChatbarRowStart",r),style:u})});He.displayName="Chatbar.RowStart";const Ne=e.forwardRef((a,o)=>{const{className:r,style:u,...l}=a;return e.createElement("div",{...l,ref:o,className:(0,T.default)("rt-ChatbarRowEnd",r),style:u})});Ne.displayName="Chatbar.RowEnd";const De=e.forwardRef((a,o)=>{const{asChild:r,clearOnSend:u=!0,disabled:l,children:C,className:R,style:h,size:c,variant:w,...g}=a,i=W(),m=i.value.trim().length>0||i.attachments.length>0,f=i.sendMode==="always"||i.sendMode==="whenDirty"&&m;if(i.sendMode==="never")return null;const S=V=>{i.disabled||i.readOnly||(i.onSubmit?.({value:i.value,attachments:i.attachments}),u&&(i.isValueControlled||i.setValue(""),i.clearOnSubmit&&i.setAttachments([])),g.onClick?.(V))};return e.createElement(Pe.IconButton,{...g,ref:o,size:c??i.size,variant:w??(i.open?"solid":"ghost"),disabled:l||i.disabled||i.readOnly,className:(0,T.default)("rt-ChatbarSend",R),style:{opacity:f?1:0,pointerEvents:f?"auto":"none",...h},asChild:r,onClick:S,"aria-label":g["aria-label"]??"Send"},C??e.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"lucide lucide-arrow-right-icon lucide-arrow-right"},e.createElement("path",{d:"M5 12h14"}),e.createElement("path",{d:"m12 5 7 7-7 7"})))});De.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 { Box } from './box.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 = 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 // Guards\n fileDialogOpenRef: React.MutableRefObject<boolean>;\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 /** Accent color for the control (matches TextArea) */\n color?: string;\n /** Optional radius override (matches TextArea) */\n radius?: string | number;\n /** Panel/material translucency flags (matches TextArea) */\n panelBackground?: 'solid' | 'translucent';\n material?: 'solid' | 'translucent';\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 /**\n * Optional API ref to control Chatbar imperatively without relying on DOM refs.\n * Provides methods to focus the textarea and open the file picker.\n */\n apiRef?: React.Ref<ChatbarApi>;\n}\n\ntype RootElement = React.ElementRef<'div'>;\n/** Imperative API for Chatbar.Root */\nexport interface ChatbarApi {\n /** Focus the textarea input */\n focusTextarea: () => void;\n /** Open the file picker dialog (respects accept/multiple) */\n openFilePicker: () => void;\n}\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 extends ComponentPropsWithout<'div', RemovedProps | 'onSubmit'>, 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 color,\n radius,\n panelBackground,\n material,\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 apiRef,\n ...divProps\n } = props;\n const effectiveMaterial = material || panelBackground;\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 const fileDialogOpenRef = React.useRef<boolean>(false);\n\n // Attachments state\n // Treat `attachments` as controlled if the prop is provided, even if its value is `undefined`.\n // This avoids switching between controlled and uncontrolled when a consumer sets\n // `attachments={undefined}` to clear attachments. In that case we normalize to an empty array.\n const isAttachmentsControlled = 'attachments' in props;\n const [attachmentsUncontrolled, setAttachmentsUncontrolled] = React.useState<ChatbarAttachment[]>(defaultAttachments);\n const attachments = React.useMemo(\n () => (isAttachmentsControlled ? ((attachmentsProp ?? []) as ChatbarAttachment[]) : attachmentsUncontrolled),\n [isAttachmentsControlled, attachmentsProp, attachmentsUncontrolled],\n );\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) => (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))) 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 = typeof maxAttachments === 'number' ? Math.max(maxAttachments - attachments.length, 0) : 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 // Ensure chatbar expands when attachments are added\n if (!isOpenControlled) setOpenUncontrolled(true);\n onOpenChangeProp?.(true);\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 = typeof maxAttachments === 'number' ? Math.max(maxAttachments - attachments.length, 0) : 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 const urlSet = generatedUrlSetRef.current;\n return () => {\n for (const url of Array.from(urlSet)) {\n URL.revokeObjectURL(url);\n }\n urlSet.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 // If native file dialog is open, avoid collapsing on blur\n if (fileDialogOpenRef.current) return;\n // Collapse when leaving the root if the value is empty\n // Only collapse when both message and attachments are empty\n if ((value?.trim?.() ?? '').length === 0 && attachments.length === 0) {\n if (!isOpenControlled) setOpenUncontrolled(false);\n onOpenChangeProp?.(false);\n }\n },\n [isOpenControlled, onOpenChangeProp, value, attachments],\n );\n\n // Dropzone functionality\n const {\n getRootProps,\n getInputProps,\n isDragActive,\n open: openFileDialog,\n } = 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 = errors[0]?.code === 'file-too-large' ? 'size' : errors[0]?.code === 'file-invalid-type' ? 'type' : '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 // Expose imperative API via apiRef (non-breaking; forwardedRef still receives the DOM node)\n React.useImperativeHandle(\n apiRef,\n () => ({\n focusTextarea: () => textareaRef.current?.focus({ preventScroll: true }),\n openFilePicker: () => {\n // Guard against blur-collapse while native dialog is open\n fileDialogOpenRef.current = true;\n openFileDialog();\n },\n }),\n [openFileDialog],\n );\n\n // Click-to-focus: focus textarea when clicking non-interactive areas inside the container\n const isInteractiveTarget = React.useCallback((target: EventTarget | null) => {\n if (!(target instanceof Element)) return false;\n const el = target as Element;\n if (el.closest('.rt-ChatbarDropOverlay')) return true;\n return !!el.closest('button, [role=\"button\"], a[href], input, textarea, select, [contenteditable], [tabindex]:not([tabindex=\"-1\"])');\n }, []);\n\n const handleContainerPointerDown = React.useCallback(\n (event: React.PointerEvent) => {\n if (disabled) return;\n if (isInteractiveTarget(event.target)) return;\n if (event.pointerType === 'mouse' && event.button !== 0) return;\n event.preventDefault();\n textareaRef.current?.focus({ preventScroll: true });\n },\n [disabled, isInteractiveTarget, textareaRef],\n );\n\n // Clicking the label-wrapped Card will naturally focus the nested textarea.\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 fileDialogOpenRef,\n }}\n >\n <Comp\n {...divProps}\n ref={(node: HTMLDivElement) => {\n if (typeof forwardedRef === 'function') forwardedRef(node);\n else if (forwardedRef) (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 data-accent-color={color}\n data-radius={radius as any}\n data-panel-background={effectiveMaterial}\n data-material={effectiveMaterial}\n aria-expanded={open}\n onBlurCapture={handleBlurCapture}\n >\n {dropzone && <input {...getInputProps()} />}\n <div {...(dropzone ? getRootProps() : {})} style={{ width: '100%', height: '100%' }} onPointerDown={handleContainerPointerDown}>\n <Box\n className={classNames('rt-ChatbarBox', `rt-variant-${variant ?? 'surface'}`)}\n style={{ position: 'relative' }}\n data-accent-color={color}\n data-radius={radius as any}\n data-panel-background={effectiveMaterial}\n data-material={effectiveMaterial}\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 </Box>\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 { className, style, asChild, onFocus, onInput, onChange, onPaste, onKeyDown, submitOnEnter = false, rows, ...textareaProps } = props;\n const ctx = useChatbarContext();\n const { open, minLines, maxLines, expandOn, disabled, readOnly, setOpen, setValue, textareaRef, value, isValueControlled, sendMode, paste, appendFilesFromPaste, size } = 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 // Auto-open on external value changes when content overflows one line\n useIsomorphicLayoutEffect(() => {\n if (!(expandOn === 'overflow' || expandOn === 'both')) return;\n if (open) return;\n const el = textareaRef.current;\n if (!el) return;\n // Measure overflow against compact (1-line) height\n el.style.height = 'auto';\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\n updateHeight(true);\n requestAnimationFrame(() => updateHeight(true));\n }\n }, [value, expandOn, open, setOpen, textareaRef, recomputeMetrics, updateHeight]);\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 = textareaProps['aria-label'] != null || textareaProps['aria-labelledby'] != null;\n if (!hasLabel) {\n console.warn('[Chatbar.Textarea] Provide aria-label or aria-labelledby to ensure the control has an accessible name.');\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 // Prevent pasting the file name or any text representation when files are present\n event.preventDefault();\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 (event.key === 'Enter' && !event.shiftKey && !event.altKey && !event.ctrlKey && !event.metaKey && !event.nativeEvent.isComposing) {\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 [submitOnEnter, disabled, readOnly, sendMode, value, isValueControlled, setValue, ctx, onKeyDown],\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) (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 {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarInlineStart', className)} style={style}>\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 {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarInlineEnd', className)} style={style}>\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>((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 {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarAttachmentsRow', className)} style={style} role=\"list\" aria-label={divProps['aria-label'] ?? 'Attachments'}>\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});\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 {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarAttachment', className)} style={style} role=\"listitem\" data-kind={isImage ? 'image' : 'file'} title={attachment.name}>\n {children ?? (\n // <Card size={ctx.size} variant=\"surface\">\n <Flex align=\"center\" gap=\"2\" pr={!isImage ? '6' : undefined}>\n <div className=\"rt-ChatbarAttachmentPreview\" aria-hidden>\n {isImage ? <img className=\"rt-ChatbarAttachmentImage\" src={attachment.url} alt=\"\" /> : <FileTextIcon />}\n </div>\n {!isImage && (\n <Flex direction=\"column\" gap=\"0\" style={{ minWidth: 0 }}>\n <Text size={ctx.size} weight=\"medium\" style={{ whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>\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={() => ctx.setAttachments(ctx.attachments.filter((a) => a.id !== attachment.id))}\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>((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 // Prefer Chatbar.Root's accept when a local accept is not provided\n const mergedAccept = accept ?? ctx.accept;\n const actualAccept = (Array.isArray(mergedAccept) ? mergedAccept : (mergedAccept?.split(',') ?? [])).join(',');\n React.useEffect(() => {\n const handleWindowFocus = () => {\n // Reset guard when window regains focus after file dialog closes\n ctx.fileDialogOpenRef.current = false;\n };\n window.addEventListener('focus', handleWindowFocus);\n return () => window.removeEventListener('focus', handleWindowFocus);\n }, [ctx.fileDialogOpenRef]);\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 onPointerDown={(e: any) => {\n // Set guard before blur occurs (Safari fires blur before click)\n ctx.fileDialogOpenRef.current = true;\n buttonProps.onPointerDown?.(e);\n }}\n onMouseDown={(e: any) => {\n // Fallback for environments without Pointer Events\n ctx.fileDialogOpenRef.current = true;\n buttonProps.onMouseDown?.(e);\n }}\n onClick={(e: any) => {\n // Ensure file input opens reliably by clicking it first\n ctx.fileDialogOpenRef.current = true;\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 // File dialog closed; allow normal blur handling\n ctx.fileDialogOpenRef.current = false;\n // Reset input value to allow selecting the same file again\n e.currentTarget.value = '';\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 {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarRow', className)} style={style}>\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'>>((props, forwardedRef) => {\n const { className, style, ...divProps } = props;\n return <div {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarRowStart', className)} style={style} />;\n});\nRowStart.displayName = 'Chatbar.RowStart';\n\nconst RowEnd = React.forwardRef<HTMLDivElement, React.ComponentPropsWithoutRef<'div'>>((props, forwardedRef) => {\n const { className, style, ...divProps } = props;\n return <div {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarRowEnd', className)} style={style} />;\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 { asChild, clearOnSend = true, disabled, children, className, style, ...buttonProps } = 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 ?? (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"lucide lucide-arrow-right-icon lucide-arrow-right\"\n >\n <path d=\"M5 12h14\" />\n <path d=\"m12 5 7 7-7 7\" />\n </svg>\n )}\n </IconButton>\n );\n});\nSend.displayName = 'Chatbar.Send';\n\nexport { Root, Textarea, InlineStart, InlineEnd, AttachmentsRow, Attachment, AttachTrigger, Row, RowStart, RowEnd, Send };\nexport type { RootProps as ChatbarRootProps, TextareaProps as ChatbarTextareaProps, RowProps as ChatbarRowProps, SendProps as ChatbarSendProps, ChatbarAttachment };\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_box", "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", "color", "radius", "panelBackground", "material", "width", "maxWidth", "asChild", "attachmentsProp", "defaultAttachments", "onAttachmentsChange", "accept", "multiple", "maxAttachments", "maxFileSize", "paste", "pasteAccept", "clearOnSubmit", "onAttachmentReject", "dropzone", "apiRef", "divProps", "effectiveMaterial", "isValueControlled", "valueUncontrolled", "setValueUncontrolled", "value", "isOpenControlled", "openUncontrolled", "setOpenUncontrolled", "open", "rootRef", "textareaRef", "fileDialogOpenRef", "isAttachmentsControlled", "attachmentsUncontrolled", "setAttachmentsUncontrolled", "attachments", "generatedUrlSetRef", "toArray", "val", "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", "urlSet", "Comp", "handleBlurCapture", "event", "nextTarget", "rootEl", "getRootProps", "getInputProps", "isDragActive", "openFileDialog", "rejectedFiles", "rejections", "errors", "reason", "acc", "pattern", "isInteractiveTarget", "target", "el", "handleContainerPointerDown", "node", "classNames", "onFocus", "onInput", "onChange", "onPaste", "onKeyDown", "submitOnEnter", "rows", "textareaProps", "setOpen", "setValue", "lineHeightRef", "paddingRef", "compactHeightRef", "recomputeMetrics", "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", "mergedAccept", "actualAccept", "handleWindowFocus", "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 { Box } from './box.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 = 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 // Guards\n fileDialogOpenRef: React.MutableRefObject<boolean>;\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 /** Accent color for the control (matches TextArea) */\n color?: string;\n /** Optional radius override (matches TextArea) */\n radius?: string | number;\n /** Panel/material translucency flags (matches TextArea) */\n panelBackground?: 'solid' | 'translucent';\n material?: 'solid' | 'translucent';\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 /**\n * Optional API ref to control Chatbar imperatively without relying on DOM refs.\n * Provides methods to focus the textarea and open the file picker.\n */\n apiRef?: React.Ref<ChatbarApi>;\n}\n\ntype RootElement = React.ElementRef<'div'>;\n/** Imperative API for Chatbar.Root */\nexport interface ChatbarApi {\n /** Focus the textarea input */\n focusTextarea: () => void;\n /** Open the file picker dialog (respects accept/multiple) */\n openFilePicker: () => void;\n}\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 extends ComponentPropsWithout<'div', RemovedProps | 'onSubmit'>, 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 color,\n radius,\n panelBackground,\n material,\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 apiRef,\n ...divProps\n } = props;\n const effectiveMaterial = material || panelBackground;\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 const fileDialogOpenRef = React.useRef<boolean>(false);\n\n // Attachments state\n // Treat `attachments` as controlled if the prop is provided, even if its value is `undefined`.\n // This avoids switching between controlled and uncontrolled when a consumer sets\n // `attachments={undefined}` to clear attachments. In that case we normalize to an empty array.\n const isAttachmentsControlled = 'attachments' in props;\n const [attachmentsUncontrolled, setAttachmentsUncontrolled] = React.useState<ChatbarAttachment[]>(defaultAttachments);\n const attachments = React.useMemo(\n () => (isAttachmentsControlled ? ((attachmentsProp ?? []) as ChatbarAttachment[]) : attachmentsUncontrolled),\n [isAttachmentsControlled, attachmentsProp, attachmentsUncontrolled],\n );\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) => (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))) 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 = typeof maxAttachments === 'number' ? Math.max(maxAttachments - attachments.length, 0) : 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 // Ensure chatbar expands when attachments are added\n if (!isOpenControlled) setOpenUncontrolled(true);\n onOpenChangeProp?.(true);\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 = typeof maxAttachments === 'number' ? Math.max(maxAttachments - attachments.length, 0) : 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 const urlSet = generatedUrlSetRef.current;\n return () => {\n for (const url of Array.from(urlSet)) {\n URL.revokeObjectURL(url);\n }\n urlSet.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 // If native file dialog is open, avoid collapsing on blur\n if (fileDialogOpenRef.current) return;\n // Collapse when leaving the root if the value is empty\n // Only collapse when both message and attachments are empty\n if ((value?.trim?.() ?? '').length === 0 && attachments.length === 0) {\n if (!isOpenControlled) setOpenUncontrolled(false);\n onOpenChangeProp?.(false);\n }\n },\n [isOpenControlled, onOpenChangeProp, value, attachments],\n );\n\n // Dropzone functionality\n const {\n getRootProps,\n getInputProps,\n isDragActive,\n open: openFileDialog,\n } = 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 = errors[0]?.code === 'file-too-large' ? 'size' : errors[0]?.code === 'file-invalid-type' ? 'type' : '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 // Expose imperative API via apiRef (non-breaking; forwardedRef still receives the DOM node)\n React.useImperativeHandle(\n apiRef,\n () => ({\n focusTextarea: () => textareaRef.current?.focus({ preventScroll: true }),\n openFilePicker: () => {\n // Guard against blur-collapse while native dialog is open\n fileDialogOpenRef.current = true;\n openFileDialog();\n },\n }),\n [openFileDialog],\n );\n\n // Click-to-focus: focus textarea when clicking non-interactive areas inside the container\n const isInteractiveTarget = React.useCallback((target: EventTarget | null) => {\n if (!(target instanceof Element)) return false;\n const el = target as Element;\n if (el.closest('.rt-ChatbarDropOverlay')) return true;\n return !!el.closest('button, [role=\"button\"], a[href], input, textarea, select, [contenteditable], [tabindex]:not([tabindex=\"-1\"])');\n }, []);\n\n const handleContainerPointerDown = React.useCallback(\n (event: React.PointerEvent) => {\n if (disabled) return;\n if (isInteractiveTarget(event.target)) return;\n if (event.pointerType === 'mouse' && event.button !== 0) return;\n event.preventDefault();\n textareaRef.current?.focus({ preventScroll: true });\n },\n [disabled, isInteractiveTarget, textareaRef],\n );\n\n // Clicking the label-wrapped Card will naturally focus the nested textarea.\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 fileDialogOpenRef,\n }}\n >\n <Comp\n {...divProps}\n ref={(node: HTMLDivElement) => {\n if (typeof forwardedRef === 'function') forwardedRef(node);\n else if (forwardedRef) (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 data-accent-color={color}\n data-radius={radius as any}\n data-panel-background={effectiveMaterial}\n data-material={effectiveMaterial}\n aria-expanded={open}\n onBlurCapture={handleBlurCapture}\n >\n {dropzone && <input {...getInputProps()} />}\n <div {...(dropzone ? getRootProps() : {})} style={{ width: '100%', height: '100%' }} onPointerDown={handleContainerPointerDown}>\n <Box\n className={classNames('rt-ChatbarBox', `rt-variant-${variant ?? 'surface'}`)}\n style={{ position: 'relative' }}\n data-accent-color={color}\n data-radius={radius as any}\n data-panel-background={effectiveMaterial}\n data-material={effectiveMaterial}\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 </Box>\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 { className, style, asChild, onFocus, onInput, onChange, onPaste, onKeyDown, submitOnEnter = false, rows, ...textareaProps } = props;\n const ctx = useChatbarContext();\n const { open, minLines, maxLines, expandOn, disabled, readOnly, setOpen, setValue, textareaRef, value, isValueControlled, sendMode, paste, appendFilesFromPaste, size } = 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 // Auto-open on external value changes when content overflows one line\n useIsomorphicLayoutEffect(() => {\n if (!(expandOn === 'overflow' || expandOn === 'both')) return;\n if (open) return;\n const el = textareaRef.current;\n if (!el) return;\n // Measure overflow against compact (1-line) height\n el.style.height = 'auto';\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\n updateHeight(true);\n requestAnimationFrame(() => updateHeight(true));\n }\n }, [value, expandOn, open, setOpen, textareaRef, recomputeMetrics, updateHeight]);\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 = textareaProps['aria-label'] != null || textareaProps['aria-labelledby'] != null;\n if (!hasLabel) {\n console.warn('[Chatbar.Textarea] Provide aria-label or aria-labelledby to ensure the control has an accessible name.');\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 // Prevent pasting the file name or any text representation when files are present\n event.preventDefault();\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 (event.key === 'Enter' && !event.shiftKey && !event.altKey && !event.ctrlKey && !event.metaKey && !event.nativeEvent.isComposing) {\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 [submitOnEnter, disabled, readOnly, sendMode, value, isValueControlled, setValue, ctx, onKeyDown],\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) (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 {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarInlineStart', className)} style={style}>\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 {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarInlineEnd', className)} style={style}>\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>((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 {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarAttachmentsRow', className)} style={style} role=\"list\" aria-label={divProps['aria-label'] ?? 'Attachments'}>\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});\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 {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarAttachment', className)} style={style} role=\"listitem\" data-kind={isImage ? 'image' : 'file'} title={attachment.name}>\n {children ?? (\n // <Card size={ctx.size} variant=\"surface\">\n <Flex align=\"center\" gap=\"2\" pr={!isImage ? '6' : undefined}>\n <div className=\"rt-ChatbarAttachmentPreview\" aria-hidden>\n {isImage ? <img className=\"rt-ChatbarAttachmentImage\" src={attachment.url} alt=\"\" /> : <FileTextIcon />}\n </div>\n {!isImage && (\n <Flex direction=\"column\" gap=\"0\" style={{ minWidth: 0 }}>\n <Text size={ctx.size} weight=\"medium\" style={{ whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>\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={() => ctx.setAttachments(ctx.attachments.filter((a) => a.id !== attachment.id))}\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>((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 // Prefer Chatbar.Root's accept when a local accept is not provided\n const mergedAccept = accept ?? ctx.accept;\n const actualAccept = (Array.isArray(mergedAccept) ? mergedAccept : (mergedAccept?.split(',') ?? [])).join(',');\n React.useEffect(() => {\n const handleWindowFocus = () => {\n // Reset guard when window regains focus after file dialog closes\n ctx.fileDialogOpenRef.current = false;\n };\n window.addEventListener('focus', handleWindowFocus);\n return () => window.removeEventListener('focus', handleWindowFocus);\n }, [ctx.fileDialogOpenRef]);\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 onPointerDown={(e: any) => {\n // Set guard before blur occurs (Safari fires blur before click)\n ctx.fileDialogOpenRef.current = true;\n buttonProps.onPointerDown?.(e);\n }}\n onMouseDown={(e: any) => {\n // Fallback for environments without Pointer Events\n ctx.fileDialogOpenRef.current = true;\n buttonProps.onMouseDown?.(e);\n }}\n onClick={(e: any) => {\n // Ensure file input opens reliably by clicking it first\n ctx.fileDialogOpenRef.current = true;\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 // File dialog closed; allow normal blur handling\n ctx.fileDialogOpenRef.current = false;\n // Reset input value to allow selecting the same file again\n e.currentTarget.value = '';\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 {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarRow', className)} style={style}>\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'>>((props, forwardedRef) => {\n const { className, style, ...divProps } = props;\n return <div {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarRowStart', className)} style={style} />;\n});\nRowStart.displayName = 'Chatbar.RowStart';\n\nconst RowEnd = React.forwardRef<HTMLDivElement, React.ComponentPropsWithoutRef<'div'>>((props, forwardedRef) => {\n const { className, style, ...divProps } = props;\n return <div {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarRowEnd', className)} style={style} />;\n});\nRowEnd.displayName = 'Chatbar.RowEnd';\n\ntype SendProps = IconButtonProps & {\n asChild?: boolean;\n clearOnSend?: boolean;\n};\n\nconst Send = React.forwardRef<HTMLButtonElement, SendProps>((props, forwardedRef) => {\n const { asChild, clearOnSend = true, disabled, children, className, style, size: sizeProp, variant: variantProp, ...buttonProps } = 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={sizeProp ?? ctx.size}\n variant={variantProp ?? (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 as any)['aria-label'] ?? 'Send'}\n >\n {children ?? (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"lucide lucide-arrow-right-icon lucide-arrow-right\"\n >\n <path d=\"M5 12h14\" />\n <path d=\"m12 5 7 7-7 7\" />\n </svg>\n )}\n </IconButton>\n );\n});\nSend.displayName = 'Chatbar.Send';\n\nexport { Root, Textarea, InlineStart, InlineEnd, AttachmentsRow, Attachment, AttachTrigger, Row, RowStart, RowEnd, Send };\nexport type { RootProps as ChatbarRootProps, TextareaProps as ChatbarTextareaProps, RowProps as ChatbarRowProps, SendProps as ChatbarSendProps, ChatbarAttachment };\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_box", "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", "color", "radius", "panelBackground", "material", "width", "maxWidth", "asChild", "attachmentsProp", "defaultAttachments", "onAttachmentsChange", "accept", "multiple", "maxAttachments", "maxFileSize", "paste", "pasteAccept", "clearOnSubmit", "onAttachmentReject", "dropzone", "apiRef", "divProps", "effectiveMaterial", "isValueControlled", "valueUncontrolled", "setValueUncontrolled", "value", "isOpenControlled", "openUncontrolled", "setOpenUncontrolled", "open", "rootRef", "textareaRef", "fileDialogOpenRef", "isAttachmentsControlled", "attachmentsUncontrolled", "setAttachmentsUncontrolled", "attachments", "generatedUrlSetRef", "toArray", "val", "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", "urlSet", "Comp", "handleBlurCapture", "event", "nextTarget", "rootEl", "getRootProps", "getInputProps", "isDragActive", "openFileDialog", "rejectedFiles", "rejections", "errors", "reason", "acc", "pattern", "isInteractiveTarget", "target", "el", "handleContainerPointerDown", "node", "classNames", "onFocus", "onInput", "onChange", "onPaste", "onKeyDown", "submitOnEnter", "rows", "textareaProps", "setOpen", "setValue", "lineHeightRef", "paddingRef", "compactHeightRef", "recomputeMetrics", "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", "mergedAccept", "actualAccept", "handleWindowFocus", "e", "clearOnSend", "sizeProp", "variantProp", "visible", "handleClick"]
|
|
7
7
|
}
|
|
@@ -214,10 +214,10 @@ interface RowProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'children
|
|
|
214
214
|
declare const Row: React.ForwardRefExoticComponent<RowProps & React.RefAttributes<HTMLDivElement>>;
|
|
215
215
|
declare const RowStart: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
216
216
|
declare const RowEnd: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
217
|
-
|
|
217
|
+
type SendProps = IconButtonProps & {
|
|
218
218
|
asChild?: boolean;
|
|
219
219
|
clearOnSend?: boolean;
|
|
220
|
-
}
|
|
220
|
+
};
|
|
221
221
|
declare const Send: React.ForwardRefExoticComponent<SendProps & React.RefAttributes<HTMLButtonElement>>;
|
|
222
222
|
export { Root, Textarea, InlineStart, InlineEnd, AttachmentsRow, Attachment, AttachTrigger, Row, RowStart, RowEnd, Send };
|
|
223
223
|
export type { RootProps as ChatbarRootProps, TextareaProps as ChatbarTextareaProps, RowProps as ChatbarRowProps, SendProps as ChatbarSendProps, ChatbarAttachment };
|
|
@@ -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":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AASpE,OAAO,KAAK,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAKzF,KAAK,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC;AACvD,KAAK,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,OAAO,CAAC;AAGjD,4CAA4C;AAC5C,KAAK,gBAAgB,GAAG,MAAM,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;AAChE;;;;GAIG;AACH,UAAU,iBAAiB;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,IAAI,EAAE,IAAI,CAAC;IACX,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AA4DD;;;;;;;;;;;;;;GAcG;AACH,UAAU,oBAAoB;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAExC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAEvC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAEpB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAEpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,iBAAiB,EAAE,CAAA;KAAE,KAAK,IAAI,CAAC;IAElF,IAAI,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IACvB,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;IAC/D,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,OAAO,GAAG,aAAa,CAAC;IAC1C,QAAQ,CAAC,EAAE,OAAO,GAAG,aAAa,CAAC;IAEnC,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACrC,QAAQ,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAC;IAGlB,WAAW,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAClC,kBAAkB,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACzC,mBAAmB,CAAC,EAAE,CAAC,WAAW,EAAE,iBAAiB,EAAE,KAAK,IAAI,CAAC;IACjE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAChC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kBAAkB,CAAC,EAAE,CAAC,UAAU,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;KAAE,EAAE,KAAK,IAAI,CAAC;IAE/F;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;CAChC;AAGD,sCAAsC;AACtC,MAAM,WAAW,UAAU;IACzB,+BAA+B;IAC/B,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,6DAA6D;IAC7D,cAAc,EAAE,MAAM,IAAI,CAAC;CAC5B;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,UAAU,SAAU,SAAQ,qBAAqB,CAAC,KAAK,EAAE,YAAY,GAAG,UAAU,CAAC,EAAE,oBAAoB;CAAG;AAE5G,QAAA,MAAM,IAAI,kFAuYR,CAAC;AAGH;;;;;;;GAOG;AACH,UAAU,aAAc,SAAQ,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IACtF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,qBAAqB,CAAC,mBAAmB,CAAC,CAAC;IAC3D;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;;;;;;;GAeG;AACH,QAAA,MAAM,QAAQ,2FAsPZ,CAAC;AAGH,UAAU,eAAgB,SAAQ,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IACvF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED,QAAA,MAAM,WAAW,wFAUf,CAAC;AAGH,QAAA,MAAM,SAAS,wFAUb,CAAC;AAGH;;;GAGG;AACH,UAAU,mBAAoB,SAAQ,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC3F,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,iBAAiB,KAAK,KAAK,CAAC,SAAS,CAAC;CACvE;AAED,QAAA,MAAM,cAAc,4FAmBlB,CAAC;AAGH,qDAAqD;AACrD,UAAU,eAAgB,SAAQ,KAAK,CAAC,wBAAwB,CAAC,KAAK,CAAC;IACrE,UAAU,EAAE,iBAAiB,CAAC;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,QAAA,MAAM,UAAU,wFAwCd,CAAC;AAGH,UAAU,kBAAmB,SAAQ,KAAK,CAAC,wBAAwB,CAAC,QAAQ,CAAC;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,QAAA,MAAM,aAAa,8FAiEjB,CAAC;AAEH,UAAU,QAAS,SAAQ,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAChF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED,QAAA,MAAM,GAAG,iFAYP,CAAC;AAGH,QAAA,MAAM,QAAQ,mKAGZ,CAAC;AAGH,QAAA,MAAM,MAAM,mKAGV,CAAC;AAGH,KAAK,SAAS,GAAG,eAAe,GAAG;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,QAAA,MAAM,IAAI,qFAuDR,CAAC;AAGH,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,aAAa,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAC1H,YAAY,EAAE,SAAS,IAAI,gBAAgB,EAAE,aAAa,IAAI,oBAAoB,EAAE,QAAQ,IAAI,eAAe,EAAE,SAAS,IAAI,gBAAgB,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import*as e from"react";import S from"classnames";import{IconButton as Oe}from"./icon-button.js";import{CloseIcon as _e,FileTextIcon as Je}from"./icons.js";import{Flex as ce}from"./flex.js";import{ScrollArea as Qe}from"./scroll-area.js";import{Slot as B}from"./slot.js";import{Box as Xe}from"./box.js";import{Text as ve}from"./text.js";import{useDropzone as Ze}from"react-dropzone";const xe=typeof window<"u"?e.useLayoutEffect:e.useEffect,Me=e.createContext(null),W=()=>{const l=e.useContext(Me);if(!l)throw new Error("Chatbar context not found. Wrap parts in <Chatbar.Root>.");return l},Le=e.forwardRef((l,i)=>{const{className:s,style:p,children:m,value:b,defaultValue:A="",onValueChange:h,open:r,defaultOpen:o=!1,onOpenChange:R,expandOn:P="both",minLines:T=1,maxLines:u=6,sendMode:C="whenDirty",disabled:F,readOnly:Y,onSubmit:O,size:H="2",variant:V,color:N,radius:U,panelBackground:M,material:D,width:oe,maxWidth:G,asChild:re,attachments:_,defaultAttachments:ue=[],onAttachmentsChange:K,accept:J,multiple:z=!0,maxAttachments:w,maxFileSize:d,paste:de=!0,pasteAccept:Q,clearOnSubmit:me=!0,onAttachmentReject:$,dropzone:k=!0,apiRef:n,...c}=l,f=D||M,v=b!=null,[L,pe]=e.useState(A),X=v?b:L,I=r!=null,[Z,q]=e.useState(o),ee=I?r:Z,he=e.useRef(null),se=e.useRef(null),fe=e.useRef(!1),te="attachments"in l,[Re,we]=e.useState(ue),j=e.useMemo(()=>te?_??[]:Re,[te,_,Re]),ie=e.useRef(new Set),be=t=>Array.isArray(t)?t:typeof t=="string"?t.split(",").map(a=>a.trim()):[],ne=be(J),Pe=be(Q).length>0?be(Q):ne,Ce=(t,a)=>{if(a.length===0)return!0;const g=t.type.toLowerCase(),E=t.name.toLowerCase();for(const y of a){const x=y.toLowerCase();if(x.includes("/")){const[le,ye]=x.split("/"),[ae,Ge]=g.split("/");if(le==="*"||le===ae&&(ye==="*"||ye===Ge))return!0}else if(x.startsWith(".")&&E.endsWith(x))return!0}return!1},We=t=>{const a=[],g=[],E=typeof w=="number"?Math.max(w-j.length,0):1/0;for(const y of t){if(a.length>=E){g.push({file:y,reason:"count"});continue}if(typeof d=="number"&&y.size>d){g.push({file:y,reason:"size"});continue}if(!Ce(y,ne)){g.push({file:y,reason:"type"});continue}const x=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,le=/\.(png|jpe?g|gif|webp|bmp|svg)$/i.test(y.name),ae=(y.type||"").toLowerCase().startsWith("image/")||le?URL.createObjectURL(y):void 0;ae&&ie.current.add(ae),a.push({id:x,name:y.name,size:y.size,type:y.type,file:y,url:ae,status:"idle"})}return{accepted:a,rejected:g}},ge=t=>{const{accepted:a,rejected:g}=We(t);if(a.length>0){const E=j.concat(a);te||we(E),K?.(E),I||q(!0),R?.(!0)}g.length>0&&$?.(g)},Ve=t=>{const a=x=>Pe.length===0?Ce(x,ne):Ce(x,Pe),g=[],E=[],y=typeof w=="number"?Math.max(w-j.length,0):1/0;for(const x of t){if(g.length>=y){E.push({file:x,reason:"count"});continue}if(typeof d=="number"&&x.size>d){E.push({file:x,reason:"size"});continue}if(!a(x)){E.push({file:x,reason:"type"});continue}g.push(x)}g.length>0&&ge(g),E.length>0&&$?.(E)};e.useEffect(()=>{const t=new Set(j.map(a=>a.url).filter(Boolean));for(const a of Array.from(ie.current))t.has(a)||(URL.revokeObjectURL(a),ie.current.delete(a))},[j]),e.useEffect(()=>{const t=ie.current;return()=>{for(const a of Array.from(t))URL.revokeObjectURL(a);t.clear()}},[]);const Ue=re?B:"div",Ke=e.useCallback(t=>{const a=t.relatedTarget,g=he.current;g&&(a&&g.contains(a)||fe.current||(X?.trim?.()??"").length===0&&j.length===0&&(I||q(!1),R?.(!1)))},[I,R,X,j]),{getRootProps:$e,getInputProps:qe,isDragActive:Ee,open:Te}=Ze({onDrop:(t,a)=>{if(t.length>0&&ge(t),a.length>0&&$){const g=a.map(({file:E,errors:y})=>{const x=y[0]?.code==="file-too-large"?"size":y[0]?.code==="file-invalid-type"?"type":"count";return{file:E,reason:x}});$(g)}},accept:ne.length>0?ne.reduce((t,a)=>(a.includes("/")?t[a]=[]:a.startsWith(".")&&(t[a]=[]),t),{}):void 0,multiple:z,maxSize:d,noClick:!0,noKeyboard:!0,disabled:!k||F});e.useImperativeHandle(n,()=>({focusTextarea:()=>se.current?.focus({preventScroll:!0}),openFilePicker:()=>{fe.current=!0,Te()}}),[Te]);const Se=e.useCallback(t=>{if(!(t instanceof Element))return!1;const a=t;return a.closest(".rt-ChatbarDropOverlay")?!0:!!a.closest('button, [role="button"], a[href], input, textarea, select, [contenteditable], [tabindex]:not([tabindex="-1"])')},[]),Ye=e.useCallback(t=>{F||Se(t.target)||t.pointerType==="mouse"&&t.button!==0||(t.preventDefault(),se.current?.focus({preventScroll:!0}))},[F,Se,se]);return e.createElement(Me.Provider,{value:{open:ee,setOpen:t=>{I||q(t),R?.(t)},isOpenControlled:I,value:X,setValue:t=>{v||pe(t),h?.(t)},isValueControlled:v,size:H,expandOn:P,minLines:T,maxLines:u,sendMode:C,disabled:F,readOnly:Y,onSubmit:O,rootRef:he,textareaRef:se,attachments:j,setAttachments:t=>{te||we(t),K?.(t)},isAttachmentsControlled:te,accept:J,multiple:z,maxAttachments:w,maxFileSize:d,paste:de,pasteAccept:Q,clearOnSubmit:me,onAttachmentReject:$,dropzone:k,appendFiles:ge,appendFilesFromPaste:Ve,fileDialogOpenRef:fe}},e.createElement(Ue,{...c,ref:t=>{typeof i=="function"?i(t):i&&(i.current=t),he.current=t},className:S("rt-ChatbarRoot",`rt-r-size-${H}`,s),style:{position:"relative",width:oe,maxWidth:G,...p},"data-state":ee?"open":"closed","data-disabled":F?"":void 0,"data-readonly":Y?"":void 0,"data-drop-active":k&&Ee?"":void 0,"data-accent-color":N,"data-radius":U,"data-panel-background":f,"data-material":f,"aria-expanded":ee,onBlurCapture:Ke},k&&e.createElement("input",{...qe()}),e.createElement("div",{...k?$e():{},style:{width:"100%",height:"100%"},onPointerDown:Ye},e.createElement(Xe,{className:S("rt-ChatbarBox",`rt-variant-${V??"surface"}`),style:{position:"relative"},"data-accent-color":N,"data-radius":U,"data-panel-background":f,"data-material":f},e.createElement("div",{className:"rt-ChatbarGrid"},m),k&&Ee&&e.createElement("div",{className:"rt-ChatbarDropOverlay"},e.createElement("div",{className:"rt-ChatbarDropContent"},e.createElement(ve,{color:"gray",size:H,weight:"medium"},"Drop files here to attach")))))))});Le.displayName="Chatbar.Root";const Fe=e.forwardRef((l,i)=>{const{className:s,style:p,asChild:m,onFocus:b,onInput:A,onChange:h,onPaste:r,onKeyDown:o,submitOnEnter:R=!1,rows:P,...T}=l,u=W(),{open:C,minLines:F,maxLines:Y,expandOn:O,disabled:H,readOnly:V,setOpen:N,setValue:U,textareaRef:M,value:D,isValueControlled:oe,sendMode:G,paste:re,appendFilesFromPaste:_,size:ue}=u,K=e.useRef(0),J=e.useRef(0),z=e.useRef(0),w=e.useCallback(()=>{const n=M.current;if(!n)return;const c=window.getComputedStyle(n),f=parseFloat(c.lineHeight)||20,v=parseFloat(c.paddingTop)||0,L=parseFloat(c.paddingBottom)||0;K.current=f,J.current=v+L,z.current=Math.ceil(1*f)+v+L},[M]),d=e.useCallback(n=>{const c=M.current;if(!c)return;c.style.height="auto",K.current===0&&w();const f=K.current,v=J.current,L=n??C,pe=L?F:1,X=L?Y:1,I=Math.ceil(pe*f)+v,Z=Math.ceil(X*f)+v,q=Math.max(c.scrollHeight,I),ee=Math.min(q,Z);c.style.height=`${ee}px`,q>Z?(c.style.overflowY="auto",c.style.maxHeight=`${Z}px`):(c.style.overflowY="hidden",c.style.maxHeight="none")},[C,F,Y,M,w]);xe(()=>{d()},[d,D,C]),xe(()=>{if(!(O==="overflow"||O==="both")||C)return;const n=M.current;if(!n)return;n.style.height="auto",z.current===0&&w(),n.scrollHeight>z.current+1&&(N(!0),d(!0),requestAnimationFrame(()=>d(!0)))},[D,O,C,N,M,w,d]),xe(()=>{w(),d()},[w,d,ue]),e.useEffect(()=>{const n=M.current;if(!n||typeof ResizeObserver>"u")return;let c=K.current;const f=new ResizeObserver(()=>{const v=window.getComputedStyle(n),L=parseFloat(v.lineHeight)||20;L!==c&&(c=L,w(),requestAnimationFrame(()=>d()))});return f.observe(n),()=>f.disconnect()},[M,w,d]),e.useEffect(()=>{},[]);const de=e.useCallback(n=>{H||V||((O==="focus"||O==="both")&&!C&&N(!0),b?.(n))},[H,V,O,C,N,b]),Q=e.useCallback(n=>{const c=n.currentTarget,f=c.value;U(f),(O==="overflow"||O==="both")&&!C&&(c.style.height="auto",z.current===0&&w(),c.scrollHeight>z.current+1&&(N(!0),d(!0),requestAnimationFrame(()=>d(!0)))),requestAnimationFrame(()=>d()),h?.(n)},[O,C,N,U,h,d,w]),me=e.useCallback(n=>{if(re){const f=Array.from(n.clipboardData?.items??[]).filter(v=>v.kind==="file").map(v=>v.getAsFile()).filter(v=>!!v);f.length>0&&(n.preventDefault(),_(f))}setTimeout(()=>{C?d():d(!0)},0),r?.(n)},[re,C,d,r,_]),$=e.useCallback(n=>{if(!R){o?.(n);return}if(n.key==="Enter"&&!n.shiftKey&&!n.altKey&&!n.ctrlKey&&!n.metaKey&&!n.nativeEvent.isComposing){if(H||V){o?.(n);return}if(G==="never"){o?.(n);return}const f=D.trim().length>0||u.attachments.length>0;if(G==="whenDirty"&&!f){o?.(n);return}n.preventDefault(),u.onSubmit?.({value:D,attachments:u.attachments}),u.clearOnSubmit&&(oe||U(""),u.setAttachments([]))}o?.(n)},[R,H,V,G,D,oe,U,u,o]),k=m?B:"textarea";return e.createElement("div",{className:S("rt-ChatbarField","rt-ChatbarTextarea",s)},e.createElement(k,{...T,ref:n=>{typeof i=="function"?i(n):i&&(i.current=n),M.current=n},className:"rt-ChatbarInput",value:D,onInput:A,onChange:Q,onFocus:de,onPaste:me,onKeyDown:$,disabled:H,readOnly:V,rows:C?F:1,spellCheck:T.spellCheck??!0,autoCorrect:T.autoCorrect??"on",style:p}))});Fe.displayName="Chatbar.Textarea";const He=e.forwardRef((l,i)=>{const{children:s,asChild:p,style:m,className:b,...A}=l;return W().open?null:e.createElement(p?B:"div",{...A,ref:i,className:S("rt-ChatbarInlineStart",b),style:m},s)});He.displayName="Chatbar.InlineStart";const Ne=e.forwardRef((l,i)=>{const{children:s,asChild:p,style:m,className:b,...A}=l;return W().open?null:e.createElement(p?B:"div",{...A,ref:i,className:S("rt-ChatbarInlineEnd",b),style:m},s)});Ne.displayName="Chatbar.InlineEnd";const De=e.forwardRef((l,i)=>{const{asChild:s,forceMount:p,renderAttachment:m,className:b,style:A,...h}=l,r=W();return!(r.attachments.length>0)&&!p?null:e.createElement(s?B:"div",{...h,ref:i,className:S("rt-ChatbarAttachmentsRow",b),style:A,role:"list","aria-label":h["aria-label"]??"Attachments"},e.createElement(Qe,{className:"rt-ChatbarScrollArea",scrollbars:"horizontal",size:"1"},e.createElement(ce,{align:"center",gap:"2",style:{minWidth:"fit-content"}},r.attachments.map(P=>e.createElement(Ae,{key:P.id,attachment:P,asChild:!!m},m?.(P))))))});De.displayName="Chatbar.AttachmentsRow";const Ae=e.forwardRef((l,i)=>{const{attachment:s,asChild:p,className:m,style:b,children:A,...h}=l,r=W(),o=p?B:"div",R=!!s.url&&s.type.startsWith("image/");return e.createElement(o,{...h,ref:i,className:S("rt-ChatbarAttachment",m),style:b,role:"listitem","data-kind":R?"image":"file",title:s.name},A??e.createElement(ce,{align:"center",gap:"2",pr:R?void 0:"6"},e.createElement("div",{className:"rt-ChatbarAttachmentPreview","aria-hidden":!0},R?e.createElement("img",{className:"rt-ChatbarAttachmentImage",src:s.url,alt:""}):e.createElement(Je,null)),!R&&e.createElement(ce,{direction:"column",gap:"0",style:{minWidth:0}},e.createElement(ve,{size:r.size,weight:"medium",style:{whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"}},s.name),e.createElement(ve,{size:"1",color:"gray"},Math.ceil(s.size/1024)," KB")),e.createElement(Oe,{className:"rt-ChatbarAttachmentRemove","aria-label":`Remove ${s.name}`,size:"1",variant:"classic",highContrast:!0,color:"gray",onClick:()=>r.setAttachments(r.attachments.filter(P=>P.id!==s.id))},e.createElement(_e,null))))});Ae.displayName="Chatbar.Attachment";const ze=e.forwardRef((l,i)=>{const{asChild:s,accept:p,multiple:m,className:b,style:A,...h}=l,r=W(),o=e.useRef(null),R=s?B:"button",P=p??r.accept,T=(Array.isArray(P)?P:P?.split(",")??[]).join(",");return e.useEffect(()=>{const u=()=>{r.fileDialogOpenRef.current=!1};return window.addEventListener("focus",u),()=>window.removeEventListener("focus",u)},[r.fileDialogOpenRef]),e.createElement(e.Fragment,null,e.createElement(R,{...h,ref:i,className:S("rt-ChatbarAttachTrigger",b),style:A,type:h.type??"button","aria-label":h["aria-label"]??"Add attachments",onPointerDown:u=>{r.fileDialogOpenRef.current=!0,h.onPointerDown?.(u)},onMouseDown:u=>{r.fileDialogOpenRef.current=!0,h.onMouseDown?.(u)},onClick:u=>{r.fileDialogOpenRef.current=!0,o.current&&o.current.click(),h.onClick?.(u)}}),e.createElement("input",{ref:o,type:"file",accept:T,multiple:m??r.multiple,tabIndex:-1,style:{display:"none"},onChange:u=>{const C=Array.from(u.currentTarget.files??[]);C.length>0&&r.appendFiles(C),r.fileDialogOpenRef.current=!1,u.currentTarget.value=""}}))});ze.displayName="Chatbar.AttachTrigger";const ke=e.forwardRef((l,i)=>{const{asChild:s,children:p,className:m,style:b,...A}=l;return W().open?e.createElement(s?B:"div",{...A,ref:i,className:S("rt-ChatbarRow",m),style:b},e.createElement(ce,{align:"center",justify:"between",width:"100%"},p)):null});ke.displayName="Chatbar.Row";const Ie=e.forwardRef((l,i)=>{const{className:s,style:p,...m}=l;return e.createElement("div",{...m,ref:i,className:S("rt-ChatbarRowStart",s),style:p})});Ie.displayName="Chatbar.RowStart";const je=e.forwardRef((l,i)=>{const{className:s,style:p,...m}=l;return e.createElement("div",{...m,ref:i,className:S("rt-ChatbarRowEnd",s),style:p})});je.displayName="Chatbar.RowEnd";const Be=e.forwardRef((l,i)=>{const{asChild:s,clearOnSend:p=!0,disabled:m,children:b,className:A,style:h,...r}=l,o=W(),P=o.value.trim().length>0||o.attachments.length>0,T=o.sendMode==="always"||o.sendMode==="whenDirty"&&P;if(o.sendMode==="never")return null;const u=C=>{o.disabled||o.readOnly||(o.onSubmit?.({value:o.value,attachments:o.attachments}),p&&(o.isValueControlled||o.setValue(""),o.clearOnSubmit&&o.setAttachments([])),r.onClick?.(C))};return e.createElement(Oe,{...r,ref:i,size:o.size,variant:o.open?"solid":"ghost",disabled:m||o.disabled||o.readOnly,className:S("rt-ChatbarSend",A),style:{opacity:T?1:0,pointerEvents:T?"auto":"none",...h},asChild:s,onClick:u,"aria-label":r["aria-label"]??"Send"},b??e.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"lucide lucide-arrow-right-icon lucide-arrow-right"},e.createElement("path",{d:"M5 12h14"}),e.createElement("path",{d:"m12 5 7 7-7 7"})))});Be.displayName="Chatbar.Send";export{ze as AttachTrigger,Ae as Attachment,De as AttachmentsRow,Ne as InlineEnd,He as InlineStart,Le as Root,ke as Row,je as RowEnd,Ie as RowStart,Be as Send,Fe as Textarea};
|
|
1
|
+
import*as e from"react";import T from"classnames";import{IconButton as Oe}from"./icon-button.js";import{CloseIcon as _e,FileTextIcon as Je}from"./icons.js";import{Flex as ce}from"./flex.js";import{ScrollArea as Qe}from"./scroll-area.js";import{Slot as B}from"./slot.js";import{Box as Xe}from"./box.js";import{Text as ve}from"./text.js";import{useDropzone as Ze}from"react-dropzone";const xe=typeof window<"u"?e.useLayoutEffect:e.useEffect,Me=e.createContext(null),W=()=>{const l=e.useContext(Me);if(!l)throw new Error("Chatbar context not found. Wrap parts in <Chatbar.Root>.");return l},Le=e.forwardRef((l,s)=>{const{className:r,style:p,children:m,value:C,defaultValue:R="",onValueChange:h,open:i,defaultOpen:w=!1,onOpenChange:g,expandOn:o="both",minLines:L=1,maxLines:u=6,sendMode:f="whenDirty",disabled:S,readOnly:V,onSubmit:O,size:H="2",variant:U,color:N,radius:K,panelBackground:M,material:D,width:oe,maxWidth:G,asChild:re,attachments:_,defaultAttachments:ue=[],onAttachmentsChange:$,accept:J,multiple:z=!0,maxAttachments:P,maxFileSize:d,paste:de=!0,pasteAccept:Q,clearOnSubmit:me=!0,onAttachmentReject:q,dropzone:k=!0,apiRef:n,...c}=l,b=D||M,x=C!=null,[F,pe]=e.useState(R),X=x?C:F,I=i!=null,[Z,Y]=e.useState(w),ee=I?i:Z,he=e.useRef(null),se=e.useRef(null),fe=e.useRef(!1),te="attachments"in l,[Re,we]=e.useState(ue),j=e.useMemo(()=>te?_??[]:Re,[te,_,Re]),ie=e.useRef(new Set),be=t=>Array.isArray(t)?t:typeof t=="string"?t.split(",").map(a=>a.trim()):[],ne=be(J),Pe=be(Q).length>0?be(Q):ne,Ce=(t,a)=>{if(a.length===0)return!0;const y=t.type.toLowerCase(),E=t.name.toLowerCase();for(const v of a){const A=v.toLowerCase();if(A.includes("/")){const[le,ye]=A.split("/"),[ae,Ge]=y.split("/");if(le==="*"||le===ae&&(ye==="*"||ye===Ge))return!0}else if(A.startsWith(".")&&E.endsWith(A))return!0}return!1},We=t=>{const a=[],y=[],E=typeof P=="number"?Math.max(P-j.length,0):1/0;for(const v of t){if(a.length>=E){y.push({file:v,reason:"count"});continue}if(typeof d=="number"&&v.size>d){y.push({file:v,reason:"size"});continue}if(!Ce(v,ne)){y.push({file:v,reason:"type"});continue}const A=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,le=/\.(png|jpe?g|gif|webp|bmp|svg)$/i.test(v.name),ae=(v.type||"").toLowerCase().startsWith("image/")||le?URL.createObjectURL(v):void 0;ae&&ie.current.add(ae),a.push({id:A,name:v.name,size:v.size,type:v.type,file:v,url:ae,status:"idle"})}return{accepted:a,rejected:y}},ge=t=>{const{accepted:a,rejected:y}=We(t);if(a.length>0){const E=j.concat(a);te||we(E),$?.(E),I||Y(!0),g?.(!0)}y.length>0&&q?.(y)},Ve=t=>{const a=A=>Pe.length===0?Ce(A,ne):Ce(A,Pe),y=[],E=[],v=typeof P=="number"?Math.max(P-j.length,0):1/0;for(const A of t){if(y.length>=v){E.push({file:A,reason:"count"});continue}if(typeof d=="number"&&A.size>d){E.push({file:A,reason:"size"});continue}if(!a(A)){E.push({file:A,reason:"type"});continue}y.push(A)}y.length>0&&ge(y),E.length>0&&q?.(E)};e.useEffect(()=>{const t=new Set(j.map(a=>a.url).filter(Boolean));for(const a of Array.from(ie.current))t.has(a)||(URL.revokeObjectURL(a),ie.current.delete(a))},[j]),e.useEffect(()=>{const t=ie.current;return()=>{for(const a of Array.from(t))URL.revokeObjectURL(a);t.clear()}},[]);const Ue=re?B:"div",Ke=e.useCallback(t=>{const a=t.relatedTarget,y=he.current;y&&(a&&y.contains(a)||fe.current||(X?.trim?.()??"").length===0&&j.length===0&&(I||Y(!1),g?.(!1)))},[I,g,X,j]),{getRootProps:$e,getInputProps:qe,isDragActive:Ee,open:Te}=Ze({onDrop:(t,a)=>{if(t.length>0&&ge(t),a.length>0&&q){const y=a.map(({file:E,errors:v})=>{const A=v[0]?.code==="file-too-large"?"size":v[0]?.code==="file-invalid-type"?"type":"count";return{file:E,reason:A}});q(y)}},accept:ne.length>0?ne.reduce((t,a)=>(a.includes("/")?t[a]=[]:a.startsWith(".")&&(t[a]=[]),t),{}):void 0,multiple:z,maxSize:d,noClick:!0,noKeyboard:!0,disabled:!k||S});e.useImperativeHandle(n,()=>({focusTextarea:()=>se.current?.focus({preventScroll:!0}),openFilePicker:()=>{fe.current=!0,Te()}}),[Te]);const Se=e.useCallback(t=>{if(!(t instanceof Element))return!1;const a=t;return a.closest(".rt-ChatbarDropOverlay")?!0:!!a.closest('button, [role="button"], a[href], input, textarea, select, [contenteditable], [tabindex]:not([tabindex="-1"])')},[]),Ye=e.useCallback(t=>{S||Se(t.target)||t.pointerType==="mouse"&&t.button!==0||(t.preventDefault(),se.current?.focus({preventScroll:!0}))},[S,Se,se]);return e.createElement(Me.Provider,{value:{open:ee,setOpen:t=>{I||Y(t),g?.(t)},isOpenControlled:I,value:X,setValue:t=>{x||pe(t),h?.(t)},isValueControlled:x,size:H,expandOn:o,minLines:L,maxLines:u,sendMode:f,disabled:S,readOnly:V,onSubmit:O,rootRef:he,textareaRef:se,attachments:j,setAttachments:t=>{te||we(t),$?.(t)},isAttachmentsControlled:te,accept:J,multiple:z,maxAttachments:P,maxFileSize:d,paste:de,pasteAccept:Q,clearOnSubmit:me,onAttachmentReject:q,dropzone:k,appendFiles:ge,appendFilesFromPaste:Ve,fileDialogOpenRef:fe}},e.createElement(Ue,{...c,ref:t=>{typeof s=="function"?s(t):s&&(s.current=t),he.current=t},className:T("rt-ChatbarRoot",`rt-r-size-${H}`,r),style:{position:"relative",width:oe,maxWidth:G,...p},"data-state":ee?"open":"closed","data-disabled":S?"":void 0,"data-readonly":V?"":void 0,"data-drop-active":k&&Ee?"":void 0,"data-accent-color":N,"data-radius":K,"data-panel-background":b,"data-material":b,"aria-expanded":ee,onBlurCapture:Ke},k&&e.createElement("input",{...qe()}),e.createElement("div",{...k?$e():{},style:{width:"100%",height:"100%"},onPointerDown:Ye},e.createElement(Xe,{className:T("rt-ChatbarBox",`rt-variant-${U??"surface"}`),style:{position:"relative"},"data-accent-color":N,"data-radius":K,"data-panel-background":b,"data-material":b},e.createElement("div",{className:"rt-ChatbarGrid"},m),k&&Ee&&e.createElement("div",{className:"rt-ChatbarDropOverlay"},e.createElement("div",{className:"rt-ChatbarDropContent"},e.createElement(ve,{color:"gray",size:H,weight:"medium"},"Drop files here to attach")))))))});Le.displayName="Chatbar.Root";const Fe=e.forwardRef((l,s)=>{const{className:r,style:p,asChild:m,onFocus:C,onInput:R,onChange:h,onPaste:i,onKeyDown:w,submitOnEnter:g=!1,rows:o,...L}=l,u=W(),{open:f,minLines:S,maxLines:V,expandOn:O,disabled:H,readOnly:U,setOpen:N,setValue:K,textareaRef:M,value:D,isValueControlled:oe,sendMode:G,paste:re,appendFilesFromPaste:_,size:ue}=u,$=e.useRef(0),J=e.useRef(0),z=e.useRef(0),P=e.useCallback(()=>{const n=M.current;if(!n)return;const c=window.getComputedStyle(n),b=parseFloat(c.lineHeight)||20,x=parseFloat(c.paddingTop)||0,F=parseFloat(c.paddingBottom)||0;$.current=b,J.current=x+F,z.current=Math.ceil(1*b)+x+F},[M]),d=e.useCallback(n=>{const c=M.current;if(!c)return;c.style.height="auto",$.current===0&&P();const b=$.current,x=J.current,F=n??f,pe=F?S:1,X=F?V:1,I=Math.ceil(pe*b)+x,Z=Math.ceil(X*b)+x,Y=Math.max(c.scrollHeight,I),ee=Math.min(Y,Z);c.style.height=`${ee}px`,Y>Z?(c.style.overflowY="auto",c.style.maxHeight=`${Z}px`):(c.style.overflowY="hidden",c.style.maxHeight="none")},[f,S,V,M,P]);xe(()=>{d()},[d,D,f]),xe(()=>{if(!(O==="overflow"||O==="both")||f)return;const n=M.current;if(!n)return;n.style.height="auto",z.current===0&&P(),n.scrollHeight>z.current+1&&(N(!0),d(!0),requestAnimationFrame(()=>d(!0)))},[D,O,f,N,M,P,d]),xe(()=>{P(),d()},[P,d,ue]),e.useEffect(()=>{const n=M.current;if(!n||typeof ResizeObserver>"u")return;let c=$.current;const b=new ResizeObserver(()=>{const x=window.getComputedStyle(n),F=parseFloat(x.lineHeight)||20;F!==c&&(c=F,P(),requestAnimationFrame(()=>d()))});return b.observe(n),()=>b.disconnect()},[M,P,d]),e.useEffect(()=>{},[]);const de=e.useCallback(n=>{H||U||((O==="focus"||O==="both")&&!f&&N(!0),C?.(n))},[H,U,O,f,N,C]),Q=e.useCallback(n=>{const c=n.currentTarget,b=c.value;K(b),(O==="overflow"||O==="both")&&!f&&(c.style.height="auto",z.current===0&&P(),c.scrollHeight>z.current+1&&(N(!0),d(!0),requestAnimationFrame(()=>d(!0)))),requestAnimationFrame(()=>d()),h?.(n)},[O,f,N,K,h,d,P]),me=e.useCallback(n=>{if(re){const b=Array.from(n.clipboardData?.items??[]).filter(x=>x.kind==="file").map(x=>x.getAsFile()).filter(x=>!!x);b.length>0&&(n.preventDefault(),_(b))}setTimeout(()=>{f?d():d(!0)},0),i?.(n)},[re,f,d,i,_]),q=e.useCallback(n=>{if(!g){w?.(n);return}if(n.key==="Enter"&&!n.shiftKey&&!n.altKey&&!n.ctrlKey&&!n.metaKey&&!n.nativeEvent.isComposing){if(H||U){w?.(n);return}if(G==="never"){w?.(n);return}const b=D.trim().length>0||u.attachments.length>0;if(G==="whenDirty"&&!b){w?.(n);return}n.preventDefault(),u.onSubmit?.({value:D,attachments:u.attachments}),u.clearOnSubmit&&(oe||K(""),u.setAttachments([]))}w?.(n)},[g,H,U,G,D,oe,K,u,w]),k=m?B:"textarea";return e.createElement("div",{className:T("rt-ChatbarField","rt-ChatbarTextarea",r)},e.createElement(k,{...L,ref:n=>{typeof s=="function"?s(n):s&&(s.current=n),M.current=n},className:"rt-ChatbarInput",value:D,onInput:R,onChange:Q,onFocus:de,onPaste:me,onKeyDown:q,disabled:H,readOnly:U,rows:f?S:1,spellCheck:L.spellCheck??!0,autoCorrect:L.autoCorrect??"on",style:p}))});Fe.displayName="Chatbar.Textarea";const He=e.forwardRef((l,s)=>{const{children:r,asChild:p,style:m,className:C,...R}=l;return W().open?null:e.createElement(p?B:"div",{...R,ref:s,className:T("rt-ChatbarInlineStart",C),style:m},r)});He.displayName="Chatbar.InlineStart";const Ne=e.forwardRef((l,s)=>{const{children:r,asChild:p,style:m,className:C,...R}=l;return W().open?null:e.createElement(p?B:"div",{...R,ref:s,className:T("rt-ChatbarInlineEnd",C),style:m},r)});Ne.displayName="Chatbar.InlineEnd";const De=e.forwardRef((l,s)=>{const{asChild:r,forceMount:p,renderAttachment:m,className:C,style:R,...h}=l,i=W();return!(i.attachments.length>0)&&!p?null:e.createElement(r?B:"div",{...h,ref:s,className:T("rt-ChatbarAttachmentsRow",C),style:R,role:"list","aria-label":h["aria-label"]??"Attachments"},e.createElement(Qe,{className:"rt-ChatbarScrollArea",scrollbars:"horizontal",size:"1"},e.createElement(ce,{align:"center",gap:"2",style:{minWidth:"fit-content"}},i.attachments.map(o=>e.createElement(Ae,{key:o.id,attachment:o,asChild:!!m},m?.(o))))))});De.displayName="Chatbar.AttachmentsRow";const Ae=e.forwardRef((l,s)=>{const{attachment:r,asChild:p,className:m,style:C,children:R,...h}=l,i=W(),w=p?B:"div",g=!!r.url&&r.type.startsWith("image/");return e.createElement(w,{...h,ref:s,className:T("rt-ChatbarAttachment",m),style:C,role:"listitem","data-kind":g?"image":"file",title:r.name},R??e.createElement(ce,{align:"center",gap:"2",pr:g?void 0:"6"},e.createElement("div",{className:"rt-ChatbarAttachmentPreview","aria-hidden":!0},g?e.createElement("img",{className:"rt-ChatbarAttachmentImage",src:r.url,alt:""}):e.createElement(Je,null)),!g&&e.createElement(ce,{direction:"column",gap:"0",style:{minWidth:0}},e.createElement(ve,{size:i.size,weight:"medium",style:{whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"}},r.name),e.createElement(ve,{size:"1",color:"gray"},Math.ceil(r.size/1024)," KB")),e.createElement(Oe,{className:"rt-ChatbarAttachmentRemove","aria-label":`Remove ${r.name}`,size:"1",variant:"classic",highContrast:!0,color:"gray",onClick:()=>i.setAttachments(i.attachments.filter(o=>o.id!==r.id))},e.createElement(_e,null))))});Ae.displayName="Chatbar.Attachment";const ze=e.forwardRef((l,s)=>{const{asChild:r,accept:p,multiple:m,className:C,style:R,...h}=l,i=W(),w=e.useRef(null),g=r?B:"button",o=p??i.accept,L=(Array.isArray(o)?o:o?.split(",")??[]).join(",");return e.useEffect(()=>{const u=()=>{i.fileDialogOpenRef.current=!1};return window.addEventListener("focus",u),()=>window.removeEventListener("focus",u)},[i.fileDialogOpenRef]),e.createElement(e.Fragment,null,e.createElement(g,{...h,ref:s,className:T("rt-ChatbarAttachTrigger",C),style:R,type:h.type??"button","aria-label":h["aria-label"]??"Add attachments",onPointerDown:u=>{i.fileDialogOpenRef.current=!0,h.onPointerDown?.(u)},onMouseDown:u=>{i.fileDialogOpenRef.current=!0,h.onMouseDown?.(u)},onClick:u=>{i.fileDialogOpenRef.current=!0,w.current&&w.current.click(),h.onClick?.(u)}}),e.createElement("input",{ref:w,type:"file",accept:L,multiple:m??i.multiple,tabIndex:-1,style:{display:"none"},onChange:u=>{const f=Array.from(u.currentTarget.files??[]);f.length>0&&i.appendFiles(f),i.fileDialogOpenRef.current=!1,u.currentTarget.value=""}}))});ze.displayName="Chatbar.AttachTrigger";const ke=e.forwardRef((l,s)=>{const{asChild:r,children:p,className:m,style:C,...R}=l;return W().open?e.createElement(r?B:"div",{...R,ref:s,className:T("rt-ChatbarRow",m),style:C},e.createElement(ce,{align:"center",justify:"between",width:"100%"},p)):null});ke.displayName="Chatbar.Row";const Ie=e.forwardRef((l,s)=>{const{className:r,style:p,...m}=l;return e.createElement("div",{...m,ref:s,className:T("rt-ChatbarRowStart",r),style:p})});Ie.displayName="Chatbar.RowStart";const je=e.forwardRef((l,s)=>{const{className:r,style:p,...m}=l;return e.createElement("div",{...m,ref:s,className:T("rt-ChatbarRowEnd",r),style:p})});je.displayName="Chatbar.RowEnd";const Be=e.forwardRef((l,s)=>{const{asChild:r,clearOnSend:p=!0,disabled:m,children:C,className:R,style:h,size:i,variant:w,...g}=l,o=W(),u=o.value.trim().length>0||o.attachments.length>0,f=o.sendMode==="always"||o.sendMode==="whenDirty"&&u;if(o.sendMode==="never")return null;const S=V=>{o.disabled||o.readOnly||(o.onSubmit?.({value:o.value,attachments:o.attachments}),p&&(o.isValueControlled||o.setValue(""),o.clearOnSubmit&&o.setAttachments([])),g.onClick?.(V))};return e.createElement(Oe,{...g,ref:s,size:i??o.size,variant:w??(o.open?"solid":"ghost"),disabled:m||o.disabled||o.readOnly,className:T("rt-ChatbarSend",R),style:{opacity:f?1:0,pointerEvents:f?"auto":"none",...h},asChild:r,onClick:S,"aria-label":g["aria-label"]??"Send"},C??e.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"lucide lucide-arrow-right-icon lucide-arrow-right"},e.createElement("path",{d:"M5 12h14"}),e.createElement("path",{d:"m12 5 7 7-7 7"})))});Be.displayName="Chatbar.Send";export{ze as AttachTrigger,Ae as Attachment,De as AttachmentsRow,Ne as InlineEnd,He as InlineStart,Le as Root,ke as Row,je as RowEnd,Ie as RowStart,Be as Send,Fe 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 { Box } from './box.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 = 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 // Guards\n fileDialogOpenRef: React.MutableRefObject<boolean>;\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 /** Accent color for the control (matches TextArea) */\n color?: string;\n /** Optional radius override (matches TextArea) */\n radius?: string | number;\n /** Panel/material translucency flags (matches TextArea) */\n panelBackground?: 'solid' | 'translucent';\n material?: 'solid' | 'translucent';\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 /**\n * Optional API ref to control Chatbar imperatively without relying on DOM refs.\n * Provides methods to focus the textarea and open the file picker.\n */\n apiRef?: React.Ref<ChatbarApi>;\n}\n\ntype RootElement = React.ElementRef<'div'>;\n/** Imperative API for Chatbar.Root */\nexport interface ChatbarApi {\n /** Focus the textarea input */\n focusTextarea: () => void;\n /** Open the file picker dialog (respects accept/multiple) */\n openFilePicker: () => void;\n}\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 extends ComponentPropsWithout<'div', RemovedProps | 'onSubmit'>, 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 color,\n radius,\n panelBackground,\n material,\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 apiRef,\n ...divProps\n } = props;\n const effectiveMaterial = material || panelBackground;\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 const fileDialogOpenRef = React.useRef<boolean>(false);\n\n // Attachments state\n // Treat `attachments` as controlled if the prop is provided, even if its value is `undefined`.\n // This avoids switching between controlled and uncontrolled when a consumer sets\n // `attachments={undefined}` to clear attachments. In that case we normalize to an empty array.\n const isAttachmentsControlled = 'attachments' in props;\n const [attachmentsUncontrolled, setAttachmentsUncontrolled] = React.useState<ChatbarAttachment[]>(defaultAttachments);\n const attachments = React.useMemo(\n () => (isAttachmentsControlled ? ((attachmentsProp ?? []) as ChatbarAttachment[]) : attachmentsUncontrolled),\n [isAttachmentsControlled, attachmentsProp, attachmentsUncontrolled],\n );\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) => (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))) 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 = typeof maxAttachments === 'number' ? Math.max(maxAttachments - attachments.length, 0) : 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 // Ensure chatbar expands when attachments are added\n if (!isOpenControlled) setOpenUncontrolled(true);\n onOpenChangeProp?.(true);\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 = typeof maxAttachments === 'number' ? Math.max(maxAttachments - attachments.length, 0) : 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 const urlSet = generatedUrlSetRef.current;\n return () => {\n for (const url of Array.from(urlSet)) {\n URL.revokeObjectURL(url);\n }\n urlSet.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 // If native file dialog is open, avoid collapsing on blur\n if (fileDialogOpenRef.current) return;\n // Collapse when leaving the root if the value is empty\n // Only collapse when both message and attachments are empty\n if ((value?.trim?.() ?? '').length === 0 && attachments.length === 0) {\n if (!isOpenControlled) setOpenUncontrolled(false);\n onOpenChangeProp?.(false);\n }\n },\n [isOpenControlled, onOpenChangeProp, value, attachments],\n );\n\n // Dropzone functionality\n const {\n getRootProps,\n getInputProps,\n isDragActive,\n open: openFileDialog,\n } = 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 = errors[0]?.code === 'file-too-large' ? 'size' : errors[0]?.code === 'file-invalid-type' ? 'type' : '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 // Expose imperative API via apiRef (non-breaking; forwardedRef still receives the DOM node)\n React.useImperativeHandle(\n apiRef,\n () => ({\n focusTextarea: () => textareaRef.current?.focus({ preventScroll: true }),\n openFilePicker: () => {\n // Guard against blur-collapse while native dialog is open\n fileDialogOpenRef.current = true;\n openFileDialog();\n },\n }),\n [openFileDialog],\n );\n\n // Click-to-focus: focus textarea when clicking non-interactive areas inside the container\n const isInteractiveTarget = React.useCallback((target: EventTarget | null) => {\n if (!(target instanceof Element)) return false;\n const el = target as Element;\n if (el.closest('.rt-ChatbarDropOverlay')) return true;\n return !!el.closest('button, [role=\"button\"], a[href], input, textarea, select, [contenteditable], [tabindex]:not([tabindex=\"-1\"])');\n }, []);\n\n const handleContainerPointerDown = React.useCallback(\n (event: React.PointerEvent) => {\n if (disabled) return;\n if (isInteractiveTarget(event.target)) return;\n if (event.pointerType === 'mouse' && event.button !== 0) return;\n event.preventDefault();\n textareaRef.current?.focus({ preventScroll: true });\n },\n [disabled, isInteractiveTarget, textareaRef],\n );\n\n // Clicking the label-wrapped Card will naturally focus the nested textarea.\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 fileDialogOpenRef,\n }}\n >\n <Comp\n {...divProps}\n ref={(node: HTMLDivElement) => {\n if (typeof forwardedRef === 'function') forwardedRef(node);\n else if (forwardedRef) (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 data-accent-color={color}\n data-radius={radius as any}\n data-panel-background={effectiveMaterial}\n data-material={effectiveMaterial}\n aria-expanded={open}\n onBlurCapture={handleBlurCapture}\n >\n {dropzone && <input {...getInputProps()} />}\n <div {...(dropzone ? getRootProps() : {})} style={{ width: '100%', height: '100%' }} onPointerDown={handleContainerPointerDown}>\n <Box\n className={classNames('rt-ChatbarBox', `rt-variant-${variant ?? 'surface'}`)}\n style={{ position: 'relative' }}\n data-accent-color={color}\n data-radius={radius as any}\n data-panel-background={effectiveMaterial}\n data-material={effectiveMaterial}\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 </Box>\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 { className, style, asChild, onFocus, onInput, onChange, onPaste, onKeyDown, submitOnEnter = false, rows, ...textareaProps } = props;\n const ctx = useChatbarContext();\n const { open, minLines, maxLines, expandOn, disabled, readOnly, setOpen, setValue, textareaRef, value, isValueControlled, sendMode, paste, appendFilesFromPaste, size } = 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 // Auto-open on external value changes when content overflows one line\n useIsomorphicLayoutEffect(() => {\n if (!(expandOn === 'overflow' || expandOn === 'both')) return;\n if (open) return;\n const el = textareaRef.current;\n if (!el) return;\n // Measure overflow against compact (1-line) height\n el.style.height = 'auto';\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\n updateHeight(true);\n requestAnimationFrame(() => updateHeight(true));\n }\n }, [value, expandOn, open, setOpen, textareaRef, recomputeMetrics, updateHeight]);\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 = textareaProps['aria-label'] != null || textareaProps['aria-labelledby'] != null;\n if (!hasLabel) {\n console.warn('[Chatbar.Textarea] Provide aria-label or aria-labelledby to ensure the control has an accessible name.');\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 // Prevent pasting the file name or any text representation when files are present\n event.preventDefault();\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 (event.key === 'Enter' && !event.shiftKey && !event.altKey && !event.ctrlKey && !event.metaKey && !event.nativeEvent.isComposing) {\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 [submitOnEnter, disabled, readOnly, sendMode, value, isValueControlled, setValue, ctx, onKeyDown],\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) (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 {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarInlineStart', className)} style={style}>\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 {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarInlineEnd', className)} style={style}>\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>((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 {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarAttachmentsRow', className)} style={style} role=\"list\" aria-label={divProps['aria-label'] ?? 'Attachments'}>\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});\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 {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarAttachment', className)} style={style} role=\"listitem\" data-kind={isImage ? 'image' : 'file'} title={attachment.name}>\n {children ?? (\n // <Card size={ctx.size} variant=\"surface\">\n <Flex align=\"center\" gap=\"2\" pr={!isImage ? '6' : undefined}>\n <div className=\"rt-ChatbarAttachmentPreview\" aria-hidden>\n {isImage ? <img className=\"rt-ChatbarAttachmentImage\" src={attachment.url} alt=\"\" /> : <FileTextIcon />}\n </div>\n {!isImage && (\n <Flex direction=\"column\" gap=\"0\" style={{ minWidth: 0 }}>\n <Text size={ctx.size} weight=\"medium\" style={{ whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>\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={() => ctx.setAttachments(ctx.attachments.filter((a) => a.id !== attachment.id))}\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>((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 // Prefer Chatbar.Root's accept when a local accept is not provided\n const mergedAccept = accept ?? ctx.accept;\n const actualAccept = (Array.isArray(mergedAccept) ? mergedAccept : (mergedAccept?.split(',') ?? [])).join(',');\n React.useEffect(() => {\n const handleWindowFocus = () => {\n // Reset guard when window regains focus after file dialog closes\n ctx.fileDialogOpenRef.current = false;\n };\n window.addEventListener('focus', handleWindowFocus);\n return () => window.removeEventListener('focus', handleWindowFocus);\n }, [ctx.fileDialogOpenRef]);\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 onPointerDown={(e: any) => {\n // Set guard before blur occurs (Safari fires blur before click)\n ctx.fileDialogOpenRef.current = true;\n buttonProps.onPointerDown?.(e);\n }}\n onMouseDown={(e: any) => {\n // Fallback for environments without Pointer Events\n ctx.fileDialogOpenRef.current = true;\n buttonProps.onMouseDown?.(e);\n }}\n onClick={(e: any) => {\n // Ensure file input opens reliably by clicking it first\n ctx.fileDialogOpenRef.current = true;\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 // File dialog closed; allow normal blur handling\n ctx.fileDialogOpenRef.current = false;\n // Reset input value to allow selecting the same file again\n e.currentTarget.value = '';\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 {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarRow', className)} style={style}>\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'>>((props, forwardedRef) => {\n const { className, style, ...divProps } = props;\n return <div {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarRowStart', className)} style={style} />;\n});\nRowStart.displayName = 'Chatbar.RowStart';\n\nconst RowEnd = React.forwardRef<HTMLDivElement, React.ComponentPropsWithoutRef<'div'>>((props, forwardedRef) => {\n const { className, style, ...divProps } = props;\n return <div {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarRowEnd', className)} style={style} />;\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 { asChild, clearOnSend = true, disabled, children, className, style, ...buttonProps } = 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 ?? (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"lucide lucide-arrow-right-icon lucide-arrow-right\"\n >\n <path d=\"M5 12h14\" />\n <path d=\"m12 5 7 7-7 7\" />\n </svg>\n )}\n </IconButton>\n );\n});\nSend.displayName = 'Chatbar.Send';\n\nexport { Root, Textarea, InlineStart, InlineEnd, AttachmentsRow, Attachment, AttachTrigger, Row, RowStart, RowEnd, Send };\nexport type { RootProps as ChatbarRootProps, TextareaProps as ChatbarTextareaProps, RowProps as ChatbarRowProps, SendProps as ChatbarSendProps, ChatbarAttachment };\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["React", "classNames", "IconButton", "CloseIcon", "FileTextIcon", "Flex", "ScrollArea", "Slot", "Box", "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", "color", "radius", "panelBackground", "material", "width", "maxWidth", "asChild", "attachmentsProp", "defaultAttachments", "onAttachmentsChange", "accept", "multiple", "maxAttachments", "maxFileSize", "paste", "pasteAccept", "clearOnSubmit", "onAttachmentReject", "dropzone", "apiRef", "divProps", "effectiveMaterial", "isValueControlled", "valueUncontrolled", "setValueUncontrolled", "value", "isOpenControlled", "openUncontrolled", "setOpenUncontrolled", "open", "rootRef", "textareaRef", "fileDialogOpenRef", "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", "urlSet", "Comp", "handleBlurCapture", "event", "nextTarget", "rootEl", "getRootProps", "getInputProps", "isDragActive", "openFileDialog", "rejectedFiles", "rejections", "errors", "reason", "acc", "pattern", "isInteractiveTarget", "target", "el", "handleContainerPointerDown", "node", "Textarea", "onFocus", "onInput", "onChange", "onPaste", "onKeyDown", "submitOnEnter", "rows", "textareaProps", "setOpen", "setValue", "lineHeightRef", "paddingRef", "compactHeightRef", "recomputeMetrics", "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", "a", "AttachTrigger", "buttonProps", "inputRef", "mergedAccept", "actualAccept", "handleWindowFocus", "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 { Box } from './box.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 = 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 // Guards\n fileDialogOpenRef: React.MutableRefObject<boolean>;\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 /** Accent color for the control (matches TextArea) */\n color?: string;\n /** Optional radius override (matches TextArea) */\n radius?: string | number;\n /** Panel/material translucency flags (matches TextArea) */\n panelBackground?: 'solid' | 'translucent';\n material?: 'solid' | 'translucent';\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 /**\n * Optional API ref to control Chatbar imperatively without relying on DOM refs.\n * Provides methods to focus the textarea and open the file picker.\n */\n apiRef?: React.Ref<ChatbarApi>;\n}\n\ntype RootElement = React.ElementRef<'div'>;\n/** Imperative API for Chatbar.Root */\nexport interface ChatbarApi {\n /** Focus the textarea input */\n focusTextarea: () => void;\n /** Open the file picker dialog (respects accept/multiple) */\n openFilePicker: () => void;\n}\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 extends ComponentPropsWithout<'div', RemovedProps | 'onSubmit'>, 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 color,\n radius,\n panelBackground,\n material,\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 apiRef,\n ...divProps\n } = props;\n const effectiveMaterial = material || panelBackground;\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 const fileDialogOpenRef = React.useRef<boolean>(false);\n\n // Attachments state\n // Treat `attachments` as controlled if the prop is provided, even if its value is `undefined`.\n // This avoids switching between controlled and uncontrolled when a consumer sets\n // `attachments={undefined}` to clear attachments. In that case we normalize to an empty array.\n const isAttachmentsControlled = 'attachments' in props;\n const [attachmentsUncontrolled, setAttachmentsUncontrolled] = React.useState<ChatbarAttachment[]>(defaultAttachments);\n const attachments = React.useMemo(\n () => (isAttachmentsControlled ? ((attachmentsProp ?? []) as ChatbarAttachment[]) : attachmentsUncontrolled),\n [isAttachmentsControlled, attachmentsProp, attachmentsUncontrolled],\n );\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) => (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))) 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 = typeof maxAttachments === 'number' ? Math.max(maxAttachments - attachments.length, 0) : 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 // Ensure chatbar expands when attachments are added\n if (!isOpenControlled) setOpenUncontrolled(true);\n onOpenChangeProp?.(true);\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 = typeof maxAttachments === 'number' ? Math.max(maxAttachments - attachments.length, 0) : 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 const urlSet = generatedUrlSetRef.current;\n return () => {\n for (const url of Array.from(urlSet)) {\n URL.revokeObjectURL(url);\n }\n urlSet.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 // If native file dialog is open, avoid collapsing on blur\n if (fileDialogOpenRef.current) return;\n // Collapse when leaving the root if the value is empty\n // Only collapse when both message and attachments are empty\n if ((value?.trim?.() ?? '').length === 0 && attachments.length === 0) {\n if (!isOpenControlled) setOpenUncontrolled(false);\n onOpenChangeProp?.(false);\n }\n },\n [isOpenControlled, onOpenChangeProp, value, attachments],\n );\n\n // Dropzone functionality\n const {\n getRootProps,\n getInputProps,\n isDragActive,\n open: openFileDialog,\n } = 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 = errors[0]?.code === 'file-too-large' ? 'size' : errors[0]?.code === 'file-invalid-type' ? 'type' : '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 // Expose imperative API via apiRef (non-breaking; forwardedRef still receives the DOM node)\n React.useImperativeHandle(\n apiRef,\n () => ({\n focusTextarea: () => textareaRef.current?.focus({ preventScroll: true }),\n openFilePicker: () => {\n // Guard against blur-collapse while native dialog is open\n fileDialogOpenRef.current = true;\n openFileDialog();\n },\n }),\n [openFileDialog],\n );\n\n // Click-to-focus: focus textarea when clicking non-interactive areas inside the container\n const isInteractiveTarget = React.useCallback((target: EventTarget | null) => {\n if (!(target instanceof Element)) return false;\n const el = target as Element;\n if (el.closest('.rt-ChatbarDropOverlay')) return true;\n return !!el.closest('button, [role=\"button\"], a[href], input, textarea, select, [contenteditable], [tabindex]:not([tabindex=\"-1\"])');\n }, []);\n\n const handleContainerPointerDown = React.useCallback(\n (event: React.PointerEvent) => {\n if (disabled) return;\n if (isInteractiveTarget(event.target)) return;\n if (event.pointerType === 'mouse' && event.button !== 0) return;\n event.preventDefault();\n textareaRef.current?.focus({ preventScroll: true });\n },\n [disabled, isInteractiveTarget, textareaRef],\n );\n\n // Clicking the label-wrapped Card will naturally focus the nested textarea.\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 fileDialogOpenRef,\n }}\n >\n <Comp\n {...divProps}\n ref={(node: HTMLDivElement) => {\n if (typeof forwardedRef === 'function') forwardedRef(node);\n else if (forwardedRef) (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 data-accent-color={color}\n data-radius={radius as any}\n data-panel-background={effectiveMaterial}\n data-material={effectiveMaterial}\n aria-expanded={open}\n onBlurCapture={handleBlurCapture}\n >\n {dropzone && <input {...getInputProps()} />}\n <div {...(dropzone ? getRootProps() : {})} style={{ width: '100%', height: '100%' }} onPointerDown={handleContainerPointerDown}>\n <Box\n className={classNames('rt-ChatbarBox', `rt-variant-${variant ?? 'surface'}`)}\n style={{ position: 'relative' }}\n data-accent-color={color}\n data-radius={radius as any}\n data-panel-background={effectiveMaterial}\n data-material={effectiveMaterial}\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 </Box>\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 { className, style, asChild, onFocus, onInput, onChange, onPaste, onKeyDown, submitOnEnter = false, rows, ...textareaProps } = props;\n const ctx = useChatbarContext();\n const { open, minLines, maxLines, expandOn, disabled, readOnly, setOpen, setValue, textareaRef, value, isValueControlled, sendMode, paste, appendFilesFromPaste, size } = 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 // Auto-open on external value changes when content overflows one line\n useIsomorphicLayoutEffect(() => {\n if (!(expandOn === 'overflow' || expandOn === 'both')) return;\n if (open) return;\n const el = textareaRef.current;\n if (!el) return;\n // Measure overflow against compact (1-line) height\n el.style.height = 'auto';\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\n updateHeight(true);\n requestAnimationFrame(() => updateHeight(true));\n }\n }, [value, expandOn, open, setOpen, textareaRef, recomputeMetrics, updateHeight]);\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 = textareaProps['aria-label'] != null || textareaProps['aria-labelledby'] != null;\n if (!hasLabel) {\n console.warn('[Chatbar.Textarea] Provide aria-label or aria-labelledby to ensure the control has an accessible name.');\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 // Prevent pasting the file name or any text representation when files are present\n event.preventDefault();\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 (event.key === 'Enter' && !event.shiftKey && !event.altKey && !event.ctrlKey && !event.metaKey && !event.nativeEvent.isComposing) {\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 [submitOnEnter, disabled, readOnly, sendMode, value, isValueControlled, setValue, ctx, onKeyDown],\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) (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 {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarInlineStart', className)} style={style}>\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 {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarInlineEnd', className)} style={style}>\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>((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 {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarAttachmentsRow', className)} style={style} role=\"list\" aria-label={divProps['aria-label'] ?? 'Attachments'}>\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});\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 {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarAttachment', className)} style={style} role=\"listitem\" data-kind={isImage ? 'image' : 'file'} title={attachment.name}>\n {children ?? (\n // <Card size={ctx.size} variant=\"surface\">\n <Flex align=\"center\" gap=\"2\" pr={!isImage ? '6' : undefined}>\n <div className=\"rt-ChatbarAttachmentPreview\" aria-hidden>\n {isImage ? <img className=\"rt-ChatbarAttachmentImage\" src={attachment.url} alt=\"\" /> : <FileTextIcon />}\n </div>\n {!isImage && (\n <Flex direction=\"column\" gap=\"0\" style={{ minWidth: 0 }}>\n <Text size={ctx.size} weight=\"medium\" style={{ whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>\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={() => ctx.setAttachments(ctx.attachments.filter((a) => a.id !== attachment.id))}\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>((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 // Prefer Chatbar.Root's accept when a local accept is not provided\n const mergedAccept = accept ?? ctx.accept;\n const actualAccept = (Array.isArray(mergedAccept) ? mergedAccept : (mergedAccept?.split(',') ?? [])).join(',');\n React.useEffect(() => {\n const handleWindowFocus = () => {\n // Reset guard when window regains focus after file dialog closes\n ctx.fileDialogOpenRef.current = false;\n };\n window.addEventListener('focus', handleWindowFocus);\n return () => window.removeEventListener('focus', handleWindowFocus);\n }, [ctx.fileDialogOpenRef]);\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 onPointerDown={(e: any) => {\n // Set guard before blur occurs (Safari fires blur before click)\n ctx.fileDialogOpenRef.current = true;\n buttonProps.onPointerDown?.(e);\n }}\n onMouseDown={(e: any) => {\n // Fallback for environments without Pointer Events\n ctx.fileDialogOpenRef.current = true;\n buttonProps.onMouseDown?.(e);\n }}\n onClick={(e: any) => {\n // Ensure file input opens reliably by clicking it first\n ctx.fileDialogOpenRef.current = true;\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 // File dialog closed; allow normal blur handling\n ctx.fileDialogOpenRef.current = false;\n // Reset input value to allow selecting the same file again\n e.currentTarget.value = '';\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 {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarRow', className)} style={style}>\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'>>((props, forwardedRef) => {\n const { className, style, ...divProps } = props;\n return <div {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarRowStart', className)} style={style} />;\n});\nRowStart.displayName = 'Chatbar.RowStart';\n\nconst RowEnd = React.forwardRef<HTMLDivElement, React.ComponentPropsWithoutRef<'div'>>((props, forwardedRef) => {\n const { className, style, ...divProps } = props;\n return <div {...divProps} ref={forwardedRef} className={classNames('rt-ChatbarRowEnd', className)} style={style} />;\n});\nRowEnd.displayName = 'Chatbar.RowEnd';\n\ntype SendProps = IconButtonProps & {\n asChild?: boolean;\n clearOnSend?: boolean;\n};\n\nconst Send = React.forwardRef<HTMLButtonElement, SendProps>((props, forwardedRef) => {\n const { asChild, clearOnSend = true, disabled, children, className, style, size: sizeProp, variant: variantProp, ...buttonProps } = 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={sizeProp ?? ctx.size}\n variant={variantProp ?? (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 as any)['aria-label'] ?? 'Send'}\n >\n {children ?? (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"lucide lucide-arrow-right-icon lucide-arrow-right\"\n >\n <path d=\"M5 12h14\" />\n <path d=\"m12 5 7 7-7 7\" />\n </svg>\n )}\n </IconButton>\n );\n});\nSend.displayName = 'Chatbar.Send';\n\nexport { Root, Textarea, InlineStart, InlineEnd, AttachmentsRow, Attachment, AttachTrigger, Row, RowStart, RowEnd, Send };\nexport type { RootProps as ChatbarRootProps, TextareaProps as ChatbarTextareaProps, RowProps as ChatbarRowProps, SendProps as ChatbarSendProps, ChatbarAttachment };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["React", "classNames", "IconButton", "CloseIcon", "FileTextIcon", "Flex", "ScrollArea", "Slot", "Box", "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", "color", "radius", "panelBackground", "material", "width", "maxWidth", "asChild", "attachmentsProp", "defaultAttachments", "onAttachmentsChange", "accept", "multiple", "maxAttachments", "maxFileSize", "paste", "pasteAccept", "clearOnSubmit", "onAttachmentReject", "dropzone", "apiRef", "divProps", "effectiveMaterial", "isValueControlled", "valueUncontrolled", "setValueUncontrolled", "value", "isOpenControlled", "openUncontrolled", "setOpenUncontrolled", "open", "rootRef", "textareaRef", "fileDialogOpenRef", "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", "urlSet", "Comp", "handleBlurCapture", "event", "nextTarget", "rootEl", "getRootProps", "getInputProps", "isDragActive", "openFileDialog", "rejectedFiles", "rejections", "errors", "reason", "acc", "pattern", "isInteractiveTarget", "target", "el", "handleContainerPointerDown", "node", "Textarea", "onFocus", "onInput", "onChange", "onPaste", "onKeyDown", "submitOnEnter", "rows", "textareaProps", "setOpen", "setValue", "lineHeightRef", "paddingRef", "compactHeightRef", "recomputeMetrics", "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", "a", "AttachTrigger", "buttonProps", "inputRef", "mergedAccept", "actualAccept", "handleWindowFocus", "e", "Row", "RowStart", "RowEnd", "Send", "clearOnSend", "sizeProp", "variantProp", "visible", "handleClick"]
|
|
7
7
|
}
|
package/package.json
CHANGED
package/schemas/base-button.json
CHANGED
|
@@ -279,6 +279,6 @@
|
|
|
279
279
|
"title": "Base-button Component Props",
|
|
280
280
|
"description": "Props schema for the base-button component in Kookie UI",
|
|
281
281
|
"version": "1.0.0",
|
|
282
|
-
"generatedAt": "2025-12-
|
|
282
|
+
"generatedAt": "2025-12-06T17:47:26.225Z",
|
|
283
283
|
"source": "Zod schema"
|
|
284
284
|
}
|
package/schemas/button.json
CHANGED
|
@@ -530,6 +530,6 @@
|
|
|
530
530
|
"title": "Button Component Props",
|
|
531
531
|
"description": "Props schema for the button component in Kookie UI",
|
|
532
532
|
"version": "1.0.0",
|
|
533
|
-
"generatedAt": "2025-12-
|
|
533
|
+
"generatedAt": "2025-12-06T17:47:26.230Z",
|
|
534
534
|
"source": "Zod schema"
|
|
535
535
|
}
|
package/schemas/icon-button.json
CHANGED
|
@@ -313,6 +313,6 @@
|
|
|
313
313
|
"title": "Icon-button Component Props",
|
|
314
314
|
"description": "Props schema for the icon-button component in Kookie UI",
|
|
315
315
|
"version": "1.0.0",
|
|
316
|
-
"generatedAt": "2025-12-
|
|
316
|
+
"generatedAt": "2025-12-06T17:47:26.232Z",
|
|
317
317
|
"source": "Zod schema"
|
|
318
318
|
}
|
package/schemas/index.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"title": "Kookie UI Button Components",
|
|
4
4
|
"description": "Complete JSON Schema collection for all button components in Kookie UI",
|
|
5
5
|
"version": "1.0.0",
|
|
6
|
-
"generatedAt": "2025-12-
|
|
6
|
+
"generatedAt": "2025-12-06T17:47:26.234Z",
|
|
7
7
|
"source": "Zod schemas",
|
|
8
8
|
"components": {
|
|
9
9
|
"base-button": {
|
|
@@ -287,7 +287,7 @@
|
|
|
287
287
|
"title": "Base-button Component Props",
|
|
288
288
|
"description": "Props schema for the base-button component in Kookie UI",
|
|
289
289
|
"version": "1.0.0",
|
|
290
|
-
"generatedAt": "2025-12-
|
|
290
|
+
"generatedAt": "2025-12-06T17:47:26.225Z",
|
|
291
291
|
"source": "Zod schema"
|
|
292
292
|
},
|
|
293
293
|
"button": {
|
|
@@ -822,7 +822,7 @@
|
|
|
822
822
|
"title": "Button Component Props",
|
|
823
823
|
"description": "Props schema for the button component in Kookie UI",
|
|
824
824
|
"version": "1.0.0",
|
|
825
|
-
"generatedAt": "2025-12-
|
|
825
|
+
"generatedAt": "2025-12-06T17:47:26.230Z",
|
|
826
826
|
"source": "Zod schema"
|
|
827
827
|
},
|
|
828
828
|
"icon-button": {
|
|
@@ -1140,7 +1140,7 @@
|
|
|
1140
1140
|
"title": "Icon-button Component Props",
|
|
1141
1141
|
"description": "Props schema for the icon-button component in Kookie UI",
|
|
1142
1142
|
"version": "1.0.0",
|
|
1143
|
-
"generatedAt": "2025-12-
|
|
1143
|
+
"generatedAt": "2025-12-06T17:47:26.232Z",
|
|
1144
1144
|
"source": "Zod schema"
|
|
1145
1145
|
},
|
|
1146
1146
|
"toggle-button": {
|
|
@@ -1683,7 +1683,7 @@
|
|
|
1683
1683
|
"title": "Toggle-button Component Props",
|
|
1684
1684
|
"description": "Props schema for the toggle-button component in Kookie UI",
|
|
1685
1685
|
"version": "1.0.0",
|
|
1686
|
-
"generatedAt": "2025-12-
|
|
1686
|
+
"generatedAt": "2025-12-06T17:47:26.233Z",
|
|
1687
1687
|
"source": "Zod schema"
|
|
1688
1688
|
},
|
|
1689
1689
|
"toggle-icon-button": {
|
|
@@ -2009,7 +2009,7 @@
|
|
|
2009
2009
|
"title": "Toggle-icon-button Component Props",
|
|
2010
2010
|
"description": "Props schema for the toggle-icon-button component in Kookie UI",
|
|
2011
2011
|
"version": "1.0.0",
|
|
2012
|
-
"generatedAt": "2025-12-
|
|
2012
|
+
"generatedAt": "2025-12-06T17:47:26.234Z",
|
|
2013
2013
|
"source": "Zod schema"
|
|
2014
2014
|
}
|
|
2015
2015
|
}
|
|
@@ -538,6 +538,6 @@
|
|
|
538
538
|
"title": "Toggle-button Component Props",
|
|
539
539
|
"description": "Props schema for the toggle-button component in Kookie UI",
|
|
540
540
|
"version": "1.0.0",
|
|
541
|
-
"generatedAt": "2025-12-
|
|
541
|
+
"generatedAt": "2025-12-06T17:47:26.233Z",
|
|
542
542
|
"source": "Zod schema"
|
|
543
543
|
}
|
|
@@ -321,6 +321,6 @@
|
|
|
321
321
|
"title": "Toggle-icon-button Component Props",
|
|
322
322
|
"description": "Props schema for the toggle-icon-button component in Kookie UI",
|
|
323
323
|
"version": "1.0.0",
|
|
324
|
-
"generatedAt": "2025-12-
|
|
324
|
+
"generatedAt": "2025-12-06T17:47:26.234Z",
|
|
325
325
|
"source": "Zod schema"
|
|
326
326
|
}
|
|
@@ -1121,13 +1121,13 @@ const RowEnd = React.forwardRef<HTMLDivElement, React.ComponentPropsWithoutRef<'
|
|
|
1121
1121
|
});
|
|
1122
1122
|
RowEnd.displayName = 'Chatbar.RowEnd';
|
|
1123
1123
|
|
|
1124
|
-
|
|
1124
|
+
type SendProps = IconButtonProps & {
|
|
1125
1125
|
asChild?: boolean;
|
|
1126
1126
|
clearOnSend?: boolean;
|
|
1127
|
-
}
|
|
1127
|
+
};
|
|
1128
1128
|
|
|
1129
1129
|
const Send = React.forwardRef<HTMLButtonElement, SendProps>((props, forwardedRef) => {
|
|
1130
|
-
const { asChild, clearOnSend = true, disabled, children, className, style, ...buttonProps } = props;
|
|
1130
|
+
const { asChild, clearOnSend = true, disabled, children, className, style, size: sizeProp, variant: variantProp, ...buttonProps } = props;
|
|
1131
1131
|
const ctx = useChatbarContext();
|
|
1132
1132
|
|
|
1133
1133
|
const trimmed = ctx.value.trim();
|
|
@@ -1149,8 +1149,8 @@ const Send = React.forwardRef<HTMLButtonElement, SendProps>((props, forwardedRef
|
|
|
1149
1149
|
<IconButton
|
|
1150
1150
|
{...(buttonProps as any)}
|
|
1151
1151
|
ref={forwardedRef as any}
|
|
1152
|
-
size={ctx.size}
|
|
1153
|
-
variant={ctx.open ? 'solid' : 'ghost'}
|
|
1152
|
+
size={sizeProp ?? ctx.size}
|
|
1153
|
+
variant={variantProp ?? (ctx.open ? 'solid' : 'ghost')}
|
|
1154
1154
|
disabled={disabled || ctx.disabled || ctx.readOnly}
|
|
1155
1155
|
className={classNames('rt-ChatbarSend', className)}
|
|
1156
1156
|
style={{
|
|
@@ -1160,7 +1160,7 @@ const Send = React.forwardRef<HTMLButtonElement, SendProps>((props, forwardedRef
|
|
|
1160
1160
|
}}
|
|
1161
1161
|
asChild={asChild}
|
|
1162
1162
|
onClick={handleClick}
|
|
1163
|
-
aria-label={buttonProps['aria-label'] ?? 'Send'}
|
|
1163
|
+
aria-label={(buttonProps as any)['aria-label'] ?? 'Send'}
|
|
1164
1164
|
>
|
|
1165
1165
|
{children ?? (
|
|
1166
1166
|
<svg
|