@pmate/chat-sdk 0.1.18 → 0.1.20

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.
Files changed (45) hide show
  1. package/dist/assets/ChatInput.stories-pjQKncGw.js +1644 -0
  2. package/dist/assets/Color-AVL7NMMY-CKkkQz33.js +1 -0
  3. package/dist/assets/DocsRenderer-PQXLIZUC-CVx0v9rK.js +1243 -0
  4. package/dist/assets/client-CMlGEQEC.js +9 -0
  5. package/dist/assets/iframe-4FbYaDjf.css +1 -0
  6. package/dist/assets/iframe-Bo_J3UyC.js +1071 -0
  7. package/dist/assets/index-D9myAQ7a.js +1 -0
  8. package/dist/assets/preload-helper-PPVm8Dsz.js +1 -0
  9. package/dist/assets/react-18-CVKdgGic.js +1 -0
  10. package/dist/favicon-wrapper.svg +46 -0
  11. package/dist/favicon.svg +1 -0
  12. package/dist/iframe.html +687 -0
  13. package/dist/index.html +148 -0
  14. package/dist/index.json +1 -0
  15. package/dist/nunito-sans-bold-italic.woff2 +0 -0
  16. package/dist/nunito-sans-bold.woff2 +0 -0
  17. package/dist/nunito-sans-italic.woff2 +0 -0
  18. package/dist/nunito-sans-regular.woff2 +0 -0
  19. package/dist/project.json +1 -0
  20. package/dist/sb-addons/docs-1/manager-bundle.js +151 -0
  21. package/dist/sb-addons/docs-1/manager-bundle.js.LEGAL.txt +0 -0
  22. package/dist/sb-addons/storybook-core-server-presets-0/common-manager-bundle.js +971 -0
  23. package/dist/sb-addons/storybook-core-server-presets-0/common-manager-bundle.js.LEGAL.txt +0 -0
  24. package/dist/sb-common-assets/favicon-wrapper.svg +46 -0
  25. package/dist/sb-common-assets/favicon.svg +1 -0
  26. package/dist/sb-common-assets/nunito-sans-bold-italic.woff2 +0 -0
  27. package/dist/sb-common-assets/nunito-sans-bold.woff2 +0 -0
  28. package/dist/sb-common-assets/nunito-sans-italic.woff2 +0 -0
  29. package/dist/sb-common-assets/nunito-sans-regular.woff2 +0 -0
  30. package/dist/sb-manager/globals-module-info.js +799 -0
  31. package/dist/sb-manager/globals-runtime.js +69791 -0
  32. package/dist/sb-manager/globals.js +34 -0
  33. package/dist/sb-manager/runtime.js +13198 -0
  34. package/dist/vite-inject-mocker-entry.js +2 -0
  35. package/lib/components/AttachmentPreview.d.ts +2 -1
  36. package/lib/components/AttachmentPreview.js +5 -12
  37. package/lib/components/ChatInputDesktop.js +16 -3
  38. package/lib/components/ChatInputMobile.js +15 -2
  39. package/lib/hooks/useVoiceInputController.d.ts +2 -1
  40. package/lib/hooks/useVoiceInputController.js +19 -5
  41. package/lib/types/chatInput.d.ts +5 -1
  42. package/lib/voice/MicStateManager.d.ts +9 -2
  43. package/lib/voice/MicStateManager.js +70 -13
  44. package/lib/voice/Recorder.js +1 -0
  45. package/package.json +1 -1
@@ -0,0 +1,2 @@
1
+ import{_ as me}from"./assets/preload-helper-PPVm8Dsz.js";class se{registryByUrl=new Map;registryById=new Map;clear(){this.registryByUrl.clear(),this.registryById.clear()}keys(){return this.registryByUrl.keys()}add(e){this.registryByUrl.set(e.url,e),this.registryById.set(e.id,e)}register(e,t,r,i,s){const a=typeof e=="object"?e.type:e;if(typeof e=="object"){const o=e;if(o instanceof q||o instanceof O||o instanceof F||o instanceof C)throw new TypeError(`[vitest] Cannot register a mock that is already defined. Expected a JSON representation from \`MockedModule.toJSON\`, instead got "${o.type}". Use "registry.add()" to update a mock instead.`);if(o.type==="automock"){const l=q.fromJSON(o);return this.add(l),l}else if(o.type==="autospy"){const l=O.fromJSON(o);return this.add(l),l}else if(o.type==="redirect"){const l=C.fromJSON(o);return this.add(l),l}else throw o.type==="manual"?new Error("Cannot set serialized manual mock. Define a factory function manually with `ManualMockedModule.fromJSON()`."):new Error(`Unknown mock type: ${o.type}`)}if(typeof t!="string")throw new TypeError("[vitest] Mocks require a raw string.");if(typeof i!="string")throw new TypeError("[vitest] Mocks require a url string.");if(typeof r!="string")throw new TypeError("[vitest] Mocks require an id string.");if(a==="manual"){if(typeof s!="function")throw new TypeError("[vitest] Manual mocks require a factory function.");const o=new F(t,r,i,s);return this.add(o),o}else if(a==="automock"||a==="autospy"){const o=a==="automock"?new q(t,r,i):new O(t,r,i);return this.add(o),o}else if(a==="redirect"){if(typeof s!="string")throw new TypeError("[vitest] Redirect mocks require a redirect string.");const o=new C(t,r,i,s);return this.add(o),o}else throw new Error(`[vitest] Unknown mock type: ${a}`)}delete(e){this.registryByUrl.delete(e)}get(e){return this.registryByUrl.get(e)}getById(e){return this.registryById.get(e)}has(e){return this.registryByUrl.has(e)}}class q{type="automock";constructor(e,t,r){this.raw=e,this.id=t,this.url=r}static fromJSON(e){return new O(e.raw,e.id,e.url)}toJSON(){return{type:this.type,url:this.url,raw:this.raw,id:this.id}}}class O{type="autospy";constructor(e,t,r){this.raw=e,this.id=t,this.url=r}static fromJSON(e){return new O(e.raw,e.id,e.url)}toJSON(){return{type:this.type,url:this.url,id:this.id,raw:this.raw}}}class C{type="redirect";constructor(e,t,r,i){this.raw=e,this.id=t,this.url=r,this.redirect=i}static fromJSON(e){return new C(e.raw,e.id,e.url,e.redirect)}toJSON(){return{type:this.type,url:this.url,raw:this.raw,id:this.id,redirect:this.redirect}}}class F{cache;type="manual";constructor(e,t,r,i){this.raw=e,this.id=t,this.url=r,this.factory=i}async resolve(){if(this.cache)return this.cache;let e;try{e=await this.factory()}catch(t){const r=new Error('[vitest] There was an error when mocking a module. If you are using "vi.mock" factory, make sure there are no top level variables inside, since this call is hoisted to top of the file. Read more: https://vitest.dev/api/vi.html#vi-mock');throw r.cause=t,r}if(e===null||typeof e!="object"||Array.isArray(e))throw new TypeError(`[vitest] vi.mock("${this.raw}", factory?: () => unknown) is not returning an object. Did you mean to return an object with a "default" key?`);return this.cache=e}static fromJSON(e,t){return new F(e.raw,e.id,e.url,t)}toJSON(){return{type:this.type,url:this.url,id:this.id,raw:this.raw}}}function ye(n,e,t={}){const r=new Array,i=new ge,s=(l,d,h)=>{try{return l[d]=h,!0}catch{return!1}},a=(l,d)=>{const h=D(l),g=h==="Module"||!!l.__esModule;for(const{key:w,descriptor:b}of K(l,g,n.globalConstructors)){if(!g&&b.get){try{Object.defineProperty(d,w,b)}catch{}continue}if(ve(w,h))continue;const y=l[w],c=i.getId(y);if(c!==void 0){r.push(()=>s(d,w,i.getMockedValue(c)));continue}const u=D(y);if(Array.isArray(y)){s(d,w,[]);continue}const x=u.includes("Function")&&typeof y=="function";if((!x||y._isMockFunction)&&u!=="Object"&&u!=="Module"){s(d,w,y);continue}if(s(d,w,x?y:{})){if(x){let _=function(){if(this instanceof d[w])for(const{key:I,descriptor:R}of K(this,!1,n.globalConstructors)){if(R.get)continue;const N=this[I];if(D(N).includes("Function")&&typeof N=="function"){const L=this[I],f=M(this,I).mockImplementation(L),$=f.mockReset;f.mockRestore=f.mockReset=()=>($.call(f),f.mockImplementation(L),f)}}};if(!n.spyOn)throw new Error("[@vitest/mocker] `spyOn` is not defined. This is a Vitest error. Please open a new issue with reproduction.");const M=n.spyOn,P=M(d,w);if(n.type==="automock"){P.mockImplementation(_);const I=P.mockReset;P.mockRestore=P.mockReset=()=>(I.call(P),P.mockImplementation(_),P)}Object.defineProperty(d[w],"length",{value:0})}i.track(y,d[w]),a(y,d[w])}}},o=t;a(e,o);for(const l of r)l();return o}class ge{idMap=new Map;mockedValueMap=new Map;getId(e){return this.idMap.get(e)}getMockedValue(e){return this.mockedValueMap.get(e)}track(e,t){const r=this.idMap.size;return this.idMap.set(e,r),this.mockedValueMap.set(r,t),r}}function D(n){return Object.prototype.toString.apply(n).slice(8,-1)}function ve(n,e){return e.includes("Function")&&typeof n=="string"&&["arguments","callee","caller","length","name"].includes(n)}function K(n,e,t){const{Map:r,Object:i,Function:s,RegExp:a,Array:o}=t,l=new r;let d=n;do{if(d===i.prototype||d===s.prototype||d===a.prototype)break;we(d,h=>{const g=i.getOwnPropertyDescriptor(d,h);g&&l.set(h,{key:h,descriptor:g})})}while(d=i.getPrototypeOf(d));if(e&&!l.has("default")&&"default"in n){const h=i.getOwnPropertyDescriptor(n,"default");h&&l.set("default",{key:"default",descriptor:h})}return o.from(l.values())}function we(n,e){const t=typeof e=="function"?e:r=>e.add(r);Object.getOwnPropertyNames(n).forEach(t),Object.getOwnPropertySymbols(n).forEach(t)}const ke=/^[A-Za-z]:\//;function ce(n=""){return n&&n.replace(/\\/g,"/").replace(ke,e=>e.toUpperCase())}const Se=/^[/\\]{2}/,_e=/^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/,Ee=/^[A-Za-z]:$/,be=/.(\.[^./]+|\.)$/,Ie=function(n){if(n.length===0)return".";n=ce(n);const e=n.match(Se),t=H(n),r=n[n.length-1]==="/";return n=Te(n,!t),n.length===0?t?"/":r?"./":".":(r&&(n+="/"),Ee.test(n)&&(n+="/"),e?t?`//${n}`:`//./${n}`:t&&!H(n)?`/${n}`:n)},xe=function(...n){let e="";for(const t of n)if(t)if(e.length>0){const r=e[e.length-1]==="/",i=t[0]==="/";r&&i?e+=t.slice(1):e+=r||i?t:`/${t}`}else e+=t;return Ie(e)};function Te(n,e){let t="",r=0,i=-1,s=0,a=null;for(let o=0;o<=n.length;++o){if(o<n.length)a=n[o];else{if(a==="/")break;a="/"}if(a==="/"){if(!(i===o-1||s===1))if(s===2){if(t.length<2||r!==2||t[t.length-1]!=="."||t[t.length-2]!=="."){if(t.length>2){const l=t.lastIndexOf("/");l===-1?(t="",r=0):(t=t.slice(0,l),r=t.length-1-t.lastIndexOf("/")),i=o,s=0;continue}else if(t.length>0){t="",r=0,i=o,s=0;continue}}e&&(t+=t.length>0?"/..":"..",r=2)}else t.length>0?t+=`/${n.slice(i+1,o)}`:t=n.slice(i+1,o),r=o-i-1;i=o,s=0}else a==="."&&s!==-1?++s:s=-1}return t}const H=function(n){return _e.test(n)},$e=function(n){if(n==="..")return"";const e=be.exec(ce(n));return e&&e[1]||""};var Pe={reset:[0,0],bold:[1,22,"\x1B[22m\x1B[1m"],dim:[2,22,"\x1B[22m\x1B[2m"],italic:[3,23],underline:[4,24],inverse:[7,27],hidden:[8,28],strikethrough:[9,29],black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],gray:[90,39],bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],blackBright:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39],bgBlackBright:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]},Me=Object.entries(Pe);function j(n){return String(n)}j.open="";j.close="";function Re(n=!1){let e=typeof process<"u"?process:void 0,t=e?.env||{},r=e?.argv||[];return!("NO_COLOR"in t||r.includes("--no-color"))&&("FORCE_COLOR"in t||r.includes("--color")||e?.platform==="win32"||n&&t.TERM!=="dumb"||"CI"in t)||typeof window<"u"&&!!window.chrome}function Ae(n=!1){let e=Re(n),t=(a,o,l,d)=>{let h="",g=0;do h+=a.substring(g,d)+l,g=d+o.length,d=a.indexOf(o,g);while(~d);return h+a.substring(g)},r=(a,o,l=a)=>{let d=h=>{let g=String(h),w=g.indexOf(o,a.length);return~w?a+t(g,o,l,w)+o:a+g+o};return d.open=a,d.close=o,d},i={isColorSupported:e},s=a=>`\x1B[${a}m`;for(let[a,o]of Me)i[a]=e?r(s(o[0]),s(o[1]),o[2]):j;return i}Ae();function ae(n,e){return e.forEach(function(t){t&&typeof t!="string"&&!Array.isArray(t)&&Object.keys(t).forEach(function(r){if(r!=="default"&&!(r in n)){var i=Object.getOwnPropertyDescriptor(t,r);Object.defineProperty(n,r,i.get?i:{enumerable:!0,get:function(){return t[r]}})}})}),Object.freeze(n)}function le(n){return n&&n.__esModule&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n}var U={exports:{}},k={};var Z;function Oe(){if(Z)return k;Z=1;var n=Symbol.for("react.transitional.element"),e=Symbol.for("react.portal"),t=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),i=Symbol.for("react.profiler"),s=Symbol.for("react.consumer"),a=Symbol.for("react.context"),o=Symbol.for("react.forward_ref"),l=Symbol.for("react.suspense"),d=Symbol.for("react.suspense_list"),h=Symbol.for("react.memo"),g=Symbol.for("react.lazy"),w=Symbol.for("react.view_transition"),b=Symbol.for("react.client.reference");function y(c){if(typeof c=="object"&&c!==null){var u=c.$$typeof;switch(u){case n:switch(c=c.type,c){case t:case i:case r:case l:case d:case w:return c;default:switch(c=c&&c.$$typeof,c){case a:case o:case g:case h:return c;case s:return c;default:return u}}case e:return u}}}return k.ContextConsumer=s,k.ContextProvider=a,k.Element=n,k.ForwardRef=o,k.Fragment=t,k.Lazy=g,k.Memo=h,k.Portal=e,k.Profiler=i,k.StrictMode=r,k.Suspense=l,k.SuspenseList=d,k.isContextConsumer=function(c){return y(c)===s},k.isContextProvider=function(c){return y(c)===a},k.isElement=function(c){return typeof c=="object"&&c!==null&&c.$$typeof===n},k.isForwardRef=function(c){return y(c)===o},k.isFragment=function(c){return y(c)===t},k.isLazy=function(c){return y(c)===g},k.isMemo=function(c){return y(c)===h},k.isPortal=function(c){return y(c)===e},k.isProfiler=function(c){return y(c)===i},k.isStrictMode=function(c){return y(c)===r},k.isSuspense=function(c){return y(c)===l},k.isSuspenseList=function(c){return y(c)===d},k.isValidElementType=function(c){return typeof c=="string"||typeof c=="function"||c===t||c===i||c===r||c===l||c===d||typeof c=="object"&&c!==null&&(c.$$typeof===g||c.$$typeof===h||c.$$typeof===a||c.$$typeof===s||c.$$typeof===o||c.$$typeof===b||c.getModuleId!==void 0)},k.typeOf=y,k}var G;function Ce(){return G||(G=1,U.exports=Oe()),U.exports}var ue=Ce(),Ne=le(ue),Le=ae({__proto__:null,default:Ne},[ue]),z={exports:{}},v={};var Q;function Je(){if(Q)return v;Q=1;var n=Symbol.for("react.element"),e=Symbol.for("react.portal"),t=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),i=Symbol.for("react.profiler"),s=Symbol.for("react.provider"),a=Symbol.for("react.context"),o=Symbol.for("react.server_context"),l=Symbol.for("react.forward_ref"),d=Symbol.for("react.suspense"),h=Symbol.for("react.suspense_list"),g=Symbol.for("react.memo"),w=Symbol.for("react.lazy"),b=Symbol.for("react.offscreen"),y;y=Symbol.for("react.module.reference");function c(u){if(typeof u=="object"&&u!==null){var x=u.$$typeof;switch(x){case n:switch(u=u.type,u){case t:case i:case r:case d:case h:return u;default:switch(u=u&&u.$$typeof,u){case o:case a:case l:case w:case g:case s:return u;default:return x}}case e:return x}}}return v.ContextConsumer=a,v.ContextProvider=s,v.Element=n,v.ForwardRef=l,v.Fragment=t,v.Lazy=w,v.Memo=g,v.Portal=e,v.Profiler=i,v.StrictMode=r,v.Suspense=d,v.SuspenseList=h,v.isAsyncMode=function(){return!1},v.isConcurrentMode=function(){return!1},v.isContextConsumer=function(u){return c(u)===a},v.isContextProvider=function(u){return c(u)===s},v.isElement=function(u){return typeof u=="object"&&u!==null&&u.$$typeof===n},v.isForwardRef=function(u){return c(u)===l},v.isFragment=function(u){return c(u)===t},v.isLazy=function(u){return c(u)===w},v.isMemo=function(u){return c(u)===g},v.isPortal=function(u){return c(u)===e},v.isProfiler=function(u){return c(u)===i},v.isStrictMode=function(u){return c(u)===r},v.isSuspense=function(u){return c(u)===d},v.isSuspenseList=function(u){return c(u)===h},v.isValidElementType=function(u){return typeof u=="string"||typeof u=="function"||u===t||u===i||u===r||u===d||u===h||u===b||typeof u=="object"&&u!==null&&(u.$$typeof===w||u.$$typeof===g||u.$$typeof===s||u.$$typeof===a||u.$$typeof===l||u.$$typeof===y||u.getModuleId!==void 0)},v.typeOf=c,v}var ee;function Be(){return ee||(ee=1,z.exports=Je()),z.exports}var fe=Be(),Xe=le(fe),qe=ae({__proto__:null,default:Xe},[fe]);const Fe=["isAsyncMode","isConcurrentMode","isContextConsumer","isContextProvider","isElement","isForwardRef","isFragment","isLazy","isMemo","isPortal","isProfiler","isStrictMode","isSuspense","isSuspenseList","isValidElementType"];Object.fromEntries(Fe.map(n=>[n,e=>qe[n](e)||Le[n](e)]));let De=()=>"Promise{…}";try{const{getPromiseDetails:n,kPending:e,kRejected:t}=process.binding("util");Array.isArray(n(Promise.resolve()))&&(De=(r,i)=>{const[s,a]=n(r);return s===e?"Promise{<pending>}":`Promise${s===t?"!":""}{${i.inspect(a,i)}}`})}catch{}function Ue(n){const{message:e="$$stack trace error",stackTraceLimit:t=1}=n||{},r=Error.stackTraceLimit,i=Error.prepareStackTrace;Error.stackTraceLimit=t,Error.prepareStackTrace=o=>o.stack;const a=new Error(e).stack||"";return Error.prepareStackTrace=i,Error.stackTraceLimit=r,a}var V,te;function ze(){if(te)return V;te=1;var n,e,t,r,i,s,a,o,l,d,h,g,w,b,y,c,u,x,M;return w=/\/(?![*\/])(?:\[(?:(?![\]\\]).|\\.)*\]|(?![\/\\]).|\\.)*(\/[$_\u200C\u200D\p{ID_Continue}]*|\\)?/uy,g=/--|\+\+|=>|\.{3}|\??\.(?!\d)|(?:&&|\|\||\?\?|[+\-%&|^]|\*{1,2}|<{1,2}|>{1,3}|!=?|={1,2}|\/(?![\/*]))=?|[?~,:;[\](){}]/y,n=/(\x23?)(?=[$_\p{ID_Start}\\])(?:[$_\u200C\u200D\p{ID_Continue}]|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+/uy,y=/(['"])(?:(?!\1)[^\\\n\r]|\\(?:\r\n|[^]))*(\1)?/y,h=/(?:0[xX][\da-fA-F](?:_?[\da-fA-F])*|0[oO][0-7](?:_?[0-7])*|0[bB][01](?:_?[01])*)n?|0n|[1-9](?:_?\d)*n|(?:(?:0(?!\d)|0\d*[89]\d*|[1-9](?:_?\d)*)(?:\.(?:\d(?:_?\d)*)?)?|\.\d(?:_?\d)*)(?:[eE][+-]?\d(?:_?\d)*)?|0[0-7]+/y,c=/[`}](?:[^`\\$]|\\[^]|\$(?!\{))*(`|\$\{)?/y,M=/[\t\v\f\ufeff\p{Zs}]+/uy,o=/\r?\n|[\r\u2028\u2029]/y,l=/\/\*(?:[^*]|\*(?!\/))*(\*\/)?/y,b=/\/\/.*/y,t=/[<>.:={}]|\/(?![\/*])/y,e=/[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}-]*/uy,r=/(['"])(?:(?!\1)[^])*(\1)?/y,i=/[^<>{}]+/y,x=/^(?:[\/+-]|\.{3}|\?(?:InterpolationIn(?:JSX|Template)|NoLineTerminatorHere|NonExpressionParenEnd|UnaryIncDec))?$|[{}([,;<>=*%&|^!~?:]$/,u=/^(?:=>|[;\]){}]|else|\?(?:NoLineTerminatorHere|NonExpressionParenEnd))?$/,s=/^(?:await|case|default|delete|do|else|instanceof|new|return|throw|typeof|void|yield)$/,a=/^(?:return|throw|yield)$/,d=RegExp(o.source),V=function*(_,{jsx:P=!1}={}){var I,R,N,p,m,L,f,$,Y,T,J,S,B,E;for({length:L}=_,p=0,m="",E=[{tag:"JS"}],I=[],J=0,S=!1;p<L;){switch($=E[E.length-1],$.tag){case"JS":case"JSNonExpressionParen":case"InterpolationInTemplate":case"InterpolationInJSX":if(_[p]==="/"&&(x.test(m)||s.test(m))&&(w.lastIndex=p,f=w.exec(_))){p=w.lastIndex,m=f[0],S=!0,yield{type:"RegularExpressionLiteral",value:f[0],closed:f[1]!==void 0&&f[1]!=="\\"};continue}if(g.lastIndex=p,f=g.exec(_)){switch(B=f[0],Y=g.lastIndex,T=B,B){case"(":m==="?NonExpressionParenKeyword"&&E.push({tag:"JSNonExpressionParen",nesting:J}),J++,S=!1;break;case")":J--,S=!0,$.tag==="JSNonExpressionParen"&&J===$.nesting&&(E.pop(),T="?NonExpressionParenEnd",S=!1);break;case"{":g.lastIndex=0,N=!u.test(m)&&(x.test(m)||s.test(m)),I.push(N),S=!1;break;case"}":switch($.tag){case"InterpolationInTemplate":if(I.length===$.nesting){c.lastIndex=p,f=c.exec(_),p=c.lastIndex,m=f[0],f[1]==="${"?(m="?InterpolationInTemplate",S=!1,yield{type:"TemplateMiddle",value:f[0]}):(E.pop(),S=!0,yield{type:"TemplateTail",value:f[0],closed:f[1]==="`"});continue}break;case"InterpolationInJSX":if(I.length===$.nesting){E.pop(),p+=1,m="}",yield{type:"JSXPunctuator",value:"}"};continue}}S=I.pop(),T=S?"?ExpressionBraceEnd":"}";break;case"]":S=!0;break;case"++":case"--":T=S?"?PostfixIncDec":"?UnaryIncDec";break;case"<":if(P&&(x.test(m)||s.test(m))){E.push({tag:"JSXTag"}),p+=1,m="<",yield{type:"JSXPunctuator",value:B};continue}S=!1;break;default:S=!1}p=Y,m=T,yield{type:"Punctuator",value:B};continue}if(n.lastIndex=p,f=n.exec(_)){switch(p=n.lastIndex,T=f[0],f[0]){case"for":case"if":case"while":case"with":m!=="."&&m!=="?."&&(T="?NonExpressionParenKeyword")}m=T,S=!s.test(f[0]),yield{type:f[1]==="#"?"PrivateIdentifier":"IdentifierName",value:f[0]};continue}if(y.lastIndex=p,f=y.exec(_)){p=y.lastIndex,m=f[0],S=!0,yield{type:"StringLiteral",value:f[0],closed:f[2]!==void 0};continue}if(h.lastIndex=p,f=h.exec(_)){p=h.lastIndex,m=f[0],S=!0,yield{type:"NumericLiteral",value:f[0]};continue}if(c.lastIndex=p,f=c.exec(_)){p=c.lastIndex,m=f[0],f[1]==="${"?(m="?InterpolationInTemplate",E.push({tag:"InterpolationInTemplate",nesting:I.length}),S=!1,yield{type:"TemplateHead",value:f[0]}):(S=!0,yield{type:"NoSubstitutionTemplate",value:f[0],closed:f[1]==="`"});continue}break;case"JSXTag":case"JSXTagEnd":if(t.lastIndex=p,f=t.exec(_)){switch(p=t.lastIndex,T=f[0],f[0]){case"<":E.push({tag:"JSXTag"});break;case">":E.pop(),m==="/"||$.tag==="JSXTagEnd"?(T="?JSX",S=!0):E.push({tag:"JSXChildren"});break;case"{":E.push({tag:"InterpolationInJSX",nesting:I.length}),T="?InterpolationInJSX",S=!1;break;case"/":m==="<"&&(E.pop(),E[E.length-1].tag==="JSXChildren"&&E.pop(),E.push({tag:"JSXTagEnd"}))}m=T,yield{type:"JSXPunctuator",value:f[0]};continue}if(e.lastIndex=p,f=e.exec(_)){p=e.lastIndex,m=f[0],yield{type:"JSXIdentifier",value:f[0]};continue}if(r.lastIndex=p,f=r.exec(_)){p=r.lastIndex,m=f[0],yield{type:"JSXString",value:f[0],closed:f[2]!==void 0};continue}break;case"JSXChildren":if(i.lastIndex=p,f=i.exec(_)){p=i.lastIndex,m=f[0],yield{type:"JSXText",value:f[0]};continue}switch(_[p]){case"<":E.push({tag:"JSXTag"}),p++,m="<",yield{type:"JSXPunctuator",value:"<"};continue;case"{":E.push({tag:"InterpolationInJSX",nesting:I.length}),p++,m="?InterpolationInJSX",S=!1,yield{type:"JSXPunctuator",value:"{"};continue}}if(M.lastIndex=p,f=M.exec(_)){p=M.lastIndex,yield{type:"WhiteSpace",value:f[0]};continue}if(o.lastIndex=p,f=o.exec(_)){p=o.lastIndex,S=!1,a.test(m)&&(m="?NoLineTerminatorHere"),yield{type:"LineTerminatorSequence",value:f[0]};continue}if(l.lastIndex=p,f=l.exec(_)){p=l.lastIndex,d.test(f[0])&&(S=!1,a.test(m)&&(m="?NoLineTerminatorHere")),yield{type:"MultiLineComment",value:f[0],closed:f[1]!==void 0};continue}if(b.lastIndex=p,f=b.exec(_)){p=b.lastIndex,S=!1,yield{type:"SingleLineComment",value:f[0]};continue}R=String.fromCodePoint(_.codePointAt(p)),p+=R.length,m=R,S=!1,yield{type:$.tag.startsWith("JSX")?"JSXInvalid":"Invalid",value:R}}},V}ze();var de={keyword:["break","case","catch","continue","debugger","default","do","else","finally","for","function","if","return","switch","throw","try","var","const","while","with","new","this","super","class","extends","export","import","null","true","false","in","instanceof","typeof","void","delete"],strict:["implements","interface","let","package","private","protected","public","static","yield"]};new Set(de.keyword);new Set(de.strict);const re="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",Ve=new Uint8Array(64),We=new Uint8Array(128);for(let n=0;n<re.length;n++){const e=re.charCodeAt(n);Ve[n]=e,We[e]=n}var ne;(function(n){n[n.Empty=1]="Empty",n[n.Hash=2]="Hash",n[n.Query=3]="Query",n[n.RelativePath=4]="RelativePath",n[n.AbsolutePath=5]="AbsolutePath",n[n.SchemeRelative=6]="SchemeRelative",n[n.Absolute=7]="Absolute"})(ne||(ne={}));const je=/^[A-Za-z]:\//;function Ye(n=""){return n&&n.replace(/\\/g,"/").replace(je,e=>e.toUpperCase())}const Ke=/^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;function He(){return typeof process<"u"&&typeof process.cwd=="function"?process.cwd().replace(/\\/g,"/"):"/"}const Ze=function(...n){n=n.map(r=>Ye(r));let e="",t=!1;for(let r=n.length-1;r>=-1&&!t;r--){const i=r>=0?n[r]:He();!i||i.length===0||(e=`${i}/${e}`,t=ie(i))}return e=Ge(e,!t),t&&!ie(e)?`/${e}`:e.length>0?e:"."};function Ge(n,e){let t="",r=0,i=-1,s=0,a=null;for(let o=0;o<=n.length;++o){if(o<n.length)a=n[o];else{if(a==="/")break;a="/"}if(a==="/"){if(!(i===o-1||s===1))if(s===2){if(t.length<2||r!==2||t[t.length-1]!=="."||t[t.length-2]!=="."){if(t.length>2){const l=t.lastIndexOf("/");l===-1?(t="",r=0):(t=t.slice(0,l),r=t.length-1-t.lastIndexOf("/")),i=o,s=0;continue}else if(t.length>0){t="",r=0,i=o,s=0;continue}}e&&(t+=t.length>0?"/..":"..",r=2)}else t.length>0?t+=`/${n.slice(i+1,o)}`:t=n.slice(i+1,o),r=o-i-1;i=o,s=0}else a==="."&&s!==-1?++s:s=-1}return t}const ie=function(n){return Ke.test(n)},pe=/^\s*at .*(?:\S:\d+|\(native\))/m,Qe=/^(?:eval@)?(?:\[native code\])?$/;function he(n){if(!n.includes(":"))return[n];const t=/(.+?)(?::(\d+))?(?::(\d+))?$/.exec(n.replace(/^\(|\)$/g,""));if(!t)return[n];let r=t[1];if(r.startsWith("async ")&&(r=r.slice(6)),r.startsWith("http:")||r.startsWith("https:")){const i=new URL(r);i.searchParams.delete("import"),i.searchParams.delete("browserv"),r=i.pathname+i.hash+i.search}if(r.startsWith("/@fs/")){const i=/^\/@fs\/[a-zA-Z]:\//.test(r);r=r.slice(i?5:4)}return[r,t[2]||void 0,t[3]||void 0]}function et(n){let e=n.trim();if(Qe.test(e)||(e.includes(" > eval")&&(e=e.replace(/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g,":$1")),!e.includes("@")&&!e.includes(":")))return null;const t=/((.*".+"[^@]*)?[^@]*)(@)/,r=e.match(t),i=r&&r[1]?r[1]:void 0,[s,a,o]=he(e.replace(t,""));return!s||!a||!o?null:{file:s,method:i||"",line:Number.parseInt(a),column:Number.parseInt(o)}}function tt(n){const e=n.trim();return pe.test(e)?rt(e):et(e)}function rt(n){let e=n.trim();if(!pe.test(e))return null;e.includes("(eval ")&&(e=e.replace(/eval code/g,"eval").replace(/(\(eval at [^()]*)|(,.*$)/g,""));let t=e.replace(/^\s+/,"").replace(/\(eval code/g,"(").replace(/^.*?\s+/,"");const r=t.match(/ (\(.+\)$)/);t=r?t.replace(r[0],""):t;const[i,s,a]=he(r?r[1]:t);let o=r&&t||"",l=i&&["eval","<anonymous>"].includes(i)?void 0:i;return!l||!s||!a?null:(o.startsWith("async ")&&(o=o.slice(6)),l.startsWith("file://")&&(l=l.slice(7)),l=l.startsWith("node:")||l.startsWith("internal:")?l:Ze(l),o&&(o=o.replace(/__vite_ssr_import_\d+__\./g,"")),{method:o,file:l,line:Number.parseInt(s),column:Number.parseInt(a)})}function nt(n){const e=n?.globalThisKey||"__vitest_mocker__";function t(){return typeof globalThis[e]<"u"?globalThis[e]:new Proxy({},{get(r,i){throw new Error(`Vitest mocker was not initialized in this environment. vi.${String(i)}() is forbidden.`)}})}return{hoisted(r){if(typeof r!="function")throw new TypeError(`vi.hoisted() expects a function, but received a ${typeof r}`);return r()},mock(r,i){if(typeof r!="string")throw new TypeError(`vi.mock() expects a string path, but received a ${typeof r}`);const s=A("mock");t().queueMock(r,s,typeof i=="function"?()=>i(()=>t().importActual(r,s)):i)},unmock(r){if(typeof r!="string")throw new TypeError(`vi.unmock() expects a string path, but received a ${typeof r}`);t().queueUnmock(r,A("unmock"))},doMock(r,i){if(typeof r!="string")throw new TypeError(`vi.doMock() expects a string path, but received a ${typeof r}`);const s=A("doMock");t().queueMock(r,s,typeof i=="function"?()=>i(()=>t().importActual(r,s)):i)},doUnmock(r){if(typeof r!="string")throw new TypeError(`vi.doUnmock() expects a string path, but received a ${typeof r}`);t().queueUnmock(r,A("doUnmock"))},async importActual(r){return t().importActual(r,A("importActual"))},async importMock(r){return t().importMock(r,A("importMock"))}}}function A(n){const t=Ue({stackTraceLimit:5}).split(`
2
+ `),r=t.findIndex(s=>s.includes(` at Object.${n}`)||s.includes(`${n}@`)),i=tt(t[r+1]);return i?.file||""}const{now:oe}=Date;class it{registry=new se;queue=new Set;mockedIds=new Set;constructor(e,t,r,i){this.interceptor=e,this.rpc=t,this.spyOn=r,this.config=i}async prepare(){this.queue.size&&await Promise.all([...this.queue.values()])}async resolveFactoryModule(e){const t=this.registry.get(e);if(!t||t.type!=="manual")throw new Error(`Mock ${e} wasn't registered. This is probably a Vitest error. Please, open a new issue with reproduction.`);return await t.resolve()}getFactoryModule(e){const t=this.registry.get(e);if(!t||t.type!=="manual")throw new Error(`Mock ${e} wasn't registered. This is probably a Vitest error. Please, open a new issue with reproduction.`);if(!t.cache)throw new Error(`Mock ${e} wasn't resolved. This is probably a Vitest error. Please, open a new issue with reproduction.`);return t.cache}async invalidate(){const e=Array.from(this.mockedIds);e.length&&(await this.rpc.invalidate(e),await this.interceptor.invalidate(),this.registry.clear())}async importActual(e,t){const r=await this.rpc.resolveId(e,t);if(r==null)throw new Error(`[vitest] Cannot resolve "${e}" imported from "${t}"`);const i=$e(r.id),s=new URL(r.url,location.href),a=`_vitest_original&ext${i}`,o=`${s.pathname}${s.search?`${s.search}&${a}`:`?${a}`}${s.hash}`;return this.wrapDynamicImport(()=>import(o)).then(l=>{if(!r.optimized||typeof l.default>"u")return l;const d=l.default;return d?.__esModule?d:{...typeof d=="object"&&!Array.isArray(d)||typeof d=="function"?d:{},default:d}})}async importMock(e,t){await this.prepare();const{resolvedId:r,resolvedUrl:i,redirectUrl:s}=await this.rpc.resolveMock(e,t,{mock:"auto"}),a=this.resolveMockPath(X(i));let o=this.registry.get(a);if(!o)if(s){const l=new URL(this.resolveMockPath(X(s)),location.href).toString();o=new C(e,r,a,l)}else o=new q(e,r,a);if(o.type==="manual")return await o.resolve();if(o.type==="automock"||o.type==="autospy"){const l=new URL(`/@id/${r}`,location.href),d=l.search?`${l.search}&t=${oe()}`:`?t=${oe()}`,h=await me(()=>import(`${l.pathname}${d}&mock=${o.type}${l.hash}`),[],import.meta.url);return this.mockObject(h,o.type)}return import(o.redirect)}mockObject(e,t="automock"){return ye({globalConstructors:{Object,Function,Array,Map,RegExp},spyOn:this.spyOn,type:t},e)}queueMock(e,t,r){const i=this.rpc.resolveMock(e,t,{mock:typeof r=="function"?"factory":r?.spy?"spy":"auto"}).then(async({redirectUrl:s,resolvedId:a,resolvedUrl:o,needsInterop:l,mockType:d})=>{const h=this.resolveMockPath(X(o));this.mockedIds.add(a);const g=typeof r=="function"?async()=>{const y=await r();return l?{default:y}:y}:void 0,w=typeof s=="string"?new URL(this.resolveMockPath(X(s)),location.href).toString():null;let b;d==="manual"?b=this.registry.register("manual",e,a,h,g):d==="autospy"?b=this.registry.register("autospy",e,a,h):d==="redirect"?b=this.registry.register("redirect",e,a,h,w):b=this.registry.register("automock",e,a,h),await this.interceptor.register(b)}).finally(()=>{this.queue.delete(i)});this.queue.add(i)}queueUnmock(e,t){const r=this.rpc.resolveId(e,t).then(async i=>{if(!i)return;const s=this.resolveMockPath(X(i.url));this.mockedIds.add(i.id),this.registry.delete(s),await this.interceptor.delete(s)}).finally(()=>{this.queue.delete(r)});this.queue.add(r)}wrapDynamicImport(e){return typeof e=="function"?new Promise((r,i)=>{this.prepare().finally(()=>{e().then(r,i)})}):e}resolveMockPath(e){const t=this.config,r=xe("/@fs/",t.root);return e.startsWith(t.root)?e.slice(t.root.length):e.startsWith(r)?e.slice(r.length):e}}const ot=/(\?|&)v=\w{8}/;function X(n){return n.replace(ot,"")}class st{mocks=new se;constructor(){}async register(e){this.mocks.add(e)}async delete(e){this.mocks.delete(e)}async invalidate(){this.mocks.clear()}}const W=n=>{switch(n){case"resolveId":return Promise.resolve({id:"",url:"",optimized:!1});case"resolveMock":return Promise.resolve({mockType:"dummy",resolvedId:"",resolvedUrl:"",redirectUrl:"",needsInterop:!1});case"invalidate":return Promise.resolve()}};class ct extends it{queueMock(){}}function at(n){const e=new ct(n("__vitest_mocker__"),{resolveId(t,r){return W("resolveId")},resolveMock(t,r,i){return W("resolveMock")},async invalidate(t){return W("invalidate")}},(...t)=>globalThis.__STORYBOOK_MODULE_TEST__.spyOn(...t),{root:""});return globalThis.__vitest_mocker__=e,nt({globalThisKey:"__vitest_mocker__"})}globalThis.__STORYBOOK_MOCKER__=at(()=>new st);
@@ -1,6 +1,7 @@
1
1
  import type { ChatAttachment } from "../types/attachment";
2
2
  import type { ChatInputTokens } from "../types/chatInput";
3
- export declare function AttachmentPreview({ attachments, tokens, }: {
3
+ export declare function AttachmentPreview({ attachments, tokens, onRemove, }: {
4
4
  attachments: ChatAttachment[];
5
5
  tokens: ChatInputTokens;
6
+ onRemove?: (id: string) => void;
6
7
  }): import("react/jsx-runtime").JSX.Element | null;
@@ -1,6 +1,6 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React from "react";
3
- export function AttachmentPreview({ attachments, tokens, }) {
3
+ export function AttachmentPreview({ attachments, tokens, onRemove, }) {
4
4
  if (attachments.length === 0) {
5
5
  return null;
6
6
  }
@@ -12,18 +12,11 @@ export function AttachmentPreview({ attachments, tokens, }) {
12
12
  background: tokens.color.surfaceInputFocus,
13
13
  color: tokens.color.textSecondary,
14
14
  border: `1px solid ${tokens.color.borderDefault}`,
15
- padding: "6px 10px",
15
+ padding: attachment.kind === "image" ? 5 : "6px 10px",
16
16
  fontSize: 12,
17
17
  lineHeight: "16px",
18
18
  fontFamily: tokens.typography.familyBase,
19
19
  boxShadow: tokens.shadow.inputElevated,
20
- }, title: attachment.url ?? attachment.name, children: [_jsx("span", { "aria-hidden": "true", style: {
21
- width: 6,
22
- height: 6,
23
- borderRadius: 999,
24
- background: attachment.kind === "image"
25
- ? tokens.color.iconActive
26
- : tokens.color.textSecondary,
27
- opacity: 0.9,
28
- } }), attachment.name] }, attachment.id))) }));
20
+ position: "relative",
21
+ }, title: attachment.url ?? attachment.name, children: [attachment.kind === "image" && (attachment.previewUrl || attachment.url) ? (_jsx("img", { src: attachment.previewUrl ?? attachment.url, alt: attachment.name, style: { width: 64, height: 64, borderRadius: Math.max(6, tokens.radius.attachmentPreview - 4), objectFit: "cover" } })) : _jsxs(_Fragment, { children: [_jsx("span", { "aria-hidden": "true", style: { width: 6, height: 6, borderRadius: 999, background: tokens.color.textSecondary, opacity: 0.9 } }), attachment.name] }), onRemove ? _jsx("button", { type: "button", "aria-label": `Remove ${attachment.name}`, onClick: () => onRemove(attachment.id), style: { position: attachment.kind === "image" ? "absolute" : "static", top: 8, right: 8, width: 20, height: 20, display: "grid", placeItems: "center", border: `1px solid ${tokens.color.borderDefault}`, borderRadius: 999, background: tokens.color.surfaceInputDefault, color: tokens.color.textPrimary, cursor: "pointer", lineHeight: 1 }, children: "\u00D7" }) : null] }, attachment.id))) }));
29
22
  }
@@ -110,6 +110,19 @@ function DesktopInner(props) {
110
110
  file,
111
111
  });
112
112
  };
113
+ const handlePaste = (event) => {
114
+ props.onPaste?.(event);
115
+ if (event.defaultPrevented || props.enableImage === false)
116
+ return;
117
+ const images = [...event.clipboardData.items]
118
+ .filter((item) => item.kind === "file" && item.type.startsWith("image/"))
119
+ .flatMap((item) => item.getAsFile() ? [item.getAsFile()] : []);
120
+ if (!images.length)
121
+ return;
122
+ event.preventDefault();
123
+ for (const image of images)
124
+ void handleImageFile(image);
125
+ };
113
126
  const insertEmoji = (emoji) => {
114
127
  const textarea = textComposerRef.current;
115
128
  const start = textarea?.selectionStart ?? state.text.length;
@@ -179,7 +192,7 @@ function DesktopInner(props) {
179
192
  setIsMoreOpen(false);
180
193
  }
181
194
  event.currentTarget.value = "";
182
- } }), _jsx(EmojiPicker, { open: isEmojiOpen, isMobile: false, anchorRef: emojiAnchorRef, onSelect: insertEmoji, onClose: () => setIsEmojiOpen(false) }), _jsx(AttachmentPreview, { attachments: attachments.attachments, tokens: tokens }), isMoreOpen ? (_jsxs("div", { style: {
195
+ } }), _jsx(EmojiPicker, { open: isEmojiOpen, isMobile: false, anchorRef: emojiAnchorRef, onSelect: insertEmoji, onClose: () => setIsEmojiOpen(false) }), _jsx(AttachmentPreview, { attachments: attachments.attachments, tokens: tokens, onRemove: attachments.removeAttachment }), isMoreOpen ? (_jsxs("div", { style: {
183
196
  position: "absolute",
184
197
  left: 0,
185
198
  right: 0,
@@ -199,7 +212,7 @@ function DesktopInner(props) {
199
212
  display: "flex",
200
213
  flexDirection: "column",
201
214
  gap: 12,
202
- }, children: [_jsx(TextComposer, { ref: textComposerRef, tokens: tokens, value: state.text, rows: 3, placeholder: "Message PMate", onKeyDown: (event) => {
215
+ }, children: [_jsx(TextComposer, { ref: textComposerRef, tokens: tokens, value: state.text, rows: 3, placeholder: "Message PMate", onPaste: handlePaste, onDrop: props.onDrop, onKeyDown: (event) => {
203
216
  if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
204
217
  event.preventDefault();
205
218
  if (state.text.trim() || state.attachments.length > 0)
@@ -266,7 +279,7 @@ function DesktopInner(props) {
266
279
  padding: "0 14px",
267
280
  display: "flex",
268
281
  alignItems: "center",
269
- }, children: _jsx(TextComposer, { ref: textComposerRef, tokens: tokens, value: state.text, rows: 1, placeholder: "Message PMate", onKeyDown: (event) => {
282
+ }, children: _jsx(TextComposer, { ref: textComposerRef, tokens: tokens, value: state.text, rows: 1, placeholder: "Message PMate", onPaste: handlePaste, onDrop: props.onDrop, onKeyDown: (event) => {
270
283
  if (event.key !== "Enter") {
271
284
  return;
272
285
  }
@@ -114,6 +114,19 @@ function MobileInner(props) {
114
114
  file,
115
115
  });
116
116
  };
117
+ const handlePaste = (event) => {
118
+ props.onPaste?.(event);
119
+ if (event.defaultPrevented || props.enableImage === false)
120
+ return;
121
+ const images = [...event.clipboardData.items]
122
+ .filter((item) => item.kind === "file" && item.type.startsWith("image/"))
123
+ .flatMap((item) => item.getAsFile() ? [item.getAsFile()] : []);
124
+ if (!images.length)
125
+ return;
126
+ event.preventDefault();
127
+ for (const image of images)
128
+ void handleImageFile(image);
129
+ };
117
130
  const isRecordingOverlayVisible = state.status === "recording" || state.status === "transcribing";
118
131
  const isTranscriptConfirmVisible = state.status === "transcript-ready" && Boolean(state.transcript);
119
132
  const transcriptConfirmSurface = `color-mix(in srgb, ${tokens.color.surfaceInputFocus} 86%, ${tokens.color.brandPrimary})`;
@@ -455,7 +468,7 @@ function MobileInner(props) {
455
468
  lineHeight: "24px",
456
469
  fontWeight: 700,
457
470
  opacity: props.disabled || !transcriptDraft.trim() ? 0.5 : 1,
458
- }, children: "\u53D1\u9001" })] })] })) : null, _jsx(AttachmentPreview, { attachments: attachments.attachments, tokens: tokens }), _jsx("input", { ref: imageInputRef, type: "file", accept: props.image?.accept ?? "image/*", style: { display: "none" }, onChange: (event) => {
471
+ }, children: "\u53D1\u9001" })] })] })) : null, _jsx(AttachmentPreview, { attachments: attachments.attachments, tokens: tokens, onRemove: attachments.removeAttachment }), _jsx("input", { ref: imageInputRef, type: "file", accept: props.image?.accept ?? "image/*", style: { display: "none" }, onChange: (event) => {
459
472
  const file = event.target.files?.[0];
460
473
  if (file) {
461
474
  void handleImageFile(file);
@@ -539,7 +552,7 @@ function MobileInner(props) {
539
552
  }, onPressCancel: () => {
540
553
  setRecordingChoice("send");
541
554
  voice.cancelRecording();
542
- } }) })) : (_jsx(TextComposer, { ref: textComposerRef, tokens: tokens, value: state.text, rows: 1, wrap: "off", placeholder: "Message", enterKeyHint: "send", onKeyDown: (event) => {
555
+ } }) })) : (_jsx(TextComposer, { ref: textComposerRef, tokens: tokens, value: state.text, rows: 1, wrap: "off", placeholder: "Message", enterKeyHint: "send", onPaste: handlePaste, onDrop: props.onDrop, onKeyDown: (event) => {
543
556
  if (event.key === "Enter" && !event.shiftKey) {
544
557
  event.preventDefault();
545
558
  if (state.text.trim()) {
@@ -9,7 +9,8 @@ export declare function useVoiceInputController(config?: ChatVoiceConfig): {
9
9
  beginVoiceMode: () => void;
10
10
  setMode: (args_0: import("..").ChatInputMode | ((prev: import("..").ChatInputMode) => import("..").ChatInputMode)) => void;
11
11
  clearTranscriptPreview: () => void;
12
- startRecording: () => void;
12
+ prepareRecording: () => Promise<boolean>;
13
+ startRecording: () => Promise<boolean>;
13
14
  cancelRecording: (message?: string | null) => void;
14
15
  stopRecording: (action?: StopAction) => void;
15
16
  };
@@ -3,7 +3,7 @@ import { useEffect, useRef, useState } from "react";
3
3
  import { waveformLevelsAtom, recordingDurationMsAtom } from "../atoms/voiceAtoms";
4
4
  import { insertTranscriptText } from "./useTranscriptComposer";
5
5
  import { useChatInputState } from "./useChatInputState";
6
- import { MicEvents, MicStateManager } from "../voice/MicStateManager";
6
+ import { MicEvents, MicState, MicStateManager } from "../voice/MicStateManager";
7
7
  const DEFAULT_WAVEFORM = [
8
8
  0.18, 0.28, 0.42, 0.58, 0.74, 0.9, 0.74, 0.58, 0.42, 0.28, 0.18,
9
9
  ];
@@ -32,6 +32,11 @@ export function useVoiceInputController(config) {
32
32
  const unsubLevel = manager.on(MicEvents.Level, (nextLevels) => {
33
33
  setLevels(nextLevels);
34
34
  });
35
+ const unsubState = manager.on(MicEvents.StateChanged, ({ state }) => {
36
+ if (state === MicState.Recording) {
37
+ setStatus("recording");
38
+ }
39
+ });
35
40
  const unsubFinished = manager.on(MicEvents.Finished, (blob) => {
36
41
  setLevels(DEFAULT_WAVEFORM);
37
42
  setDurationMs(0);
@@ -63,6 +68,7 @@ export function useVoiceInputController(config) {
63
68
  return () => {
64
69
  unsubData();
65
70
  unsubLevel();
71
+ unsubState();
66
72
  unsubFinished();
67
73
  unsubAbort();
68
74
  unsubError();
@@ -128,11 +134,18 @@ export function useVoiceInputController(config) {
128
134
  setStatus(modeRef.current === "voice" ? "voice-mode-ready" : "idle");
129
135
  setError(null);
130
136
  }
131
- function startRecording() {
137
+ async function prepareRecording() {
138
+ setError(null);
139
+ setPendingTranscriptBlob(null);
140
+ setTranscript("");
141
+ setDurationMs(0);
142
+ abortMessageRef.current = null;
143
+ return await managerRef.current?.prepare() ?? false;
144
+ }
145
+ async function startRecording() {
132
146
  if (status === "recording") {
133
- return;
147
+ return true;
134
148
  }
135
- setStatus("recording");
136
149
  setError(null);
137
150
  setPendingTranscriptBlob(null);
138
151
  setTranscript("");
@@ -140,7 +153,7 @@ export function useVoiceInputController(config) {
140
153
  setLevels(DEFAULT_WAVEFORM);
141
154
  abortMessageRef.current = null;
142
155
  stopActionRef.current = "send";
143
- void managerRef.current?.start();
156
+ return await managerRef.current?.start() ?? false;
144
157
  }
145
158
  function cancelRecording(message = null) {
146
159
  abortMessageRef.current = message;
@@ -163,6 +176,7 @@ export function useVoiceInputController(config) {
163
176
  beginVoiceMode,
164
177
  setMode,
165
178
  clearTranscriptPreview,
179
+ prepareRecording,
166
180
  startRecording,
167
181
  cancelRecording,
168
182
  stopRecording,
@@ -1,4 +1,4 @@
1
- import type { ComponentType, ReactNode } from "react";
1
+ import type { ClipboardEventHandler, ComponentType, DragEventHandler, ReactNode } from "react";
2
2
  import type { ChatAttachment } from "./attachment";
3
3
  import type { ChatVoiceConfig } from "./voice";
4
4
  export type DeepPartial<T> = {
@@ -115,6 +115,10 @@ export type ChatInputBaseProps = {
115
115
  value?: string;
116
116
  defaultValue?: string;
117
117
  onChange?: (value: string) => void;
118
+ /** Receives paste events before built-in image extraction. Call preventDefault() to fully own the event. */
119
+ onPaste?: ClipboardEventHandler<HTMLTextAreaElement>;
120
+ /** Receives drop events from the internal textarea so hosts can accept files or custom payloads. */
121
+ onDrop?: DragEventHandler<HTMLTextAreaElement>;
118
122
  onSend?: (payload: {
119
123
  text: string;
120
124
  attachments: ChatAttachment[];
@@ -1,7 +1,9 @@
1
+ import { Recorder } from "./Recorder";
1
2
  export declare enum MicState {
2
3
  Idle = 0,
3
4
  Initializing = 1,
4
- Recording = 2
5
+ Recording = 2,
6
+ Ready = 3
5
7
  }
6
8
  export declare enum MicEvents {
7
9
  StateChanged = "stateChanged",
@@ -21,17 +23,22 @@ type MicEventMap = {
21
23
  [MicEvents.Abort]: () => void;
22
24
  [MicEvents.Error]: (error: Error) => void;
23
25
  };
26
+ type RecorderController = Pick<Recorder, "on" | "init" | "startRecording" | "stopRecording" | "detachStream" | "dispose">;
24
27
  export declare class MicStateManager {
25
28
  private recorder;
26
29
  private state;
27
30
  private chunks;
28
31
  private stream;
32
+ private preparePromise;
33
+ private operationId;
29
34
  private listeners;
30
35
  private initialized;
36
+ constructor(recorder?: RecorderController);
31
37
  on<K extends MicEvents>(event: K, handler: MicEventMap[K]): () => void;
32
38
  private emit;
33
39
  init(): void;
34
- start(): Promise<void>;
40
+ prepare(): Promise<boolean>;
41
+ start(): Promise<boolean>;
35
42
  stop(): void;
36
43
  abort(): void;
37
44
  dispose(): void;
@@ -4,6 +4,7 @@ export var MicState;
4
4
  MicState[MicState["Idle"] = 0] = "Idle";
5
5
  MicState[MicState["Initializing"] = 1] = "Initializing";
6
6
  MicState[MicState["Recording"] = 2] = "Recording";
7
+ MicState[MicState["Ready"] = 3] = "Ready";
7
8
  })(MicState || (MicState = {}));
8
9
  export var MicEvents;
9
10
  (function (MicEvents) {
@@ -15,10 +16,12 @@ export var MicEvents;
15
16
  MicEvents["Error"] = "error";
16
17
  })(MicEvents || (MicEvents = {}));
17
18
  export class MicStateManager {
18
- recorder = new Recorder();
19
+ recorder;
19
20
  state = MicState.Idle;
20
21
  chunks = [];
21
22
  stream;
23
+ preparePromise = null;
24
+ operationId = 0;
22
25
  listeners = {
23
26
  [MicEvents.StateChanged]: new Set(),
24
27
  [MicEvents.Data]: new Set(),
@@ -28,6 +31,9 @@ export class MicStateManager {
28
31
  [MicEvents.Error]: new Set(),
29
32
  };
30
33
  initialized = false;
34
+ constructor(recorder = new Recorder()) {
35
+ this.recorder = recorder;
36
+ }
31
37
  on(event, handler) {
32
38
  this.listeners[event].add(handler);
33
39
  return () => {
@@ -62,44 +68,93 @@ export class MicStateManager {
62
68
  this.reset();
63
69
  });
64
70
  this.recorder.on(RecorderEvents.Error, (error) => {
71
+ if (this.state === MicState.Initializing) {
72
+ return;
73
+ }
65
74
  this.abort();
66
75
  this.emit(MicEvents.Error, error);
67
76
  });
68
77
  }
69
- async start() {
70
- if (this.state === MicState.Initializing || this.state === MicState.Recording) {
71
- return;
78
+ async prepare() {
79
+ if (this.state === MicState.Ready || this.state === MicState.Recording) {
80
+ return true;
81
+ }
82
+ if (this.state === MicState.Initializing && this.preparePromise) {
83
+ return await this.preparePromise;
72
84
  }
85
+ const operationId = ++this.operationId;
73
86
  this.setState(MicState.Initializing);
74
- try {
87
+ this.releaseStream();
88
+ const preparePromise = (async () => {
75
89
  if (!navigator.mediaDevices?.getUserMedia) {
76
90
  throw new Error("Microphone access is not available in this browser.");
77
91
  }
78
- this.releaseStream();
79
- this.stream = await navigator.mediaDevices.getUserMedia({
92
+ const stream = await navigator.mediaDevices.getUserMedia({
80
93
  audio: {
81
94
  echoCancellation: true,
82
95
  noiseSuppression: true,
83
96
  autoGainControl: true,
84
97
  },
85
98
  });
86
- await this.recorder.init(this.stream);
87
- this.stream.getTracks().forEach((track) => {
88
- track.enabled = true;
89
- });
99
+ if (operationId !== this.operationId) {
100
+ stream.getTracks().forEach((track) => track.stop());
101
+ return false;
102
+ }
103
+ this.stream = stream;
104
+ await this.recorder.init(stream);
105
+ if (operationId !== this.operationId) {
106
+ this.releaseStream();
107
+ return false;
108
+ }
109
+ this.pauseStream();
110
+ this.setState(MicState.Ready);
111
+ return true;
112
+ })();
113
+ this.preparePromise = preparePromise;
114
+ try {
115
+ return await preparePromise;
116
+ }
117
+ catch (error) {
118
+ if (operationId !== this.operationId) {
119
+ return false;
120
+ }
121
+ this.releaseStream();
122
+ this.reset();
123
+ this.emit(MicEvents.Error, toError(error));
124
+ return false;
125
+ }
126
+ finally {
127
+ if (this.preparePromise === preparePromise) {
128
+ this.preparePromise = null;
129
+ }
130
+ }
131
+ }
132
+ async start() {
133
+ if (this.state === MicState.Recording) {
134
+ return true;
135
+ }
136
+ if (this.state !== MicState.Ready && !(await this.prepare())) {
137
+ return false;
138
+ }
139
+ try {
90
140
  await this.recorder.startRecording();
91
141
  this.setState(MicState.Recording);
142
+ return true;
92
143
  }
93
144
  catch (error) {
145
+ this.releaseStream();
94
146
  this.reset();
95
147
  this.emit(MicEvents.Error, toError(error));
148
+ return false;
96
149
  }
97
150
  }
98
151
  stop() {
99
- if (this.state !== MicState.Initializing && this.state !== MicState.Recording) {
152
+ if (this.state !== MicState.Initializing
153
+ && this.state !== MicState.Ready
154
+ && this.state !== MicState.Recording) {
100
155
  return;
101
156
  }
102
- if (this.state === MicState.Initializing) {
157
+ if (this.state !== MicState.Recording) {
103
158
  this.abort();
104
159
  return;
105
160
  }
@@ -112,6 +167,7 @@ export class MicStateManager {
112
167
  if (this.state === MicState.Idle) {
113
168
  return;
114
169
  }
170
+ this.operationId += 1;
115
171
  this.recorder.stopRecording();
116
172
  this.recorder.detachStream();
117
173
  this.pauseStream();
@@ -119,6 +175,7 @@ export class MicStateManager {
119
175
  this.reset();
120
176
  }
121
177
  dispose() {
178
+ this.operationId += 1;
122
179
  this.recorder.stopRecording();
123
180
  this.releaseStream();
124
181
  this.recorder.dispose();
@@ -46,6 +46,7 @@ export class Recorder {
46
46
  async init(stream) {
47
47
  await this.ensureAudioGraph();
48
48
  this.attachStream(stream);
49
+ await this.audioContext?.resume();
49
50
  this.initialized = true;
50
51
  }
51
52
  async ensureAudioGraph() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pmate/chat-sdk",
3
- "version": "0.1.18",
3
+ "version": "0.1.20",
4
4
  "description": "Cross-platform PMate chat input components, voice input primitives, and ASR helpers",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",