@botuyo/chat-widget-standalone 1.0.84 → 1.0.85
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/LICENSE +21 -21
- package/dist/{AudioPlayer-CmWNaFAM.js → AudioPlayer-DI98JrBM.js} +2 -2
- package/dist/AudioPlayer-DI98JrBM.js.map +1 -0
- package/dist/Avatar3D-LfNJe183.js +9 -0
- package/dist/Avatar3D-LfNJe183.js.map +1 -0
- package/dist/{Gallery-Bg8EmBE6.js → Gallery-CSN57fUw.js} +2 -2
- package/dist/Gallery-CSN57fUw.js.map +1 -0
- package/dist/botuyo-chat.es.js +1 -1
- package/dist/botuyo-chat.umd.js +1 -1
- package/dist/botuyo-chat.umd.js.map +1 -1
- package/dist/src/chat-widget/components/Avatar3D.d.ts.map +1 -1
- package/dist/src/chat-widget/components/Gallery.stories.d.ts.map +1 -1
- package/dist/src/chat-widget/components/VoiceCallOverlay.d.ts.map +1 -1
- package/dist/src/chat-widget/voice/index.d.ts +0 -1
- package/dist/src/chat-widget/voice/index.d.ts.map +1 -1
- package/dist/src/chat-widget/voice/useLiveCall.d.ts.map +1 -1
- package/dist/src/chat-widget/voice/useVoiceChat.d.ts.map +1 -1
- package/dist/{standalone-B8sCmApK.js → standalone-D-wUb5qW.js} +33 -33
- package/dist/standalone-D-wUb5qW.js.map +1 -0
- package/dist/stats-umd.html +1 -1
- package/dist/stats.html +1 -1
- package/package.json +157 -156
- package/dist/AudioPlayer-CmWNaFAM.js.map +0 -1
- package/dist/Avatar3D-CoXzuLgX.js +0 -9
- package/dist/Avatar3D-CoXzuLgX.js.map +0 -1
- package/dist/Gallery-Bg8EmBE6.js.map +0 -1
- package/dist/src/chat-widget/voice/audioEnhancement.d.ts +0 -89
- package/dist/src/chat-widget/voice/audioEnhancement.d.ts.map +0 -1
- package/dist/standalone-B8sCmApK.js.map +0 -1
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Paseo Libre
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Paseo Libre
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{jsxs as e,jsx as r,Fragment as t}from"react/jsx-runtime";import{memo as a,useState as l,useRef as o,useMemo as n,useCallback as i}from"react";import{c,g as s,a as d,L as u}from"./standalone-
|
|
1
|
+
import{jsxs as e,jsx as r,Fragment as t}from"react/jsx-runtime";import{memo as a,useState as l,useRef as o,useMemo as n,useCallback as i}from"react";import{c,g as s,a as d,L as u}from"./standalone-D-wUb5qW.js";const h=c("CircleAlert",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["line",{x1:"12",x2:"12",y1:"8",y2:"12",key:"1pkeuh"}],["line",{x1:"12",x2:"12.01",y1:"16",y2:"16",key:"4dfq90"}]]),m=c("Pause",[["rect",{x:"14",y:"4",width:"4",height:"16",rx:"1",key:"zuxfzm"}],["rect",{x:"6",y:"4",width:"4",height:"16",rx:"1",key:"1okwgv"}]]),y=c("Play",[["polygon",{points:"6 3 20 12 6 21 6 3",key:"1oa8hb"}]]),p=c("RotateCw",[["path",{d:"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8",key:"1p45f6"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}]]),f=a(function({url:a,isBot:c,primaryColor:f}){const[x,g]=l(!1),[w,k]=l(0),[N,b]=l(0),[v,C]=l(!0),[M,P]=l(null),j=o(null),S=n(()=>s({primaryColor:f}),[f]),A=i(()=>{M||(x?j.current?.pause():j.current?.play().catch(e=>{console.error("[AudioPlayer] Play error:",e),P("Error al reproducir")}),g(!x))},[x,M]),E=i(()=>{k(j.current?.duration||0)},[]),L=i(()=>{C(!1),P(null)},[]),T=i(()=>{console.error("[AudioPlayer] Failed to load audio:",a),C(!1),P("No se pudo cargar")},[a]),$=i(()=>{C(!0),P(null),j.current&&j.current.load()},[]);/* @__PURE__ */
|
|
2
2
|
return e("div",{className:d("flex items-center gap-3 py-1 min-w-[200px]",c?"text-foreground":"text-primary-foreground"),children:[
|
|
3
3
|
/* @__PURE__ */r("audio",{ref:j,src:a,preload:"metadata",onLoadedMetadata:E,onCanPlayThrough:L,onTimeUpdate:()=>b(j.current?.currentTime||0),onEnded:()=>g(!1),onError:T}),
|
|
4
4
|
/* @__PURE__ */r("button",M?{onClick:$,className:"w-8 h-8 rounded-full flex items-center justify-center shrink-0 bg-red-500/20 text-red-500 hover:bg-red-500/30 transition-colors",title:"Reintentar",children:/* @__PURE__ */r(p,{className:"w-4 h-4"})}:{onClick:A,disabled:v,className:"w-8 h-8 rounded-full flex items-center justify-center shrink-0 transition-opacity",style:{backgroundColor:c?S:"hsl(var(--card))",color:c?"white":S,opacity:v?.6:1},children:v?/* @__PURE__ */r(u,{className:"w-4 h-4 animate-spin"}):x?/* @__PURE__ */r(m,{className:"w-4 h-4 fill-current"}):/* @__PURE__ */r(y,{className:"w-4 h-4 fill-current ml-0.5"})}),
|
|
@@ -9,4 +9,4 @@ return e("div",{className:d("flex items-center gap-3 py-1 min-w-[200px]",c?"text
|
|
|
9
9
|
/* @__PURE__ */e("div",{className:"flex justify-between text-[9px] font-bold opacity-60",children:[
|
|
10
10
|
/* @__PURE__ */e("span",{children:[Math.floor(N/60),":",Math.floor(N%60).toString().padStart(2,"0")]}),
|
|
11
11
|
/* @__PURE__ */r("span",{children:v?"--:--":`${Math.floor(w/60)}:${Math.floor(w%60).toString().padStart(2,"0")}`})]})]})})]})});export{f as AudioPlayer};
|
|
12
|
-
//# sourceMappingURL=AudioPlayer-
|
|
12
|
+
//# sourceMappingURL=AudioPlayer-DI98JrBM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AudioPlayer-DI98JrBM.js","sources":["../node_modules/lucide-react/dist/esm/icons/circle-alert.js","../node_modules/lucide-react/dist/esm/icons/pause.js","../node_modules/lucide-react/dist/esm/icons/play.js","../node_modules/lucide-react/dist/esm/icons/rotate-cw.js","../src/chat-widget/components/AudioPlayer.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.400.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleAlert = createLucideIcon(\"CircleAlert\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"8\", y2: \"12\", key: \"1pkeuh\" }],\n [\"line\", { x1: \"12\", x2: \"12.01\", y1: \"16\", y2: \"16\", key: \"4dfq90\" }]\n]);\n\nexport { CircleAlert as default };\n//# sourceMappingURL=circle-alert.js.map\n","/**\n * @license lucide-react v0.400.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Pause = createLucideIcon(\"Pause\", [\n [\"rect\", { x: \"14\", y: \"4\", width: \"4\", height: \"16\", rx: \"1\", key: \"zuxfzm\" }],\n [\"rect\", { x: \"6\", y: \"4\", width: \"4\", height: \"16\", rx: \"1\", key: \"1okwgv\" }]\n]);\n\nexport { Pause as default };\n//# sourceMappingURL=pause.js.map\n","/**\n * @license lucide-react v0.400.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Play = createLucideIcon(\"Play\", [\n [\"polygon\", { points: \"6 3 20 12 6 21 6 3\", key: \"1oa8hb\" }]\n]);\n\nexport { Play as default };\n//# sourceMappingURL=play.js.map\n","/**\n * @license lucide-react v0.400.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst RotateCw = createLucideIcon(\"RotateCw\", [\n [\"path\", { d: \"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8\", key: \"1p45f6\" }],\n [\"path\", { d: \"M21 3v5h-5\", key: \"1q7to0\" }]\n]);\n\nexport { RotateCw as default };\n//# sourceMappingURL=rotate-cw.js.map\n","'use client'\r\n\r\nimport { useState, useRef, useMemo, memo, useCallback } from 'react'\r\nimport { Play, Pause, Loader2, AlertCircle, RotateCw } from './Icons'\r\nimport { cn } from '@/lib/utils'\r\nimport { getPrimaryColor } from '../utils/theme'\r\n\r\ninterface AudioPlayerProps {\r\n url: string\r\n isBot: boolean\r\n primaryColor?: string\r\n}\r\n\r\nexport type { AudioPlayerProps }\r\n\r\nexport const AudioPlayer = memo(function AudioPlayer({\r\n url,\r\n isBot,\r\n primaryColor,\r\n}: AudioPlayerProps) {\r\n const [isPlaying, setIsPlaying] = useState(false)\r\n const [duration, setDuration] = useState(0)\r\n const [currentTime, setCurrentTime] = useState(0)\r\n // Blob URLs from URL.createObjectURL() are valid during the current session\r\n const [isLoading, setIsLoading] = useState(true)\r\n const [error, setError] = useState<string | null>(null)\r\n const audioRef = useRef<HTMLAudioElement>(null)\r\n\r\n const brandColor = useMemo(() => getPrimaryColor({ primaryColor }), [primaryColor])\r\n\r\n const togglePlay = useCallback(() => {\r\n if (error) return\r\n if (isPlaying) audioRef.current?.pause()\r\n else audioRef.current?.play().catch((e) => {\r\n console.error('[AudioPlayer] Play error:', e)\r\n setError('Error al reproducir')\r\n })\r\n setIsPlaying(!isPlaying)\r\n }, [isPlaying, error])\r\n\r\n const handleLoadedMetadata = useCallback(() => {\r\n setDuration(audioRef.current?.duration || 0)\r\n }, [])\r\n\r\n const handleCanPlayThrough = useCallback(() => {\r\n setIsLoading(false)\r\n setError(null)\r\n }, [])\r\n\r\n const handleError = useCallback(() => {\r\n console.error('[AudioPlayer] Failed to load audio:', url)\r\n setIsLoading(false)\r\n setError('No se pudo cargar')\r\n }, [url])\r\n\r\n const handleRetry = useCallback(() => {\r\n setIsLoading(true)\r\n setError(null)\r\n if (audioRef.current) {\r\n audioRef.current.load()\r\n }\r\n }, [])\r\n\r\n return (\r\n <div\r\n className={cn(\r\n 'flex items-center gap-3 py-1 min-w-[200px]',\r\n isBot ? 'text-foreground' : 'text-primary-foreground'\r\n )}\r\n >\r\n {/* Always render <audio> — onError handles expired URLs naturally */}\r\n <audio\r\n ref={audioRef}\r\n src={url}\r\n preload=\"metadata\"\r\n onLoadedMetadata={handleLoadedMetadata}\r\n onCanPlayThrough={handleCanPlayThrough}\r\n onTimeUpdate={() => setCurrentTime(audioRef.current?.currentTime || 0)}\r\n onEnded={() => setIsPlaying(false)}\r\n onError={handleError}\r\n />\r\n \r\n {error ? (\r\n // Error state - show retry button\r\n <button\r\n onClick={handleRetry}\r\n className=\"w-8 h-8 rounded-full flex items-center justify-center shrink-0 bg-red-500/20 text-red-500 hover:bg-red-500/30 transition-colors\"\r\n title=\"Reintentar\"\r\n >\r\n <RotateCw className=\"w-4 h-4\" />\r\n </button>\r\n ) : (\r\n // Normal play/pause button\r\n <button\r\n onClick={togglePlay}\r\n disabled={isLoading}\r\n className=\"w-8 h-8 rounded-full flex items-center justify-center shrink-0 transition-opacity\"\r\n style={{\r\n backgroundColor: isBot ? brandColor : 'hsl(var(--card))',\r\n color: isBot ? 'white' : brandColor,\r\n opacity: isLoading ? 0.6 : 1,\r\n }}\r\n >\r\n {isLoading ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : isPlaying ? (\r\n <Pause className=\"w-4 h-4 fill-current\" />\r\n ) : (\r\n <Play className=\"w-4 h-4 fill-current ml-0.5\" />\r\n )}\r\n </button>\r\n )}\r\n \r\n <div className=\"flex-1 space-y-1\">\r\n {error ? (\r\n <div className=\"flex items-center gap-1.5 text-red-500\">\r\n <AlertCircle className=\"w-3 h-3\" />\r\n <span className=\"text-[9px] font-bold\">{error}</span>\r\n </div>\r\n ) : (\r\n <>\r\n <div className=\"relative h-1 w-full bg-current/20 rounded-full overflow-hidden\">\r\n <div\r\n className=\"absolute h-full bg-current rounded-full transition-all\"\r\n style={{ width: `${(currentTime / duration) * 100 || 0}%` }}\r\n />\r\n </div>\r\n <div className=\"flex justify-between text-[9px] font-bold opacity-60\">\r\n <span>\r\n {Math.floor(currentTime / 60)}:\r\n {Math.floor(currentTime % 60)\r\n .toString()\r\n .padStart(2, '0')}\r\n </span>\r\n <span>\r\n {isLoading ? '--:--' : `${Math.floor(duration / 60)}:${Math.floor(duration % 60).toString().padStart(2, '0')}`}\r\n </span>\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n </div>\r\n )\r\n})\r\n"],"names":["CircleAlert","createLucideIcon","cx","cy","r","key","x1","x2","y1","y2","Pause","x","y","width","height","rx","Play","points","RotateCw","d","AudioPlayer","memo","url","isBot","primaryColor","isPlaying","setIsPlaying","useState","duration","setDuration","currentTime","setCurrentTime","isLoading","setIsLoading","error","setError","audioRef","useRef","brandColor","useMemo","getPrimaryColor","togglePlay","useCallback","current","pause","play","catch","e","console","handleLoadedMetadata","handleCanPlayThrough","handleError","handleRetry","load","jsxs","className","cn","children","jsx","ref","src","preload","onLoadedMetadata","onCanPlayThrough","onTimeUpdate","onEnded","onError","onClick","title","disabled","style","backgroundColor","color","opacity","Loader2","AlertCircle","Fragment","Math","floor","toString","padStart"],"mappings":"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","x_google_ignoreList":[0,1,2,3]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useMemo as r,useEffect as n,useRef as o}from"react";import{Canvas as a,useThree as i,useFrame as s}from"@react-three/fiber";import{VRMLoaderPlugin as c,VRMExpressionPresetName as l}from"@pixiv/three-vrm";import*as u from"three";import{GLTFLoader as p}from"three/examples/jsm/loaders/GLTFLoader.js";const d={default:{expressions:{[l.Neutral]:1}},happy:{expressions:{[l.Happy]:.8}},angry:{expressions:{[l.Angry]:.7},headRotation:[.05,0,0]},sorry:{expressions:{[l.Sad]:.6},headRotation:[-.08,0,0]},confused:{expressions:{[l.Sad]:.3},headRotation:[0,0,.08]},love:{expressions:{[l.Happy]:.9,[l.Relaxed]:.4}},thinking:{expressions:{[l.Neutral]:.6},headRotation:[.06,-.1,0]},writing:{expressions:{[l.Neutral]:.8},headRotation:[-.05,0,0]},wink:{expressions:{[l.Happy]:.5,[l.Blink]:.9}}};function h({url:e,emotion:t,callState:r,audioLevel:a}){const h=o(null),m=o(null),f=o(null),g=o(0),x=o(1),M=o(0),y=o(3.5),w=o(0),v=o({}),k=o({}),b=o(new u.Euler(0,0,0)),A=o(0),{scene:S,camera:V}=i();return n(()=>{const t=new p;return t.register(e=>new c(e)),t.load(e,e=>{const t=e.userData?.vrm;if(t){h.current=t,t.scene.rotation.y=Math.PI;const e=(new u.Box3).setFromObject(t.scene),r=e.getCenter(new u.Vector3),n=e.getSize(new u.Vector3).y;t.scene.position.y=-r.y-.05*n,A.current=t.scene.position.y,S.add(t.scene)}else{console.info("[Avatar3D] Plain GLB model detected, using fallback animations");const t=e.scene;t.updateMatrixWorld(!0);const r=(new u.Box3).setFromObject(t),n=r.getCenter(new u.Vector3),o=r.getSize(new u.Vector3),a=new u.Group;t.position.sub(n),a.add(t),g.current=0,m.current=a,A.current=0,x.current=1,S.add(a);const i=V.fov*(Math.PI/180),s=.35*o.y,c=.5*o.y/Math.tan(i/2);if(V.position.set(0,s,-c),V.lookAt(0,s,0),e.animations.length>0){const r=new u.AnimationMixer(t);f.current=r,e.animations.forEach(e=>{r.clipAction(e).play()})}}},void 0,e=>{console.error("[Avatar3D] Failed to load model:",e)}),()=>{h.current&&(S.remove(h.current.scene),h.current=null),m.current&&(S.remove(m.current),m.current=null),f.current&&(f.current.stopAllAction(),f.current=null)}},[e,S]),n(()=>{const e=d[t||"default"]||d.default;k.current=e.expressions,e.headRotation?b.current.set(...e.headRotation):b.current.set(0,0,0)},[t]),s((e,t)=>{const n=Math.min(t,.1);w.current+=1.2*n;const o=m.current;if(o){f.current&&f.current.update(n);const e=.003*Math.sin(w.current);o.position.y=A.current+e;const t=.02*Math.sin(.3*w.current);if(o.rotation.y=g.current+t,"speaking"===r&&a>.01){const e=1+.03*a,t=x.current*e,r=o.scale.x;o.scale.setScalar(u.MathUtils.lerp(r,t,.1))}else{const e=o.scale.x;Math.abs(e-x.current)>.001&&o.scale.setScalar(u.MathUtils.lerp(e,x.current,.05))}return}const i=h.current;if(!i)return;const s=.003*Math.sin(w.current);if(i.scene.position.y=A.current+s,M.current+=n,M.current>=y.current){const e=(M.current-y.current)/.15;e<1?i.expressionManager?.setValue(l.Blink,e):e<2?i.expressionManager?.setValue(l.Blink,2-e):(i.expressionManager?.setValue(l.Blink,0),M.current=0,y.current=4*Math.random()+2)}const c=4*n,p=/* @__PURE__ */new Set([...Object.keys(v.current),...Object.keys(k.current)]);for(const r of p){const e=v.current[r]||0,t=k.current[r]||0,n=u.MathUtils.lerp(e,t,c);v.current[r]=n,r===l.Blink&&M.current>=y.current||i.expressionManager?.setValue(r,n)}if("speaking"===r&&a>.01){const e=Math.min(1.5*a,.8),t=i.expressionManager?.getValue(l.Aa)||0,r=u.MathUtils.lerp(t,e,8*n);i.expressionManager?.setValue(l.Aa,r)}else{const e=i.expressionManager?.getValue(l.Aa)||0;e>.01&&i.expressionManager?.setValue(l.Aa,.9*e)}if(i.humanoid){const e=i.humanoid.getNormalizedBoneNode("head");if(e){const t=.01*Math.sin(.3*w.current),r=.005*Math.cos(.2*w.current),o=b.current.x+t,a=b.current.y,i=b.current.z+r;e.rotation.x=u.MathUtils.lerp(e.rotation.x,o,3*n),e.rotation.y=u.MathUtils.lerp(e.rotation.y,a,3*n),e.rotation.z=u.MathUtils.lerp(e.rotation.z,i,3*n)}}if("listening"===r&&i.humanoid){const e=i.humanoid.getNormalizedBoneNode("head");e&&(e.rotation.z=u.MathUtils.lerp(e.rotation.z,.03,2*n))}i.update(n)}),null}function m(){const{camera:e}=i();return n(()=>{e.position.set(0,.1,.6),e.lookAt(0,.1,0)},[e]),null}function f({modelUrl:n,emotion:o,callState:i,audioLevel:s,primaryColor:c,size:l}){const u=r(()=>{switch(i){case"speaking":return.6;case"listening":return.4;case"thinking":return.3;default:return.15}},[i]);/* @__PURE__ */
|
|
2
|
+
return e("div",{className:"relative flex flex-col items-center gap-4",children:/* @__PURE__ */e("div",{className:"relative rounded-full overflow-hidden",style:{width:`${l}px`,height:`${l}px`,boxShadow:"listening"===i||"speaking"===i?`0 0 0 3px ${c}50, 0 0 30px ${c}${Math.floor(255*u).toString(16).padStart(2,"0")}, 0 0 60px ${c}20`:`0 0 0 2px ${c}25`,transition:"box-shadow 0.5s ease"},children:/* @__PURE__ */t(a,{style:{width:"100%",height:"100%",background:"transparent"},gl:{alpha:!0,antialias:!0,preserveDrawingBuffer:!1},camera:{fov:30,near:.01,far:10},dpr:[1,2],children:[
|
|
3
|
+
/* @__PURE__ */e(m,{}),
|
|
4
|
+
/* @__PURE__ */e("ambientLight",{intensity:.6}),
|
|
5
|
+
/* @__PURE__ */e("directionalLight",{position:[1,2,3],intensity:.8,color:"#ffffff"}),
|
|
6
|
+
/* @__PURE__ */e("directionalLight",{position:[-1,1,-1],intensity:.3,color:"#b4c6e7"}),
|
|
7
|
+
/* @__PURE__ */e("pointLight",{position:[0,.5,-.5],intensity:2*u,color:c,distance:3}),
|
|
8
|
+
/* @__PURE__ */e(h,{url:n,emotion:o,callState:i,audioLevel:s})]})})})}export{f as default};
|
|
9
|
+
//# sourceMappingURL=Avatar3D-LfNJe183.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Avatar3D-LfNJe183.js","sources":["../src/chat-widget/components/Avatar3D.tsx"],"sourcesContent":["/**\r\n * @package @botuyo/chat-widget\r\n * Avatar3D Component — Lazy-loaded 3D avatar for voice calls\r\n *\r\n * Uses React Three Fiber + @pixiv/three-vrm to render VRM models\r\n * with emotion-driven blendshapes and idle animations.\r\n *\r\n * This component is loaded via React.lazy() — it adds 0KB to the\r\n * main bundle. Three.js + VRM are only downloaded when a tenant\r\n * has avatar3dUrl configured.\r\n */\r\n\r\n// React Three Fiber types are resolved via tsconfig\r\n'use client'\r\n\r\nimport { useRef, useEffect, useMemo } from 'react'\r\nimport { Canvas, useFrame, useThree } from '@react-three/fiber'\r\nimport { VRMLoaderPlugin, VRMExpressionPresetName, VRM } from '@pixiv/three-vrm'\r\nimport * as THREE from 'three'\r\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'\r\n\r\n// ═══════════════════════════════════════\r\n// TYPES\r\n// ═══════════════════════════════════════\r\n\r\ntype CallState = 'idle' | 'connecting' | 'listening' | 'speaking' | 'thinking'\r\n\r\ninterface Avatar3DProps {\r\n modelUrl: string\r\n emotion: string | null\r\n callState: CallState\r\n audioLevel: number\r\n primaryColor: string\r\n size: number\r\n}\r\n\r\n// ═══════════════════════════════════════\r\n// EMOTION → VRM BLENDSHAPE MAPPING\r\n// ═══════════════════════════════════════\r\n\r\ninterface EmotionConfig {\r\n expressions: Record<string, number> // VRM expression name → weight 0-1\r\n headRotation?: [number, number, number] // euler XYZ in radians\r\n}\r\n\r\nconst EMOTION_MAP: Record<string, EmotionConfig> = {\r\n default: {\r\n expressions: { [VRMExpressionPresetName.Neutral]: 1 },\r\n },\r\n happy: {\r\n expressions: { [VRMExpressionPresetName.Happy]: 0.8 },\r\n },\r\n angry: {\r\n expressions: { [VRMExpressionPresetName.Angry]: 0.7 },\r\n headRotation: [0.05, 0, 0],\r\n },\r\n sorry: {\r\n expressions: { [VRMExpressionPresetName.Sad]: 0.6 },\r\n headRotation: [-0.08, 0, 0],\r\n },\r\n confused: {\r\n expressions: { [VRMExpressionPresetName.Sad]: 0.3 },\r\n headRotation: [0, 0, 0.08],\r\n },\r\n love: {\r\n expressions: { [VRMExpressionPresetName.Happy]: 0.9, [VRMExpressionPresetName.Relaxed]: 0.4 },\r\n },\r\n thinking: {\r\n expressions: { [VRMExpressionPresetName.Neutral]: 0.6 },\r\n headRotation: [0.06, -0.1, 0],\r\n },\r\n writing: {\r\n expressions: { [VRMExpressionPresetName.Neutral]: 0.8 },\r\n headRotation: [-0.05, 0, 0],\r\n },\r\n wink: {\r\n expressions: { [VRMExpressionPresetName.Happy]: 0.5, [VRMExpressionPresetName.Blink]: 0.9 },\r\n },\r\n}\r\n\r\n// ═══════════════════════════════════════\r\n// VRM MODEL COMPONENT (inside Canvas)\r\n// ═══════════════════════════════════════\r\n\r\ninterface VRMModelProps {\r\n url: string\r\n emotion: string | null\r\n callState: CallState\r\n audioLevel: number\r\n}\r\n\r\nfunction VRMModel({ url, emotion, callState, audioLevel }: VRMModelProps) {\r\n const vrmRef = useRef<VRM | null>(null)\r\n const glbSceneRef = useRef<THREE.Group | null>(null)\r\n const mixerRef = useRef<THREE.AnimationMixer | null>(null)\r\n const baseRotationY = useRef(0)\r\n const baseScale = useRef(1)\r\n const blinkTimer = useRef(0)\r\n const nextBlinkAt = useRef(3.5) // Initial value, randomized in useFrame\r\n const breathPhase = useRef(0)\r\n const currentExpressions = useRef<Record<string, number>>({})\r\n const targetExpressions = useRef<Record<string, number>>({})\r\n const headTarget = useRef(new THREE.Euler(0, 0, 0))\r\n const baseY = useRef(0)\r\n const { scene, camera } = useThree()\r\n\r\n // Load model using Three.js GLTFLoader (with VRM plugin for VRM models)\r\n useEffect(() => {\r\n const loader = new GLTFLoader()\r\n loader.register((parser) => new VRMLoaderPlugin(parser) as any)\r\n\r\n loader.load(\r\n url,\r\n (gltf) => {\r\n const vrm = (gltf as any).userData?.vrm as VRM | undefined\r\n if (vrm) {\r\n // ── VRM MODEL PATH ──\r\n vrmRef.current = vrm\r\n vrm.scene.rotation.y = Math.PI\r\n const box = new THREE.Box3().setFromObject(vrm.scene)\r\n const center = box.getCenter(new THREE.Vector3())\r\n const height = box.getSize(new THREE.Vector3()).y\r\n vrm.scene.position.y = -center.y - height * 0.05\r\n baseY.current = vrm.scene.position.y\r\n scene.add(vrm.scene)\r\n } else {\r\n // ── PLAIN GLB FALLBACK ──\r\n console.info('[Avatar3D] Plain GLB model detected, using fallback animations')\r\n const model = gltf.scene\r\n\r\n // Force world matrix update so bbox is accurate\r\n model.updateMatrixWorld(true)\r\n const box = new THREE.Box3().setFromObject(model)\r\n const center = box.getCenter(new THREE.Vector3())\r\n const size = box.getSize(new THREE.Vector3())\r\n\r\n // Create pivot wrapper for proper rotation around geometric center\r\n const pivot = new THREE.Group()\r\n\r\n // Center model geometry at pivot origin\r\n model.position.sub(center)\r\n pivot.add(model)\r\n\r\n // Don't rotate the model — move the CAMERA to the front instead\r\n baseRotationY.current = 0\r\n\r\n glbSceneRef.current = pivot\r\n baseY.current = 0\r\n baseScale.current = 1\r\n scene.add(pivot)\r\n\r\n // Frame the HEAD: camera at -Z (model faces -Z based on tests)\r\n const fov = (camera as THREE.PerspectiveCamera).fov * (Math.PI / 180)\r\n const headY = size.y * 0.35\r\n const cameraZ = (size.y * 0.5) / Math.tan(fov / 2)\r\n // Camera on the -Z side to see the model's FRONT\r\n camera.position.set(0, headY, -cameraZ)\r\n camera.lookAt(0, headY, 0)\r\n\r\n // Play embedded animations if available\r\n if (gltf.animations.length > 0) {\r\n const mixer = new THREE.AnimationMixer(model)\r\n mixerRef.current = mixer\r\n gltf.animations.forEach((clip) => {\r\n mixer.clipAction(clip).play()\r\n })\r\n }\r\n }\r\n },\r\n undefined,\r\n (error) => {\r\n console.error('[Avatar3D] Failed to load model:', error)\r\n },\r\n )\r\n\r\n return () => {\r\n if (vrmRef.current) {\r\n scene.remove(vrmRef.current.scene)\r\n vrmRef.current = null\r\n }\r\n if (glbSceneRef.current) {\r\n scene.remove(glbSceneRef.current)\r\n glbSceneRef.current = null\r\n }\r\n if (mixerRef.current) {\r\n mixerRef.current.stopAllAction()\r\n mixerRef.current = null\r\n }\r\n }\r\n }, [url, scene])\r\n\r\n // Update target expressions when emotion changes (VRM only)\r\n useEffect(() => {\r\n const config = EMOTION_MAP[emotion || 'default'] || EMOTION_MAP.default\r\n targetExpressions.current = config.expressions\r\n if (config.headRotation) {\r\n headTarget.current.set(...config.headRotation)\r\n } else {\r\n headTarget.current.set(0, 0, 0)\r\n }\r\n }, [emotion])\r\n\r\n // Animation loop\r\n useFrame((_, delta) => {\r\n const dt = Math.min(delta, 0.1) // Cap delta to avoid jumps\r\n breathPhase.current += dt * 1.2\r\n\r\n // ── GLB FALLBACK ANIMATION ──\r\n const glb = glbSceneRef.current\r\n if (glb) {\r\n // Update animation mixer if present\r\n if (mixerRef.current) {\r\n mixerRef.current.update(dt)\r\n }\r\n\r\n // Gentle breathing bob\r\n const breathOffset = Math.sin(breathPhase.current) * 0.003\r\n glb.position.y = baseY.current + breathOffset\r\n\r\n // Subtle idle rotation (relative to base facing direction)\r\n const idleSway = Math.sin(breathPhase.current * 0.3) * 0.02\r\n glb.rotation.y = baseRotationY.current + idleSway\r\n\r\n // Audio-reactive scale pulse when speaking\r\n if (callState === 'speaking' && audioLevel > 0.01) {\r\n const pulse = 1 + audioLevel * 0.03\r\n const targetScale = baseScale.current * pulse\r\n const currentScale = glb.scale.x\r\n glb.scale.setScalar(THREE.MathUtils.lerp(currentScale, targetScale, 0.1))\r\n } else {\r\n // Return to base scale smoothly\r\n const currentScale = glb.scale.x\r\n if (Math.abs(currentScale - baseScale.current) > 0.001) {\r\n glb.scale.setScalar(THREE.MathUtils.lerp(currentScale, baseScale.current, 0.05))\r\n }\r\n }\r\n\r\n return // Skip VRM-specific code\r\n }\r\n\r\n // ── VRM ANIMATION (original code) ──\r\n const vrm = vrmRef.current\r\n if (!vrm) return\r\n\r\n // ── BREATHING ──\r\n const breathOffset = Math.sin(breathPhase.current) * 0.003\r\n vrm.scene.position.y = baseY.current + breathOffset\r\n\r\n // ── BLINKING ──\r\n blinkTimer.current += dt\r\n if (blinkTimer.current >= nextBlinkAt.current) {\r\n const blinkProgress = (blinkTimer.current - nextBlinkAt.current) / 0.15\r\n if (blinkProgress < 1) {\r\n vrm.expressionManager?.setValue(VRMExpressionPresetName.Blink, blinkProgress)\r\n } else if (blinkProgress < 2) {\r\n vrm.expressionManager?.setValue(VRMExpressionPresetName.Blink, 2 - blinkProgress)\r\n } else {\r\n vrm.expressionManager?.setValue(VRMExpressionPresetName.Blink, 0)\r\n blinkTimer.current = 0\r\n nextBlinkAt.current = Math.random() * 4 + 2\r\n }\r\n }\r\n\r\n // ── EMOTION BLENDING ──\r\n const lerpSpeed = 4 * dt\r\n const allKeys = new Set([\r\n ...Object.keys(currentExpressions.current),\r\n ...Object.keys(targetExpressions.current),\r\n ])\r\n\r\n for (const key of allKeys) {\r\n const current = currentExpressions.current[key] || 0\r\n const target = targetExpressions.current[key] || 0\r\n const next = THREE.MathUtils.lerp(current, target, lerpSpeed)\r\n currentExpressions.current[key] = next\r\n\r\n // Don't override blink during active blink animation\r\n if (key === VRMExpressionPresetName.Blink && blinkTimer.current >= nextBlinkAt.current) continue\r\n\r\n vrm.expressionManager?.setValue(key, next)\r\n }\r\n\r\n // ── SPEAKING MOUTH ──\r\n if (callState === 'speaking' && audioLevel > 0.01) {\r\n const mouthTarget = Math.min(audioLevel * 1.5, 0.8)\r\n const currentMouth = vrm.expressionManager?.getValue(VRMExpressionPresetName.Aa) || 0\r\n const smoothMouth = THREE.MathUtils.lerp(currentMouth, mouthTarget, 8 * dt)\r\n vrm.expressionManager?.setValue(VRMExpressionPresetName.Aa, smoothMouth)\r\n } else {\r\n const currentMouth = vrm.expressionManager?.getValue(VRMExpressionPresetName.Aa) || 0\r\n if (currentMouth > 0.01) {\r\n vrm.expressionManager?.setValue(VRMExpressionPresetName.Aa, currentMouth * 0.9)\r\n }\r\n }\r\n\r\n // ── HEAD MOVEMENT ──\r\n if (vrm.humanoid) {\r\n const head = vrm.humanoid.getNormalizedBoneNode('head')\r\n if (head) {\r\n const idleSwayX = Math.sin(breathPhase.current * 0.3) * 0.01\r\n const idleSwayZ = Math.cos(breathPhase.current * 0.2) * 0.005\r\n\r\n const targetX = headTarget.current.x + idleSwayX\r\n const targetY = headTarget.current.y\r\n const targetZ = headTarget.current.z + idleSwayZ\r\n\r\n head.rotation.x = THREE.MathUtils.lerp(head.rotation.x, targetX, 3 * dt)\r\n head.rotation.y = THREE.MathUtils.lerp(head.rotation.y, targetY, 3 * dt)\r\n head.rotation.z = THREE.MathUtils.lerp(head.rotation.z, targetZ, 3 * dt)\r\n }\r\n }\r\n\r\n // ── CALL STATE REACTIONS ──\r\n if (callState === 'listening' && vrm.humanoid) {\r\n const head = vrm.humanoid.getNormalizedBoneNode('head')\r\n if (head) {\r\n head.rotation.z = THREE.MathUtils.lerp(head.rotation.z, 0.03, 2 * dt)\r\n }\r\n }\r\n\r\n // Update VRM (required for expression changes to take effect)\r\n vrm.update(dt)\r\n })\r\n\r\n return null\r\n}\r\n\r\n// ═══════════════════════════════════════\r\n// AUTO CAMERA FRAMING\r\n// ═══════════════════════════════════════\r\n\r\nfunction CameraSetup() {\r\n const { camera } = useThree()\r\n useEffect(() => {\r\n // Default camera position — will be overridden by model loader for GLB\r\n // For VRM: fixed head-level framing\r\n camera.position.set(0, 0.1, 0.6)\r\n camera.lookAt(0, 0.1, 0)\r\n }, [camera])\r\n return null\r\n}\r\n\r\n// ═══════════════════════════════════════\r\n// MAIN AVATAR 3D COMPONENT (exported)\r\n// ═══════════════════════════════════════\r\n\r\nexport default function Avatar3D({\r\n modelUrl,\r\n emotion,\r\n callState,\r\n audioLevel,\r\n primaryColor,\r\n size,\r\n}: Avatar3DProps) {\r\n const glowIntensity = useMemo(() => {\r\n switch (callState) {\r\n case 'speaking': return 0.6\r\n case 'listening': return 0.4\r\n case 'thinking': return 0.3\r\n default: return 0.15\r\n }\r\n }, [callState])\r\n\r\n const isActive = callState === 'listening' || callState === 'speaking'\r\n\r\n return (\r\n <div className=\"relative flex flex-col items-center gap-4\">\r\n {/* Glow ring behind canvas */}\r\n <div\r\n className=\"relative rounded-full overflow-hidden\"\r\n style={{\r\n width: `${size}px`,\r\n height: `${size}px`,\r\n boxShadow: isActive\r\n ? `0 0 0 3px ${primaryColor}50, 0 0 30px ${primaryColor}${Math.floor(glowIntensity * 255).toString(16).padStart(2, '0')}, 0 0 60px ${primaryColor}20`\r\n : `0 0 0 2px ${primaryColor}25`,\r\n transition: 'box-shadow 0.5s ease',\r\n }}\r\n >\r\n <Canvas\r\n style={{ width: '100%', height: '100%', background: 'transparent' }}\r\n gl={{ alpha: true, antialias: true, preserveDrawingBuffer: false }}\r\n camera={{ fov: 30, near: 0.01, far: 10 }}\r\n dpr={[1, 2]}\r\n >\r\n <CameraSetup />\r\n\r\n {/* Lighting — soft studio setup */}\r\n {/* @ts-ignore R3F IntrinsicElements conflict */}\r\n <ambientLight intensity={0.6} />\r\n {/* @ts-ignore */}\r\n <directionalLight position={[1, 2, 3]} intensity={0.8} color=\"#ffffff\" />\r\n {/* @ts-ignore */}\r\n <directionalLight position={[-1, 1, -1]} intensity={0.3} color=\"#b4c6e7\" />\r\n\r\n {/* Rim light for depth — matches primary color */}\r\n {/* @ts-ignore */}\r\n <pointLight\r\n position={[0, 0.5, -0.5]}\r\n intensity={glowIntensity * 2}\r\n color={primaryColor}\r\n distance={3}\r\n />\r\n\r\n <VRMModel\r\n url={modelUrl}\r\n emotion={emotion}\r\n callState={callState}\r\n audioLevel={audioLevel}\r\n />\r\n </Canvas>\r\n </div>\r\n </div>\r\n )\r\n}\r\n"],"names":["EMOTION_MAP","default","expressions","VRMExpressionPresetName","Neutral","happy","Happy","angry","Angry","headRotation","sorry","Sad","confused","love","Relaxed","thinking","writing","wink","Blink","VRMModel","url","emotion","callState","audioLevel","vrmRef","useRef","glbSceneRef","mixerRef","baseRotationY","baseScale","blinkTimer","nextBlinkAt","breathPhase","currentExpressions","targetExpressions","headTarget","THREE","Euler","baseY","scene","camera","useThree","useEffect","loader","GLTFLoader","register","parser","VRMLoaderPlugin","load","gltf","vrm","userData","current","rotation","y","Math","PI","box","Box3","setFromObject","center","getCenter","Vector3","height","getSize","position","add","console","info","model","updateMatrixWorld","size","pivot","Group","sub","fov","headY","cameraZ","tan","set","lookAt","animations","length","mixer","AnimationMixer","forEach","clip","clipAction","play","error","remove","stopAllAction","config","useFrame","_","delta","dt","min","glb","update","breathOffset","sin","idleSway","pulse","targetScale","currentScale","scale","x","setScalar","MathUtils","lerp","abs","blinkProgress","expressionManager","setValue","random","lerpSpeed","allKeys","Set","Object","keys","key","target","next","mouthTarget","currentMouth","getValue","Aa","smoothMouth","humanoid","head","getNormalizedBoneNode","idleSwayX","idleSwayZ","cos","targetX","targetY","targetZ","z","CameraSetup","Avatar3D","modelUrl","primaryColor","glowIntensity","useMemo","jsx","className","children","style","width","boxShadow","floor","toString","padStart","transition","jsxs","Canvas","background","gl","alpha","antialias","preserveDrawingBuffer","near","far","dpr","intensity","color","distance"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{jsx as e,jsxs as r,Fragment as a}from"react/jsx-runtime";import{memo as o,useState as t,useEffect as l,useRef as n}from"react";import{c as s,u as i,a as c,X as d}from"./standalone-
|
|
1
|
+
import{jsx as e,jsxs as r,Fragment as a}from"react/jsx-runtime";import{memo as o,useState as t,useEffect as l,useRef as n}from"react";import{c as s,u as i,a as c,X as d}from"./standalone-D-wUb5qW.js";const h=s("ChevronLeft",[["path",{d:"m15 18-6-6 6-6",key:"1wnfg3"}]]),u=s("ChevronRight",[["path",{d:"m9 18 6-6-6-6",key:"mthhwq"}]]),m=s("ZoomIn",[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["line",{x1:"21",x2:"16.65",y1:"21",y2:"16.65",key:"13gj7c"}],["line",{x1:"11",x2:"11",y1:"8",y2:"14",key:"1vmskp"}],["line",{x1:"8",x2:"14",y1:"11",y2:"11",key:"durymu"}]]),b=o(function({images:o,radius:l="rounded-lg"}){const{t:n}=i("extracted"),[s,d]=t(0),[b,p]=t(!1),v=()=>{d(e=>(e+1)%o.length)},f=()=>{d(e=>(e-1+o.length)%o.length)},y=e=>{d(e),p(!0)},[x,k]=t(/* @__PURE__ */new Set),w=e=>{k(r=>new Set(r).add(e))};return 1===o.length?/* @__PURE__ */e("div",{className:"my-3 relative group",children:x.has(0)?/* @__PURE__ */r("div",{className:c("w-full h-48 flex flex-col items-center justify-center","border bg-muted text-muted-foreground",l),style:{borderColor:"hsl(var(--border))"},children:[
|
|
2
2
|
/* @__PURE__ */e("svg",{className:"w-12 h-12 mb-2 opacity-50",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:/* @__PURE__ */e("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"})}),
|
|
3
3
|
/* @__PURE__ */e("span",{className:"text-sm",children:"Imagen no disponible"})]}):/* @__PURE__ */r(a,{children:[
|
|
4
4
|
/* @__PURE__ */e("img",{src:o[0].src,alt:o[0].alt||"Imagen",className:c("w-full h-auto object-cover cursor-pointer transition-all duration-300","border shadow-soft-md hover:shadow-soft-lg hover:scale-[1.02]",l),style:{borderColor:"hsl(var(--border))"},loading:"lazy",onClick:()=>y(0),onError:()=>w(0)}),
|
|
@@ -21,4 +21,4 @@ return r("div",{className:"absolute inset-0 z-[100000] bg-black/95 backdrop-blur
|
|
|
21
21
|
/* @__PURE__ */e("button",{onClick:e=>{e.stopPropagation(),b()},className:"absolute left-4 bg-white/10 hover:bg-white/20 p-3 rounded-full transition-all hover:scale-110 active:scale-95 z-10","aria-label":"Anterior",children:/* @__PURE__ */e(h,{size:32,className:"text-white"})}),
|
|
22
22
|
/* @__PURE__ */e("button",{onClick:e=>{e.stopPropagation(),m()},className:"absolute right-4 bg-white/10 hover:bg-white/20 p-3 rounded-full transition-all hover:scale-110 active:scale-95 z-10","aria-label":"Siguiente",children:/* @__PURE__ */e(u,{size:32,className:"text-white"})})]}),
|
|
23
23
|
/* @__PURE__ */e("img",{src:o[t].src,alt:o[t].alt||`Imagen ${t+1}`,className:"max-w-[90%] max-h-[85%] object-contain",onClick:e=>e.stopPropagation()}),o.length>1&&/* @__PURE__ */e("div",{className:"absolute bottom-4 left-1/2 -translate-x-1/2 flex gap-2 bg-black/50 backdrop-blur-sm px-3 py-2 rounded-full z-10",children:o.map((r,a)=>/* @__PURE__ */e("button",{onClick:e=>{e.stopPropagation();const r=a-t;if(r>0)for(let a=0;a<r;a++)m();if(r<0)for(let a=0;a<Math.abs(r);a++)b()},className:c("w-2 h-2 rounded-full transition-all",a===t?"bg-white scale-125":"bg-white/40 hover:bg-white/60"),"aria-label":`Imagen ${a+1}`},a))})]})}export{b as Gallery};
|
|
24
|
-
//# sourceMappingURL=Gallery-
|
|
24
|
+
//# sourceMappingURL=Gallery-CSN57fUw.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Gallery-CSN57fUw.js","sources":["../node_modules/lucide-react/dist/esm/icons/chevron-left.js","../node_modules/lucide-react/dist/esm/icons/chevron-right.js","../node_modules/lucide-react/dist/esm/icons/zoom-in.js","../src/chat-widget/components/Gallery.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.400.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ChevronLeft = createLucideIcon(\"ChevronLeft\", [\n [\"path\", { d: \"m15 18-6-6 6-6\", key: \"1wnfg3\" }]\n]);\n\nexport { ChevronLeft as default };\n//# sourceMappingURL=chevron-left.js.map\n","/**\n * @license lucide-react v0.400.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ChevronRight = createLucideIcon(\"ChevronRight\", [\n [\"path\", { d: \"m9 18 6-6-6-6\", key: \"mthhwq\" }]\n]);\n\nexport { ChevronRight as default };\n//# sourceMappingURL=chevron-right.js.map\n","/**\n * @license lucide-react v0.400.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ZoomIn = createLucideIcon(\"ZoomIn\", [\n [\"circle\", { cx: \"11\", cy: \"11\", r: \"8\", key: \"4ej97u\" }],\n [\"line\", { x1: \"21\", x2: \"16.65\", y1: \"21\", y2: \"16.65\", key: \"13gj7c\" }],\n [\"line\", { x1: \"11\", x2: \"11\", y1: \"8\", y2: \"14\", key: \"1vmskp\" }],\n [\"line\", { x1: \"8\", x2: \"14\", y1: \"11\", y2: \"11\", key: \"durymu\" }]\n]);\n\nexport { ZoomIn as default };\n//# sourceMappingURL=zoom-in.js.map\n","/**\r\n * @package @botuyo/chat-widget\r\n * Gallery - Componente visual para mostrar galerías de imágenes\r\n */\r\n\r\n'use client'\r\n\r\nimport { useState, memo, useRef, useEffect } from 'react'\r\nimport { useTranslations } from '@/chat-widget/i18n'\r\nimport { ChevronLeft, ChevronRight, X, ZoomIn } from './Icons'\r\nimport { cn } from '@/lib/utils'\r\n\r\ninterface GalleryProps {\r\n images: Array<{ src: string; alt?: string }>\r\n radius?: string\r\n}\r\n\r\nexport type { GalleryProps }\r\n\r\nexport const Gallery = memo(function Gallery({ images, radius = 'rounded-lg' }: GalleryProps) {\r\n const { t } = useTranslations('extracted')\r\n const [currentIndex, setCurrentIndex] = useState(0)\r\n const [isLightboxOpen, setIsLightboxOpen] = useState(false)\r\n\r\n const nextImage = () => {\r\n setCurrentIndex(prev => (prev + 1) % images.length)\r\n }\r\n\r\n const prevImage = () => {\r\n setCurrentIndex(prev => (prev - 1 + images.length) % images.length)\r\n }\r\n\r\n const openLightbox = (index: number) => {\r\n setCurrentIndex(index)\r\n setIsLightboxOpen(true)\r\n }\r\n\r\n const [imageError, setImageError] = useState<Set<number>>(new Set())\r\n\r\n const handleImageError = (index: number) => {\r\n setImageError(prev => new Set(prev).add(index))\r\n }\r\n\r\n // Si solo hay 1 imagen, mostrar como imagen simple\r\n if (images.length === 1) {\r\n return (\r\n <div className=\"my-3 relative group\">\r\n {imageError.has(0) ? (\r\n <div\r\n className={cn(\r\n 'w-full h-48 flex flex-col items-center justify-center',\r\n 'border bg-muted text-muted-foreground',\r\n radius\r\n )}\r\n style={{ borderColor: 'hsl(var(--border))' }}\r\n >\r\n <svg\r\n className=\"w-12 h-12 mb-2 opacity-50\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\"\r\n />\r\n </svg>\r\n <span className=\"text-sm\">Imagen no disponible</span>\r\n </div>\r\n ) : (\r\n <>\r\n <img\r\n src={images[0].src}\r\n alt={images[0].alt || 'Imagen'}\r\n className={cn(\r\n 'w-full h-auto object-cover cursor-pointer transition-all duration-300',\r\n 'border shadow-soft-md hover:shadow-soft-lg hover:scale-[1.02]',\r\n radius\r\n )}\r\n style={{ borderColor: 'hsl(var(--border))' }}\r\n loading=\"lazy\"\r\n onClick={() => openLightbox(0)}\r\n onError={() => handleImageError(0)}\r\n />\r\n <div className=\"absolute top-2 right-2 bg-black/50 backdrop-blur-sm p-1.5 rounded-full opacity-0 group-hover:opacity-100 transition-opacity\">\r\n <ZoomIn size={16} className=\"text-white\" />\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n )\r\n }\r\n\r\n // Si hay 2-3 imágenes, mostrar grid horizontal\r\n if (images.length <= 3) {\r\n return (\r\n <div className={cn('my-3 grid gap-2', images.length === 2 ? 'grid-cols-2' : 'grid-cols-3')}>\r\n {images.map((img, idx) => (\r\n <div key={idx} className=\"relative group overflow-hidden\">\r\n {imageError.has(idx) ? (\r\n <div\r\n className={cn(\r\n 'w-full h-32 flex flex-col items-center justify-center',\r\n 'border bg-muted text-muted-foreground',\r\n radius\r\n )}\r\n >\r\n <svg\r\n className=\"w-8 h-8 opacity-50\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\"\r\n />\r\n </svg>\r\n </div>\r\n ) : (\r\n <>\r\n <img\r\n src={img.src}\r\n alt={img.alt || `Imagen ${idx + 1}`}\r\n className={cn(\r\n 'w-full h-32 object-cover cursor-pointer transition-all duration-300',\r\n 'border border-border shadow-soft-md hover:shadow-soft-lg hover:scale-110',\r\n radius\r\n )}\r\n loading=\"lazy\"\r\n onClick={() => openLightbox(idx)}\r\n onError={() => handleImageError(idx)}\r\n />\r\n <div className=\"absolute inset-0 bg-gradient-to-t from-black/40 to-transparent opacity-0 group-hover:opacity-100 transition-opacity flex items-end justify-end p-2\">\r\n <span className=\"text-white text-xs font-bold bg-black/50 backdrop-blur-sm px-2 py-1 rounded-full\">\r\n {idx + 1}/{images.length}\r\n </span>\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n ))}\r\n\r\n {/* Lightbox */}\r\n {isLightboxOpen && (\r\n <Lightbox\r\n images={images}\r\n currentIndex={currentIndex}\r\n onClose={() => setIsLightboxOpen(false)}\r\n onNext={nextImage}\r\n onPrev={prevImage}\r\n />\r\n )}\r\n </div>\r\n )\r\n }\r\n\r\n // Si hay 4+ imágenes, mostrar carrusel con thumbnails\r\n return (\r\n <div className=\"my-3 space-y-2\">\r\n {/* Imagen Principal */}\r\n <div className=\"relative group\">\r\n {imageError.has(currentIndex) ? (\r\n <div\r\n className={cn(\r\n 'w-full h-56 flex flex-col items-center justify-center',\r\n 'border bg-muted text-muted-foreground',\r\n radius\r\n )}\r\n style={{ borderColor: 'hsl(var(--border))' }}\r\n >\r\n <svg\r\n className=\"w-12 h-12 mb-2 opacity-50\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\"\r\n />\r\n </svg>\r\n <span className=\"text-sm\">Imagen no disponible</span>\r\n </div>\r\n ) : (\r\n <>\r\n <img\r\n src={images[currentIndex].src}\r\n alt={images[currentIndex].alt || `Imagen ${currentIndex + 1}`}\r\n className={cn(\r\n 'w-full h-56 object-cover cursor-pointer transition-all duration-300',\r\n 'border shadow-soft-md',\r\n radius\r\n )}\r\n style={{ borderColor: 'hsl(var(--border))' }}\r\n loading=\"lazy\"\r\n onClick={() => openLightbox(currentIndex)}\r\n onError={() => handleImageError(currentIndex)}\r\n />\r\n\r\n {/* Overlay con controles */}\r\n <div className=\"absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-black/20 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-between px-3\">\r\n <button\r\n onClick={prevImage}\r\n className=\"p-2 rounded-full shadow-soft-lg transition-all hover:scale-110 active:scale-95\"\r\n style={{\r\n backgroundColor: 'hsl(var(--card) / 0.9)',\r\n color: 'hsl(var(--foreground))',\r\n }}\r\n aria-label={t('anterior')}\r\n >\r\n <ChevronLeft size={20} />\r\n </button>\r\n <button\r\n onClick={nextImage}\r\n className=\"p-2 rounded-full shadow-soft-lg transition-all hover:scale-110 active:scale-95\"\r\n style={{\r\n backgroundColor: 'hsl(var(--card) / 0.9)',\r\n color: 'hsl(var(--foreground))',\r\n }}\r\n aria-label={t('siguiente')}\r\n >\r\n <ChevronRight size={20} />\r\n </button>\r\n </div>\r\n\r\n {/* Badge con contador */}\r\n <div className=\"absolute top-3 right-3 bg-black/70 backdrop-blur-sm px-3 py-1 rounded-full\">\r\n <span className=\"text-white text-xs font-bold\">\r\n {currentIndex + 1} / {images.length}\r\n </span>\r\n </div>\r\n\r\n {/* Icono de zoom */}\r\n <div className=\"absolute bottom-3 right-3 bg-black/70 backdrop-blur-sm p-2 rounded-full opacity-0 group-hover:opacity-100 transition-opacity\">\r\n <ZoomIn size={16} className=\"text-white\" />\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n\r\n {/* Thumbnails */}\r\n <div className=\"flex gap-2 overflow-x-auto pb-2 scrollbar-thin scrollbar-thumb-border scrollbar-track-transparent\">\r\n {images.map((img, idx) => (\r\n <button\r\n key={idx}\r\n onClick={() => setCurrentIndex(idx)}\r\n className={cn(\r\n 'flex-shrink-0 w-16 h-16 overflow-hidden transition-all duration-300 relative',\r\n 'border-2 hover:scale-110',\r\n radius,\r\n currentIndex === idx\r\n ? 'border-[hsl(210,90%,50%)] ring-2 ring-[hsl(210,90%,50%)]/30 scale-105'\r\n : 'border-border hover:border-[hsl(210,90%,70%)] opacity-70 hover:opacity-100'\r\n )}\r\n >\r\n {imageError.has(idx) ? (\r\n <div className=\"w-full h-full flex items-center justify-center bg-muted\">\r\n <svg\r\n className=\"w-6 h-6 opacity-50\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\"\r\n />\r\n </svg>\r\n </div>\r\n ) : (\r\n <img\r\n src={img.src}\r\n alt={img.alt || `Thumbnail ${idx + 1}`}\r\n className=\"w-full h-full object-cover\"\r\n loading=\"lazy\"\r\n onError={() => handleImageError(idx)}\r\n />\r\n )}\r\n </button>\r\n ))}\r\n </div>\r\n\r\n {/* Lightbox */}\r\n {isLightboxOpen && (\r\n <Lightbox\r\n images={images}\r\n currentIndex={currentIndex}\r\n onClose={() => setIsLightboxOpen(false)}\r\n onNext={nextImage}\r\n onPrev={prevImage}\r\n />\r\n )}\r\n </div>\r\n )\r\n})\r\n\r\n// ==========================================\r\n// 🔍 LIGHTBOX (Modal de Imagen)\r\n// ==========================================\r\n\r\ninterface LightboxProps {\r\n images: Array<{ src: string; alt?: string }>\r\n currentIndex: number\r\n onClose: () => void\r\n onNext: () => void\r\n onPrev: () => void\r\n}\r\n\r\nfunction Lightbox({ images, currentIndex, onClose, onNext, onPrev }: LightboxProps) {\r\n const { t } = useTranslations('extracted')\r\n\r\n // Keyboard navigation\r\n useEffect(() => {\r\n const handler = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') onClose()\r\n if (e.key === 'ArrowLeft') onPrev()\r\n if (e.key === 'ArrowRight') onNext()\r\n }\r\n window.addEventListener('keydown', handler)\r\n return () => window.removeEventListener('keydown', handler)\r\n }, [onClose, onPrev, onNext])\r\n\r\n // Touch swipe support\r\n const touchStartX = useRef(0)\r\n const handleTouchStart = (e: React.TouchEvent) => {\r\n touchStartX.current = e.touches[0].clientX\r\n }\r\n const handleTouchEnd = (e: React.TouchEvent) => {\r\n const dx = e.changedTouches[0].clientX - touchStartX.current\r\n if (Math.abs(dx) > 50) {\r\n if (dx > 0) { onPrev() } else { onNext() }\r\n }\r\n }\r\n\r\n return (\r\n <div\r\n className=\"absolute inset-0 z-[100000] bg-black/95 backdrop-blur-sm flex items-center justify-center animate-in fade-in duration-200\"\r\n onClick={onClose}\r\n onTouchStart={handleTouchStart}\r\n onTouchEnd={handleTouchEnd}\r\n >\r\n {/* Botón Cerrar */}\r\n <button\r\n onClick={onClose}\r\n className=\"absolute top-4 right-4 bg-white/10 hover:bg-white/20 p-2 rounded-full transition-all hover:scale-110 active:scale-95 z-10\"\r\n aria-label={t('cerrar')}\r\n >\r\n <X size={24} className=\"text-white\" />\r\n </button>\r\n\r\n {/* Contador */}\r\n <div className=\"absolute top-4 left-4 bg-white/10 backdrop-blur-sm px-4 py-2 rounded-full z-10\">\r\n <span className=\"text-white text-sm font-bold\">\r\n {currentIndex + 1} / {images.length}\r\n </span>\r\n </div>\r\n\r\n {/* Controles de Navegación */}\r\n {images.length > 1 && (\r\n <>\r\n <button\r\n onClick={e => {\r\n e.stopPropagation()\r\n onPrev()\r\n }}\r\n className=\"absolute left-4 bg-white/10 hover:bg-white/20 p-3 rounded-full transition-all hover:scale-110 active:scale-95 z-10\"\r\n aria-label=\"Anterior\"\r\n >\r\n <ChevronLeft size={32} className=\"text-white\" />\r\n </button>\r\n <button\r\n onClick={e => {\r\n e.stopPropagation()\r\n onNext()\r\n }}\r\n className=\"absolute right-4 bg-white/10 hover:bg-white/20 p-3 rounded-full transition-all hover:scale-110 active:scale-95 z-10\"\r\n aria-label=\"Siguiente\"\r\n >\r\n <ChevronRight size={32} className=\"text-white\" />\r\n </button>\r\n </>\r\n )}\r\n\r\n {/* Imagen */}\r\n <img\r\n src={images[currentIndex].src}\r\n alt={images[currentIndex].alt || `Imagen ${currentIndex + 1}`}\r\n className=\"max-w-[90%] max-h-[85%] object-contain\"\r\n onClick={e => e.stopPropagation()}\r\n />\r\n\r\n {/* Thumbnails strip */}\r\n {images.length > 1 && (\r\n <div className=\"absolute bottom-4 left-1/2 -translate-x-1/2 flex gap-2 bg-black/50 backdrop-blur-sm px-3 py-2 rounded-full z-10\">\r\n {images.map((_, idx) => (\r\n <button\r\n key={idx}\r\n onClick={e => {\r\n e.stopPropagation()\r\n // Navigate to this index — use repeated prev/next to reach\r\n const diff = idx - currentIndex\r\n if (diff > 0) for (let i = 0; i < diff; i++) onNext()\r\n if (diff < 0) for (let i = 0; i < Math.abs(diff); i++) onPrev()\r\n }}\r\n className={cn(\r\n 'w-2 h-2 rounded-full transition-all',\r\n idx === currentIndex ? 'bg-white scale-125' : 'bg-white/40 hover:bg-white/60'\r\n )}\r\n aria-label={`Imagen ${idx + 1}`}\r\n />\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n"],"names":["ChevronLeft","createLucideIcon","d","key","ChevronRight","ZoomIn","cx","cy","r","x1","x2","y1","y2","Gallery","memo","images","radius","t","useTranslations","currentIndex","setCurrentIndex","useState","isLightboxOpen","setIsLightboxOpen","nextImage","prev","length","prevImage","openLightbox","index","imageError","setImageError","Set","handleImageError","add","className","children","has","jsxs","cn","style","borderColor","jsx","fill","stroke","viewBox","strokeLinecap","strokeLinejoin","strokeWidth","Fragment","src","alt","loading","onClick","onError","size","map","img","idx","Lightbox","onClose","onNext","onPrev","backgroundColor","color","useEffect","handler","e","window","addEventListener","removeEventListener","touchStartX","useRef","onTouchStart","current","touches","clientX","onTouchEnd","dx","changedTouches","Math","abs","X","stopPropagation","_","diff","i"],"mappings":"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","x_google_ignoreList":[0,1,2]}
|
package/dist/botuyo-chat.es.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"react-dom/client";import"react";import{B as a,C as t,d as e,b as s,f as d,i,e as o,h as r}from"./standalone-
|
|
1
|
+
import"react-dom/client";import"react";import{B as a,C as t,d as e,b as s,f as d,i,e as o,h as r}from"./standalone-D-wUb5qW.js";export{a as BotUyoChatWidget,t as ChatWidget,e as ChatWidgetProvider,s as ChatWidgetUnstyled,d as LanguageProvider,i as default,o as useChatWidget,r as useLanguage};
|
|
2
2
|
//# sourceMappingURL=botuyo-chat.es.js.map
|