chordia-ui 3.4.2 → 3.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Timeline.cjs.js +6 -1
- package/dist/Timeline.cjs.js.map +1 -1
- package/dist/Timeline.es.js +597 -129
- package/dist/Timeline.es.js.map +1 -1
- package/dist/UpdatedInteractionRecording.cjs.js +1 -1
- package/dist/UpdatedInteractionRecording.cjs.js.map +1 -1
- package/dist/UpdatedInteractionRecording.es.js +233 -241
- package/dist/UpdatedInteractionRecording.es.js.map +1 -1
- package/dist/components/UpdatedInteractionDetails.cjs.js +2 -2
- package/dist/components/UpdatedInteractionDetails.cjs.js.map +1 -1
- package/dist/components/UpdatedInteractionDetails.es.js +451 -360
- package/dist/components/UpdatedInteractionDetails.es.js.map +1 -1
- package/dist/components/media.cjs.js +1 -1
- package/dist/components/media.cjs.js.map +1 -1
- package/dist/components/media.es.js +8 -9
- package/dist/components/media.es.js.map +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs2.js +1 -1
- package/dist/index.cjs2.js.map +1 -1
- package/dist/index.es.js +52 -53
- package/dist/index.es.js.map +1 -1
- package/dist/index.es2.js +596 -587
- package/dist/index.es2.js.map +1 -1
- package/dist/pages/interactionDetails.cjs.js +2 -2
- package/dist/pages/interactionDetails.cjs.js.map +1 -1
- package/dist/pages/interactionDetails.es.js +16 -17
- package/dist/pages/interactionDetails.es.js.map +1 -1
- package/package.json +1 -1
- package/src/components/UpdatedInteractionDetails/UpdatedCompassScore.jsx +54 -2
- package/src/components/UpdatedInteractionDetails/UpdatedInteractionDetails.jsx +58 -14
- package/src/components/UpdatedInteractionDetails/UpdatedInteractionRecording.jsx +132 -126
- package/src/components/UpdatedInteractionDetails/UpdatedInteractionSignals.jsx +14 -6
- package/src/components/login/LoginPage.jsx +18 -3
- package/dist/TranscriptCard.cjs.js +0 -7
- package/dist/TranscriptCard.cjs.js.map +0 -1
- package/dist/TranscriptCard.es.js +0 -474
- package/dist/TranscriptCard.es.js.map +0 -1
package/dist/Timeline.cjs.js
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
"use strict";const e=require("react/jsx-runtime"),
|
|
1
|
+
"use strict";const e=require("react/jsx-runtime"),x=require("react"),I=require("lucide-react"),A={customer:{label:"Customer",railColor:"var(--rail-discovery)",cardBg:"var(--card-customer)",cardBgHighlight:"rgba(94, 136, 176, 0.12)",borderColor:"var(--border-subtle)"},agent:{label:"Agent",railColor:"var(--rail-outcome)",cardBg:"var(--card-agent)",cardBgHighlight:"rgba(107, 124, 147, 0.10)",borderColor:"var(--border-subtle)"},assistant:{label:"AI Assistant",railColor:"var(--rail-purple)",cardBg:"var(--card-assistant)",cardBgHighlight:"rgba(155, 122, 168, 0.10)",borderColor:"var(--border-subtle)"},system:{label:"System",railColor:"var(--text-faint)",cardBg:"transparent",cardBgHighlight:"transparent",borderColor:"transparent"}},M="conversation-turn-keyframes";function F(){if(typeof document>"u"||document.getElementById(M))return;const s=document.createElement("style");s.id=M,s.textContent=`
|
|
2
|
+
@keyframes turn-playing-pulse {
|
|
3
|
+
0%, 100% { opacity: 0.4; }
|
|
4
|
+
50% { opacity: 0.9; }
|
|
5
|
+
}
|
|
6
|
+
`,document.head.appendChild(s)}function P({role:s="agent",text:m,actorLabel:g,actorRailColor:w,actionKicker:b,toolBadges:v,streaming:u=!1,meta:k,timeRange:E,isHighlighted:R=!1,highlightRailColor:n,observations:i,onObservationClick:y,children:S}){x.useEffect(()=>{F()},[]);const j=A[s]||A.agent,T=g||j.label,C=w||j.railColor,o=R||u;return s==="system"?e.jsx("div",{style:{textAlign:"center",padding:"6px 0",flexShrink:0,fontSize:"var(--text-sm, 11px)",color:"var(--text-faint, rgba(30,33,37,0.36))",fontWeight:500,letterSpacing:"0.02em"},children:m}):e.jsxs("div",{style:{position:"relative",padding:"10px 14px 10px 18px",borderRadius:10,overflow:"hidden",flexShrink:0,background:o?j.cardBgHighlight:j.cardBg,border:`1px solid ${u?C:j.borderColor}`,boxShadow:u?`0 0 8px ${j.cardBgHighlight}`:"none",transition:"background 0.2s, border-color 0.2s, box-shadow 0.2s"},children:[e.jsx("div",{style:{position:"absolute",left:0,top:0,bottom:0,width:"var(--rail-width-thin, 4px)",backgroundColor:C,borderRadius:"10px 0 0 10px"}}),e.jsxs("div",{style:{display:"flex",alignItems:"flex-start",justifyContent:"space-between",gap:8,marginBottom:4},children:[e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:2},children:[b?e.jsx("div",{style:{fontSize:"var(--text-xs-plus, 10.5px)",fontWeight:650,textTransform:"uppercase",letterSpacing:"var(--tracking-label, 0.16em)",color:C},children:b}):null,e.jsx("div",{style:{fontSize:"var(--text-xs-plus, 10.5px)",fontWeight:650,textTransform:"uppercase",letterSpacing:"var(--tracking-label, 0.16em)",color:"var(--text-faint, rgba(30,33,37,0.36))"},children:T})]}),v&&v.length>0?e.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:4,flexShrink:0,justifyContent:"flex-end"},children:v.map((t,l)=>{const c=t.pending,d=!c&&t.success===!1,h=c?"var(--rail-discovery, #5E88B0)":d?"var(--rail-compliance, #C98A5A)":"var(--text-xfaint, rgba(30,33,37,0.28))";return e.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:5,fontSize:"var(--text-xs, 10px)",padding:"2px 8px 2px 6px",borderRadius:999,background:"var(--paper, rgba(255,255,255,0.78))",border:"1px solid var(--border-subtle, rgba(52,58,64,0.08))",color:"var(--text-faint, rgba(30,33,37,0.36))",fontWeight:500,fontFamily:"var(--font-fira-code, var(--font-mono, monospace))",letterSpacing:"0.01em",lineHeight:1.4,whiteSpace:"nowrap"},children:[e.jsx("span",{style:{width:5,height:5,borderRadius:"50%",backgroundColor:h,flexShrink:0}}),t.name]},l)})}):null]}),e.jsxs("div",{style:{fontSize:"var(--text-md, 13px)",lineHeight:"var(--leading-normal, 1.5)",color:u?"var(--text-strong, rgba(30,33,37,0.92))":"var(--text-base, rgba(30,33,37,0.78))",fontWeight:u?550:400},children:[m,u?e.jsx("span",{style:{display:"inline-block",width:6,height:14,background:C,marginLeft:2,borderRadius:1,animation:"cursorBlink 0.8s ease-in-out infinite",verticalAlign:"text-bottom"}}):null]}),E||S||i&&i.length>0?e.jsxs("div",{style:{marginTop:6,display:"flex",alignItems:"center",gap:6},children:[S,E?e.jsx("span",{style:{fontSize:"var(--text-sm, 11px)",padding:"2px 8px",borderRadius:999,border:"1px solid var(--border, rgba(52,58,64,0.12))",background:"var(--timestamp-bg, rgba(255,255,255,0.70))",color:"var(--text-muted, rgba(30,33,37,0.56))",fontFamily:"var(--font-mono, monospace)"},children:E}):null,i&&i.length>0?e.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:4,marginLeft:"auto"},children:i.map((t,l)=>e.jsxs("span",{onClick:t.onClick||(y?()=>y(t):void 0),style:{display:"inline-flex",alignItems:"center",gap:4,fontSize:"var(--text-xs, 10px)",padding:"2px 8px",borderRadius:999,background:`color-mix(in srgb, ${t.color||"var(--state-present)"} 12%, transparent)`,border:`1px solid color-mix(in srgb, ${t.color||"var(--state-present)"} 25%, transparent)`,color:t.color||"var(--state-present)",fontWeight:550,lineHeight:1.4,whiteSpace:"nowrap",cursor:t.onClick||y?"pointer":"default",transition:"background 0.15s"},title:t.reason||t.label,children:[e.jsx("span",{style:{width:4,height:4,borderRadius:"50%",backgroundColor:t.color||"var(--state-present)",flexShrink:0,opacity:.7}}),t.label]},l))}):null]}):null,k?e.jsx("div",{style:{marginTop:6,fontSize:"var(--text-xs-plus, 10.5px)",color:"var(--text-faint, rgba(30,33,37,0.36))",fontFamily:"var(--font-mono, monospace)"},children:k}):null,o&&n?e.jsx("div",{style:{position:"absolute",right:8,top:8,bottom:8,width:6,borderRadius:4,backgroundColor:n,opacity:.7,animation:"turn-playing-pulse 1.5s ease-in-out infinite"}}):null]})}const D=s=>{const[m,g]=s.split("–").map(w=>{const[b,v]=w.split(":").map(Number);return b*60+v});return{start:m,end:g}},N=s=>({customer:"customer",agent:"agent",third_party:"agent",system:"system",assistant:"assistant"})[s]||"agent";function X({turns:s,audioUrl:m,activeTurnIndex:g=-1,autoScrollActiveTurn:w=!1,isExternalPlaying:b=!1,onTurnPlayPause:v}){const[u,k]=x.useState(null),[E,R]=x.useState(!1),n=x.useRef(null),i=x.useRef(null),y=x.useRef([]),S=x.useRef(null),j=x.useRef(-1),T=typeof v=="function",C=b!==void 0;x.useEffect(()=>{if(m)return n.current=new Audio(m),n.current.preload="auto",()=>{n.current&&(n.current.pause(),n.current=null)}},[m]),x.useEffect(()=>()=>{n.current&&(n.current.pause(),i.current&&n.current.removeEventListener("timeupdate",i.current))},[]),x.useEffect(()=>{if(!w||g<0)return;const t=S.current,l=y.current[g];if(!l||!t)return;const c=t.getBoundingClientRect(),d=l.getBoundingClientRect(),h=12,f=d.top>=c.top+h&&d.bottom<=c.bottom-8;if(!(j.current===g)||!f){const W=d.top-c.top+t.scrollTop;t.scrollTop=Math.max(W-h,0)}j.current=g},[g,w]);const o=(t,l)=>{if(T){v(s[l],l);return}if(u===l&&E)n.current&&(n.current.pause(),i.current&&(n.current.removeEventListener("timeupdate",i.current),i.current=null)),R(!1);else{const c=u;if(k(l),m&&n.current){const{start:d,end:h}=D(t);c!==null&&c!==l&&(n.current.pause(),i.current&&(n.current.removeEventListener("timeupdate",i.current),i.current=null));const f=()=>{if(n.current){if(n.current.currentTime=d,h){const B=()=>{n.current&&n.current.currentTime>=h&&(n.current.pause(),R(!1),k(null),i.current&&(n.current.removeEventListener("timeupdate",i.current),i.current=null))};i.current=B,n.current.addEventListener("timeupdate",B)}n.current.play().then(()=>R(!0)).catch(B=>{B&&B.name==="AbortError"||(R(!1),k(null))})}};n.current.readyState>=2?f():(n.current.addEventListener("loadedmetadata",f,{once:!0}),n.current.load())}else R(!0)}};return e.jsxs("div",{ref:S,className:"custom-thin-scrollbar-library",style:{maxHeight:560,overflowY:"auto",scrollBehavior:"smooth",border:"1px solid var(--border, rgba(52,58,64,0.12))",borderRadius:"12px 0px 0px 12px",background:"var(--paper-elevated, rgba(255,255,255,0.82))",padding:16},children:[e.jsx("div",{style:{fontSize:"var(--text-xs-plus, 10.5px)",fontWeight:650,textTransform:"uppercase",letterSpacing:"var(--tracking-label, 0.16em)",color:"var(--text-faint, rgba(30,33,37,0.36))",marginBottom:12},children:"Transcript"}),e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:8},children:s.map((t,l)=>{const c=T||C?!!b&&g===l:u===l&&E,d=!!t.isHighlighted||c,h=N(t.actorType);return e.jsx("div",{ref:f=>{y.current[l]=f},children:e.jsx(P,{role:h,text:t.text,actorLabel:t.actor,actorRailColor:t.actorColor,timeRange:t.timeRange,isHighlighted:d,highlightRailColor:c?t.highlightColor||(h==="agent"?"var(--rail-outcome)":"var(--rail-discovery)"):t.highlightColor,toolBadges:t.toolBadges,observations:t.observations,onObservationClick:t.onObservationClick,children:t.timeRange?e.jsx("button",{onClick:()=>o(t.timeRange,l),style:{width:24,height:24,borderRadius:"50%",border:"1px solid var(--border, rgba(52,58,64,0.12))",background:c?"var(--rail-discovery, #5E88B0)":"var(--paper, rgba(255,255,255,0.78))",display:"inline-flex",alignItems:"center",justifyContent:"center",cursor:"pointer",padding:0,transition:"all 0.15s"},"aria-label":c?`Pause segment ${t.timeRange}`:`Play segment ${t.timeRange}`,children:c?e.jsx(I.Pause,{style:{width:12,height:12,color:"var(--paper, #fff)",fill:"var(--paper, #fff)"},strokeWidth:0}):e.jsx(I.Play,{style:{width:12,height:12,color:"var(--text-muted, rgba(30,33,37,0.56))",fill:"var(--text-muted, rgba(30,33,37,0.56))",marginLeft:1},strokeWidth:0})}):null})},l)})})]})}function q({segments:s=[],durationSeconds:m=0,actorRows:g=[],currentTimeSeconds:w=0,onSeek:b,showControls:v=!1,hasRecording:u=!1,timelinePlaying:k=!1,playbackRate:E=1,speedOptions:R=[1,1.25,1.5,2],onTogglePlay:n,onSeekBack:i,onSeekForward:y,onSetPlaybackRate:S,totalDurationLabel:j}){const[T,C]=x.useState(null);x.useEffect(()=>{if(!T)return;const r=setTimeout(()=>C(null),220);return()=>clearTimeout(r)},[T]);const o=Math.max(Number(m)||0,...s.map(r=>Number(r.endTime)||0),1),t=Math.max(0,Math.min(Number(w)||0,o)),l=o>0?t/o*100:0,c=`calc(${l}% + ${(5*(1-l/100)).toFixed(4)}rem)`,d=r=>{const p=Math.floor(r/60),a=Math.floor(r%60);return`${p.toString().padStart(2,"0")}:${a.toString().padStart(2,"0")}`},h=x.useMemo(()=>{if(g.length)return g.map(a=>({...a,segments:s.filter(z=>z.actor===a.key)}));const r=Array.from(new Set(s.map(a=>a.actor))),p=new Map(s.map(a=>[a.actor,a.actorColor]));return r.map(a=>({key:a,label:a,color:p.get(a)||"#6B7C93",segments:s.filter(z=>z.actor===a)}))},[g,s]),f=[],B=120;for(let r=0;r<=o;r+=B)f.push(r);(!f.length||f[f.length-1]<o)&&f.push(o);const W=r=>{if(!b)return;const p=r.currentTarget.getBoundingClientRect();if(!p.width)return;const a=Math.max(0,Math.min((r.clientX-p.left)/p.width,1));b(a*o)};return e.jsxs("div",{style:{padding:"10px 0"},children:[v&&e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:8},children:[e.jsxs("div",{style:{fontSize:"var(--text-sm, 11px)",fontFamily:"var(--font-mono, monospace)",color:"var(--text-muted, rgba(30,33,37,0.56))",fontWeight:500,minWidth:70},children:[d(t)," ",e.jsxs("span",{style:{color:"var(--text-faint, rgba(30,33,37,0.36))"},children:["/ ",d(o)]})]}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6},children:[e.jsx("button",{type:"button",onClick:()=>{C("rewind"),i==null||i()},disabled:!u,title:"Rewind 15s",style:{display:"inline-flex",alignItems:"center",justifyContent:"center",width:28,height:28,borderRadius:"50%",border:`1px solid ${T==="rewind"?"var(--rail-discovery, #5E88B0)":"var(--border, rgba(52,58,64,0.12))"}`,background:"var(--paper, rgba(255,255,255,0.78))",cursor:"pointer",padding:0},children:e.jsx(I.RotateCcw,{size:13,stroke:"var(--rail-discovery, #5E88B0)"})}),e.jsx("button",{type:"button",onClick:n,disabled:!u,style:{display:"inline-flex",alignItems:"center",justifyContent:"center",width:32,height:32,borderRadius:"50%",background:"var(--rail-discovery, #5E88B0)",color:"#fff",border:"none",cursor:"pointer",padding:0},"aria-label":k?"Pause recording":"Play recording",children:k?e.jsx(I.Pause,{size:14}):e.jsx(I.Play,{size:14,style:{marginLeft:1}})}),e.jsx("button",{type:"button",onClick:()=>{C("forward"),y==null||y()},disabled:!u,title:"Forward 15s",style:{display:"inline-flex",alignItems:"center",justifyContent:"center",width:28,height:28,borderRadius:"50%",border:`1px solid ${T==="forward"?"var(--rail-discovery, #5E88B0)":"var(--border, rgba(52,58,64,0.12))"}`,background:"var(--paper, rgba(255,255,255,0.78))",cursor:"pointer",padding:0},children:e.jsx(I.RotateCw,{size:13,stroke:"var(--rail-discovery, #5E88B0)"})}),e.jsx("div",{style:{display:"inline-flex",alignItems:"center",gap:4,borderRadius:999,border:"1px solid var(--border, rgba(52,58,64,0.12))",padding:"2px 3px",background:"var(--paper, rgba(255,255,255,0.78))",marginLeft:4},children:R.map(r=>{const p=E===r;return e.jsx("button",{type:"button",onClick:()=>S==null?void 0:S(r),disabled:!u,title:`Speed: ${r}x`,style:{display:"inline-flex",alignItems:"center",justifyContent:"center",height:24,minWidth:38,padding:"0 6px",borderRadius:999,border:`1px solid ${p?"var(--rail-discovery, #5E88B0)":"transparent"}`,background:p?"var(--rail-discovery, #5E88B0)":"transparent",color:p?"#fff":"var(--text-muted, rgba(30,33,37,0.56))",fontSize:"var(--text-xs, 10px)",fontWeight:600,cursor:"pointer"},children:r===1.5?"1.50x":`${r}x`},r)})})]})]}),e.jsx("div",{style:{background:"var(--paper, rgba(255,255,255,0.78))",border:"1px solid var(--border, rgba(52,58,64,0.12))",borderRadius:10,padding:"12px 16px 10px"},children:e.jsxs("div",{style:{position:"relative"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",marginBottom:6,height:16},children:[e.jsx("div",{style:{width:"5rem",flexShrink:0}}),e.jsx("div",{style:{position:"relative",flex:1},children:f.map(r=>{const p=o>0?r/o*100:0;return e.jsx("div",{style:{position:"absolute",fontSize:"var(--text-xs, 10px)",color:"var(--text-faint, rgba(30,33,37,0.36))",left:`${p}%`,transform:"translateX(-50%)",fontFamily:"var(--font-mono, monospace)",whiteSpace:"nowrap"},children:d(r)},r)})})]}),e.jsx("div",{style:{position:"absolute",pointerEvents:"none",top:0,bottom:0,left:"5rem",width:"calc(100% - 5rem)",zIndex:20},children:f.map(r=>{const p=o>0?r/o*100:0;return e.jsx("div",{style:{position:"absolute",top:0,bottom:0,left:`${p}%`,borderLeft:"1px dashed var(--border, rgba(52,58,64,0.12))",transform:"translateX(-1px)"}},r)})}),e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:10,marginTop:8},children:h.map(r=>{const p=r.key==="system"||r.label==="System";return e.jsxs("div",{style:{display:"flex",alignItems:"center"},children:[e.jsx("div",{style:{width:"5rem",flexShrink:0,fontSize:"var(--text-sm, 11px)",fontWeight:600,color:"var(--text-muted, rgba(30,33,37,0.56))",fontFamily:"var(--font-sans, system-ui, sans-serif)",paddingRight:8},children:r.label}),e.jsx("div",{style:{position:"relative",borderRadius:4,flex:1,height:18,backgroundColor:"var(--paper-secondary, rgba(244,241,230,0.6))",border:"1px solid var(--border-subtle, rgba(52,58,64,0.08))"},children:r.segments.map((a,z)=>{let $=o>0?a.startTime/o*100:0,L=o>0?(a.endTime-a.startTime)/o*100:0;$=Math.max(0,Math.min(100,$)),$+L>100&&(L=100-$),L=Math.max(0,L);const H=a.endTime-a.startTime;return p&&H<=5?e.jsx("div",{style:{position:"absolute",cursor:"pointer",left:`${$}%`,top:"50%",transform:"translateY(-50%)",width:10,height:10,borderRadius:"50%",backgroundColor:r.color,opacity:.85},title:`${r.label}: ${d(a.startTime)}-${d(a.endTime)}`},z):e.jsx("div",{style:{position:"absolute",top:0,bottom:0,left:`${$}%`,width:`${Math.max(L,.7)}%`,maxWidth:`${100-$}%`,backgroundColor:r.color,opacity:.85,borderRadius:2,cursor:"pointer",transition:"opacity 0.15s"},title:`${r.label}: ${d(a.startTime)}-${d(a.endTime)}`},z)})})]},r.key)})}),e.jsx("div",{style:{pointerEvents:"none",position:"absolute",top:0,bottom:0,width:2,borderRadius:1,backgroundColor:"var(--rail-discovery, #5E88B0)",opacity:.55,boxShadow:"0 0 0 1px rgba(94,136,176,0.10)",left:c,transform:"translateX(-50%)"}}),b?e.jsx("button",{type:"button",onClick:W,style:{position:"absolute",cursor:"pointer",background:"transparent",border:"none",padding:0,margin:0,appearance:"none",top:0,bottom:0,left:"5rem",width:"calc(100% - 5rem)",zIndex:25},title:"Click timeline to play from that point","aria-label":"Click timeline to play from that point"}):null]})})]})}exports.ConversationTurn=P;exports.Timeline=q;exports.TranscriptCard=X;
|
|
2
7
|
//# sourceMappingURL=Timeline.cjs.js.map
|
package/dist/Timeline.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Timeline.cjs.js","sources":["../src/components/media/Timeline.jsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport { Play, Pause, RotateCcw, RotateCw } from \"lucide-react\";\n\nexport default function Timeline({\n segments = [],\n durationSeconds = 0,\n actorRows = [],\n currentTimeSeconds = 0,\n onSeek,\n showControls = false,\n hasRecording = false,\n timelinePlaying = false,\n playbackRate = 1,\n speedOptions = [1, 1.25, 1.5, 2],\n onTogglePlay,\n onSeekBack,\n onSeekForward,\n onSetPlaybackRate,\n totalDurationLabel,\n}) {\n const [activeControl, setActiveControl] = useState(null);\n\n useEffect(() => {\n if (!activeControl) return;\n const timer = setTimeout(() => setActiveControl(null), 220);\n return () => clearTimeout(timer);\n }, [activeControl]);\n\n const timelineDuration = Math.max(\n Number(durationSeconds) || 0,\n ...segments.map((segment) => Number(segment.endTime) || 0),\n 1\n );\n const clampedCurrent = Math.max(0, Math.min(Number(currentTimeSeconds) || 0, timelineDuration));\n const playheadPercent = timelineDuration > 0 ? (clampedCurrent / timelineDuration) * 100 : 0;\n const playheadLeft = `calc(${playheadPercent}% + ${(5 * (1 - playheadPercent / 100)).toFixed(4)}rem)`;\n\n const formatTime = (seconds) => {\n const mins = Math.floor(seconds / 60);\n const secs = Math.floor(seconds % 60);\n return `${mins.toString().padStart(2, \"0\")}:${secs.toString().padStart(2, \"0\")}`;\n };\n\n const rows = useMemo(() => {\n if (actorRows.length) {\n return actorRows.map((actor) => ({\n ...actor,\n segments: segments.filter((segment) => segment.actor === actor.key),\n }));\n }\n const actors = Array.from(new Set(segments.map((segment) => segment.actor)));\n const actorColors = new Map(segments.map((segment) => [segment.actor, segment.actorColor]));\n return actors.map((actor) => ({\n key: actor,\n label: actor,\n color: actorColors.get(actor) || \"#6B7C93\",\n segments: segments.filter((segment) => segment.actor === actor),\n }));\n }, [actorRows, segments]);\n\n const timeMarkers = [];\n const interval = 120;\n for (let marker = 0; marker <= timelineDuration; marker += interval) {\n timeMarkers.push(marker);\n }\n if (!timeMarkers.length || timeMarkers[timeMarkers.length - 1] < timelineDuration) {\n timeMarkers.push(timelineDuration);\n }\n\n const handleSeekClick = (event) => {\n if (!onSeek) return;\n const rect = event.currentTarget.getBoundingClientRect();\n if (!rect.width) return;\n const ratio = Math.max(0, Math.min((event.clientX - rect.left) / rect.width, 1));\n onSeek(ratio * timelineDuration);\n };\n\n return (\n <div style={{\n padding: \"10px 0\",\n }}>\n {showControls && (\n <div style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"space-between\", marginBottom: 8 }}>\n <div style={{\n fontSize: \"var(--text-sm, 11px)\",\n fontFamily: \"var(--font-mono, monospace)\",\n color: \"var(--text-muted, rgba(30,33,37,0.56))\",\n fontWeight: 500,\n minWidth: 70,\n }}>\n {formatTime(clampedCurrent)} <span style={{ color: \"var(--text-faint, rgba(30,33,37,0.36))\" }}>/ {formatTime(timelineDuration)}</span>\n </div>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 6 }}>\n <button\n type=\"button\"\n onClick={() => { setActiveControl(\"rewind\"); onSeekBack?.(); }}\n disabled={!hasRecording}\n title=\"Rewind 15s\"\n style={{\n display: \"inline-flex\", alignItems: \"center\", justifyContent: \"center\",\n width: 28, height: 28, borderRadius: \"50%\",\n border: `1px solid ${activeControl === \"rewind\" ? \"var(--rail-discovery, #5E88B0)\" : \"var(--border, rgba(52,58,64,0.12))\"}`,\n background: \"var(--paper, rgba(255,255,255,0.78))\", cursor: \"pointer\", padding: 0,\n }}\n >\n <RotateCcw size={13} stroke=\"var(--rail-discovery, #5E88B0)\" />\n </button>\n\n <button\n type=\"button\"\n onClick={onTogglePlay}\n disabled={!hasRecording}\n style={{\n display: \"inline-flex\", alignItems: \"center\", justifyContent: \"center\",\n width: 32, height: 32, borderRadius: \"50%\",\n background: \"var(--rail-discovery, #5E88B0)\", color: \"#fff\",\n border: \"none\", cursor: \"pointer\", padding: 0,\n }}\n aria-label={timelinePlaying ? \"Pause recording\" : \"Play recording\"}\n >\n {timelinePlaying ? <Pause size={14} /> : <Play size={14} style={{ marginLeft: 1 }} />}\n </button>\n\n <button\n type=\"button\"\n onClick={() => { setActiveControl(\"forward\"); onSeekForward?.(); }}\n disabled={!hasRecording}\n title=\"Forward 15s\"\n style={{\n display: \"inline-flex\", alignItems: \"center\", justifyContent: \"center\",\n width: 28, height: 28, borderRadius: \"50%\",\n border: `1px solid ${activeControl === \"forward\" ? \"var(--rail-discovery, #5E88B0)\" : \"var(--border, rgba(52,58,64,0.12))\"}`,\n background: \"var(--paper, rgba(255,255,255,0.78))\", cursor: \"pointer\", padding: 0,\n }}\n >\n <RotateCw size={13} stroke=\"var(--rail-discovery, #5E88B0)\" />\n </button>\n\n <div style={{ display: \"inline-flex\", alignItems: \"center\", gap: 4, borderRadius: 999, border: \"1px solid var(--border, rgba(52,58,64,0.12))\", padding: \"2px 3px\", background: \"var(--paper, rgba(255,255,255,0.78))\", marginLeft: 4 }}>\n {speedOptions.map((speed) => {\n const isActive = playbackRate === speed;\n return (\n <button\n key={speed}\n type=\"button\"\n onClick={() => onSetPlaybackRate?.(speed)}\n disabled={!hasRecording}\n title={`Speed: ${speed}x`}\n style={{\n display: \"inline-flex\", alignItems: \"center\", justifyContent: \"center\",\n height: 24, minWidth: 38, padding: \"0 6px\", borderRadius: 999,\n border: `1px solid ${isActive ? \"var(--rail-discovery, #5E88B0)\" : \"transparent\"}`,\n background: isActive ? \"var(--rail-discovery, #5E88B0)\" : \"transparent\",\n color: isActive ? \"#fff\" : \"var(--text-muted, rgba(30,33,37,0.56))\",\n fontSize: \"var(--text-xs, 10px)\", fontWeight: 600, cursor: \"pointer\",\n }}\n >\n {speed === 1.5 ? \"1.50x\" : `${speed}x`}\n </button>\n );\n })}\n </div>\n </div>\n </div>\n )}\n\n <div style={{\n background: \"var(--paper, rgba(255,255,255,0.78))\",\n border: \"1px solid var(--border, rgba(52,58,64,0.12))\",\n borderRadius: 10,\n padding: \"12px 16px 10px\",\n }}>\n <div style={{ position: \"relative\" }}>\n {/* Time markers row */}\n <div style={{ display: \"flex\", alignItems: \"center\", marginBottom: 6, height: 16 }}>\n <div style={{ width: \"5rem\", flexShrink: 0 }} />\n <div style={{ position: \"relative\", flex: 1 }}>\n {timeMarkers.map((time) => {\n const percentage = timelineDuration > 0 ? (time / timelineDuration) * 100 : 0;\n return (\n <div\n key={time}\n style={{\n position: \"absolute\",\n fontSize: \"var(--text-xs, 10px)\",\n color: \"var(--text-faint, rgba(30,33,37,0.36))\",\n left: `${percentage}%`,\n transform: \"translateX(-50%)\",\n fontFamily: \"var(--font-mono, monospace)\",\n whiteSpace: \"nowrap\",\n }}\n >\n {formatTime(time)}\n </div>\n );\n })}\n </div>\n </div>\n\n {/* Vertical gridlines */}\n <div\n style={{\n position: \"absolute\",\n pointerEvents: \"none\",\n top: 0,\n bottom: 0,\n left: \"5rem\",\n width: \"calc(100% - 5rem)\",\n zIndex: 20,\n }}\n >\n {timeMarkers.map((time) => {\n const percentage = timelineDuration > 0 ? (time / timelineDuration) * 100 : 0;\n return (\n <div\n key={time}\n style={{\n position: \"absolute\",\n top: 0,\n bottom: 0,\n left: `${percentage}%`,\n borderLeft: \"1px dashed var(--border, rgba(52,58,64,0.12))\",\n transform: \"translateX(-1px)\",\n }}\n />\n );\n })}\n </div>\n\n {/* Swim lanes */}\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 10, marginTop: 8 }}>\n {rows.map((row) => {\n const isSystem = row.key === \"system\" || row.label === \"System\";\n return (\n <div key={row.key} style={{ display: \"flex\", alignItems: \"center\" }}>\n <div\n style={{\n width: \"5rem\",\n flexShrink: 0,\n fontSize: \"var(--text-sm, 11px)\",\n fontWeight: 600,\n color: \"var(--text-muted, rgba(30,33,37,0.56))\",\n fontFamily: \"var(--font-sans, system-ui, sans-serif)\",\n paddingRight: 8,\n }}\n >\n {row.label}\n </div>\n\n <div\n style={{\n position: \"relative\",\n borderRadius: 4,\n flex: 1,\n height: 18,\n backgroundColor: \"var(--paper-secondary, rgba(244,241,230,0.6))\",\n border: \"1px solid var(--border-subtle, rgba(52,58,64,0.08))\",\n }}\n >\n {row.segments.map((segment, idx) => {\n let leftPercent = timelineDuration > 0 ? (segment.startTime / timelineDuration) * 100 : 0;\n let widthPercent =\n timelineDuration > 0\n ? ((segment.endTime - segment.startTime) / timelineDuration) * 100\n : 0;\n leftPercent = Math.max(0, Math.min(100, leftPercent));\n const rightPercent = leftPercent + widthPercent;\n if (rightPercent > 100) widthPercent = 100 - leftPercent;\n widthPercent = Math.max(0, widthPercent);\n const segmentDuration = segment.endTime - segment.startTime;\n\n if (isSystem && segmentDuration <= 5) {\n return (\n <div\n key={idx}\n style={{\n position: \"absolute\",\n cursor: \"pointer\",\n left: `${leftPercent}%`,\n top: \"50%\",\n transform: \"translateY(-50%)\",\n width: 10,\n height: 10,\n borderRadius: \"50%\",\n backgroundColor: row.color,\n opacity: 0.85,\n }}\n title={`${row.label}: ${formatTime(segment.startTime)}-${formatTime(segment.endTime)}`}\n />\n );\n }\n\n return (\n <div\n key={idx}\n style={{\n position: \"absolute\",\n top: 0,\n bottom: 0,\n left: `${leftPercent}%`,\n width: `${Math.max(widthPercent, 0.7)}%`,\n maxWidth: `${100 - leftPercent}%`,\n backgroundColor: row.color,\n opacity: 0.85,\n borderRadius: 2,\n cursor: \"pointer\",\n transition: \"opacity 0.15s\",\n }}\n title={`${row.label}: ${formatTime(segment.startTime)}-${formatTime(segment.endTime)}`}\n />\n );\n })}\n </div>\n </div>\n );\n })}\n </div>\n\n {/* Playhead */}\n <div\n style={{\n pointerEvents: \"none\",\n position: \"absolute\",\n top: 0,\n bottom: 0,\n width: 2,\n borderRadius: 1,\n backgroundColor: \"var(--rail-discovery, #5E88B0)\",\n opacity: 0.55,\n boxShadow: \"0 0 0 1px rgba(94,136,176,0.10)\",\n left: playheadLeft,\n transform: \"translateX(-50%)\",\n }}\n />\n\n {/* Seek overlay */}\n {onSeek ? (\n <button\n type=\"button\"\n onClick={handleSeekClick}\n style={{\n position: \"absolute\",\n cursor: \"pointer\",\n background: \"transparent\",\n border: \"none\",\n padding: 0,\n margin: 0,\n appearance: \"none\",\n top: 0,\n bottom: 0,\n left: \"5rem\",\n width: \"calc(100% - 5rem)\",\n zIndex: 25,\n }}\n title=\"Click timeline to play from that point\"\n aria-label=\"Click timeline to play from that point\"\n />\n ) : null}\n </div>\n </div>\n </div>\n );\n}\n"],"names":["Timeline","segments","durationSeconds","actorRows","currentTimeSeconds","onSeek","showControls","hasRecording","timelinePlaying","playbackRate","speedOptions","onTogglePlay","onSeekBack","onSeekForward","onSetPlaybackRate","totalDurationLabel","activeControl","setActiveControl","useState","useEffect","timer","timelineDuration","segment","clampedCurrent","playheadPercent","playheadLeft","formatTime","seconds","mins","secs","rows","useMemo","actor","actors","actorColors","timeMarkers","interval","marker","handleSeekClick","event","rect","ratio","jsxs","jsx","RotateCcw","Pause","Play","RotateCw","speed","isActive","time","percentage","row","isSystem","idx","leftPercent","widthPercent","segmentDuration"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Timeline.cjs.js","sources":["../src/components/media/ConversationTurn.jsx","../src/components/media/TranscriptCard.jsx","../src/components/media/Timeline.jsx"],"sourcesContent":["\"use client\";\n\nimport React, { useEffect } from \"react\";\n\n/**\n * Actor configuration — rail color + subtle card tint per role.\n * Colors reference CSS custom properties from the Chordia design system.\n */\nconst ACTOR_DEFAULTS = {\n customer: {\n label: \"Customer\",\n railColor: \"var(--rail-discovery)\",\n cardBg: \"var(--card-customer)\",\n cardBgHighlight: \"rgba(94, 136, 176, 0.12)\",\n borderColor: \"var(--border-subtle)\",\n },\n agent: {\n label: \"Agent\",\n railColor: \"var(--rail-outcome)\",\n cardBg: \"var(--card-agent)\",\n cardBgHighlight: \"rgba(107, 124, 147, 0.10)\",\n borderColor: \"var(--border-subtle)\",\n },\n assistant: {\n label: \"AI Assistant\",\n railColor: \"var(--rail-purple)\",\n cardBg: \"var(--card-assistant)\",\n cardBgHighlight: \"rgba(155, 122, 168, 0.10)\",\n borderColor: \"var(--border-subtle)\",\n },\n system: {\n label: \"System\",\n railColor: \"var(--text-faint)\",\n cardBg: \"transparent\",\n cardBgHighlight: \"transparent\",\n borderColor: \"transparent\",\n },\n};\n\n/**\n * ConversationTurn Component\n * Displays a single turn in a live conversation stream.\n * Uses the TranscriptCard design language: left actor rail, uppercase label,\n * subtle per-actor card tinting.\n *\n * @param {Object} props\n * @param {string} props.role - \"customer\" | \"agent\" | \"assistant\" | \"system\"\n * @param {string} props.text - Message content\n * @param {string} [props.actorLabel] - Override the default actor label\n * @param {string} [props.actorRailColor] - Override the rail color for this turn\n * @param {string} [props.actionKicker] - NBA action label above message\n * @param {Array} [props.toolBadges] - [{name, success, pending}] tool call results\n * @param {boolean} [props.streaming] - Whether this message is actively streaming\n * @param {string} [props.meta] - Timing info, turn number, etc.\n * @param {string} [props.timeRange] - Time range label (e.g., \"00:03–00:07\")\n * @param {boolean} [props.isHighlighted] - Extra emphasis on this turn\n * @param {string} [props.highlightRailColor] - Color for the right highlight rail (when highlighted)\n * @param {React.ReactNode} [props.children] - Additional content below the message text\n */\nconst KEYFRAMES_ID = \"conversation-turn-keyframes\";\nfunction ensureKeyframes() {\n if (typeof document === \"undefined\") return;\n if (document.getElementById(KEYFRAMES_ID)) return;\n const style = document.createElement(\"style\");\n style.id = KEYFRAMES_ID;\n style.textContent = `\n @keyframes turn-playing-pulse {\n 0%, 100% { opacity: 0.4; }\n 50% { opacity: 0.9; }\n }\n `;\n document.head.appendChild(style);\n}\n\nexport default function ConversationTurn({\n role = \"agent\",\n text,\n actorLabel,\n actorRailColor,\n actionKicker,\n toolBadges,\n streaming = false,\n meta,\n timeRange,\n isHighlighted = false,\n highlightRailColor,\n observations,\n onObservationClick,\n children,\n}) {\n useEffect(() => { ensureKeyframes(); }, []);\n const actor = ACTOR_DEFAULTS[role] || ACTOR_DEFAULTS.agent;\n const label = actorLabel || actor.label;\n const railColor = actorRailColor || actor.railColor;\n const highlighted = isHighlighted || streaming;\n\n // System messages: minimal centered text, no card\n if (role === \"system\") {\n return (\n <div\n style={{\n textAlign: \"center\",\n padding: \"6px 0\",\n flexShrink: 0,\n fontSize: \"var(--text-sm, 11px)\",\n color: \"var(--text-faint, rgba(30,33,37,0.36))\",\n fontWeight: 500,\n letterSpacing: \"0.02em\",\n }}\n >\n {text}\n </div>\n );\n }\n\n return (\n <div\n style={{\n position: \"relative\",\n padding: \"10px 14px 10px 18px\",\n borderRadius: 10,\n overflow: \"hidden\",\n flexShrink: 0,\n background: highlighted ? actor.cardBgHighlight : actor.cardBg,\n border: `1px solid ${streaming ? railColor : actor.borderColor}`,\n boxShadow: streaming\n ? `0 0 8px ${actor.cardBgHighlight}`\n : \"none\",\n transition: \"background 0.2s, border-color 0.2s, box-shadow 0.2s\",\n }}\n >\n {/* Left actor rail */}\n <div\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n bottom: 0,\n width: \"var(--rail-width-thin, 4px)\",\n backgroundColor: railColor,\n borderRadius: \"10px 0 0 10px\",\n }}\n />\n\n {/* Header row: actor label left, tool badges right */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"flex-start\",\n justifyContent: \"space-between\",\n gap: 8,\n marginBottom: 4,\n }}\n >\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 2 }}>\n {/* Action kicker (NBA label) */}\n {actionKicker ? (\n <div\n style={{\n fontSize: \"var(--text-xs-plus, 10.5px)\",\n fontWeight: 650,\n textTransform: \"uppercase\",\n letterSpacing: \"var(--tracking-label, 0.16em)\",\n color: railColor,\n }}\n >\n {actionKicker}\n </div>\n ) : null}\n\n {/* Actor label */}\n <div\n style={{\n fontSize: \"var(--text-xs-plus, 10.5px)\",\n fontWeight: 650,\n textTransform: \"uppercase\",\n letterSpacing: \"var(--tracking-label, 0.16em)\",\n color: \"var(--text-faint, rgba(30,33,37,0.36))\",\n }}\n >\n {label}\n </div>\n </div>\n\n {/* Tool badges — top right pills, uniform neutral with status dot */}\n {toolBadges && toolBadges.length > 0 ? (\n <div style={{ display: \"flex\", flexWrap: \"wrap\", gap: 4, flexShrink: 0, justifyContent: \"flex-end\" }}>\n {toolBadges.map((t, i) => {\n const isPending = t.pending;\n const isError = !isPending && t.success === false;\n // Dot color only — rail colors for categorization, not judgment\n const dotColor = isPending\n ? \"var(--rail-discovery, #5E88B0)\"\n : isError\n ? \"var(--rail-compliance, #C98A5A)\"\n : \"var(--text-xfaint, rgba(30,33,37,0.28))\";\n\n return (\n <span\n key={i}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 5,\n fontSize: \"var(--text-xs, 10px)\",\n padding: \"2px 8px 2px 6px\",\n borderRadius: 999,\n background: \"var(--paper, rgba(255,255,255,0.78))\",\n border: \"1px solid var(--border-subtle, rgba(52,58,64,0.08))\",\n color: \"var(--text-faint, rgba(30,33,37,0.36))\",\n fontWeight: 500,\n fontFamily: \"var(--font-fira-code, var(--font-mono, monospace))\",\n letterSpacing: \"0.01em\",\n lineHeight: 1.4,\n whiteSpace: \"nowrap\",\n }}\n >\n <span\n style={{\n width: 5,\n height: 5,\n borderRadius: \"50%\",\n backgroundColor: dotColor,\n flexShrink: 0,\n }}\n />\n {t.name}\n </span>\n );\n })}\n </div>\n ) : null}\n </div>\n\n {/* Message text */}\n <div\n style={{\n fontSize: \"var(--text-md, 13px)\",\n lineHeight: \"var(--leading-normal, 1.5)\",\n color: streaming\n ? \"var(--text-strong, rgba(30,33,37,0.92))\"\n : \"var(--text-base, rgba(30,33,37,0.78))\",\n fontWeight: streaming ? 550 : 400,\n }}\n >\n {text}\n {streaming ? (\n <span\n style={{\n display: \"inline-block\",\n width: 6,\n height: 14,\n background: railColor,\n marginLeft: 2,\n borderRadius: 1,\n animation: \"cursorBlink 0.8s ease-in-out infinite\",\n verticalAlign: \"text-bottom\",\n }}\n />\n ) : null}\n </div>\n\n {/* Time range + play button + observation pills — single row */}\n {timeRange || children || (observations && observations.length > 0) ? (\n <div style={{ marginTop: 6, display: \"flex\", alignItems: \"center\", gap: 6 }}>\n {children}\n {timeRange ? (\n <span\n style={{\n fontSize: \"var(--text-sm, 11px)\",\n padding: \"2px 8px\",\n borderRadius: 999,\n border: \"1px solid var(--border, rgba(52,58,64,0.12))\",\n background: \"var(--timestamp-bg, rgba(255,255,255,0.70))\",\n color: \"var(--text-muted, rgba(30,33,37,0.56))\",\n fontFamily: \"var(--font-mono, monospace)\",\n }}\n >\n {timeRange}\n </span>\n ) : null}\n {observations && observations.length > 0 ? (\n <div style={{ display: \"flex\", flexWrap: \"wrap\", gap: 4, marginLeft: \"auto\" }}>\n {observations.map((obs, i) => (\n <span\n key={i}\n onClick={obs.onClick || (onObservationClick ? () => onObservationClick(obs) : undefined)}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 4,\n fontSize: \"var(--text-xs, 10px)\",\n padding: \"2px 8px\",\n borderRadius: 999,\n background: `color-mix(in srgb, ${obs.color || \"var(--state-present)\"} 12%, transparent)`,\n border: `1px solid color-mix(in srgb, ${obs.color || \"var(--state-present)\"} 25%, transparent)`,\n color: obs.color || \"var(--state-present)\",\n fontWeight: 550,\n lineHeight: 1.4,\n whiteSpace: \"nowrap\",\n cursor: obs.onClick || onObservationClick ? \"pointer\" : \"default\",\n transition: \"background 0.15s\",\n }}\n title={obs.reason || obs.label}\n >\n <span style={{\n width: 4, height: 4, borderRadius: \"50%\",\n backgroundColor: obs.color || \"var(--state-present)\",\n flexShrink: 0, opacity: 0.7,\n }} />\n {obs.label}\n </span>\n ))}\n </div>\n ) : null}\n </div>\n ) : null}\n\n {/* Meta / timestamp */}\n {meta ? (\n <div\n style={{\n marginTop: 6,\n fontSize: \"var(--text-xs-plus, 10.5px)\",\n color: \"var(--text-faint, rgba(30,33,37,0.36))\",\n fontFamily: \"var(--font-mono, monospace)\",\n }}\n >\n {meta}\n </div>\n ) : null}\n\n {/* Right highlight rail (used by TranscriptCard for active/highlighted turns) */}\n {highlighted && highlightRailColor ? (\n <div\n style={{\n position: \"absolute\",\n right: 8,\n top: 8,\n bottom: 8,\n width: 6,\n borderRadius: 4,\n backgroundColor: highlightRailColor,\n opacity: 0.7,\n animation: \"turn-playing-pulse 1.5s ease-in-out infinite\",\n }}\n />\n ) : null}\n </div>\n );\n}\n","\"use client\";\n\nimport React, { useState, useRef, useEffect } from \"react\";\nimport { Play, Pause } from \"lucide-react\";\nimport ConversationTurn from \"./ConversationTurn\";\n\n/**\n * Helper function to parse time range string (e.g., \"00:03–00:07\") to seconds\n */\nconst parseTimeRange = (timeRange) => {\n const [start, end] = timeRange.split(\"–\").map((time) => {\n const [minutes, seconds] = time.split(\":\").map(Number);\n return minutes * 60 + seconds;\n });\n return { start, end };\n};\n\n/**\n * Map TranscriptCard actorType values to ConversationTurn role values.\n * ConversationTurn uses: \"customer\" | \"agent\" | \"assistant\" | \"system\"\n * TranscriptCard uses: \"customer\" | \"agent\" | \"third_party\" | \"system\"\n */\nconst mapActorTypeToRole = (actorType) => {\n const map = {\n customer: \"customer\",\n agent: \"agent\",\n third_party: \"agent\",\n system: \"system\",\n assistant: \"assistant\",\n };\n return map[actorType] || \"agent\";\n};\n\n/**\n * TranscriptCard Component\n * Displays a complete transcript with multiple turns, audio playback,\n * highlighting, and per-turn play buttons. Composes ConversationTurn\n * for individual turn rendering.\n *\n * @param {Object} props - Component props\n * @param {Array} props.turns - Array of transcript turn objects\n * @param {string} props.turns[].actor - Display name (e.g., \"Agent\", \"Customer\")\n * @param {string} props.turns[].actorType - \"agent\" | \"customer\" | \"third_party\" | \"system\" | \"assistant\"\n * @param {string} [props.turns[].actorColor] - Override rail color for this turn\n * @param {string} props.turns[].text - Transcript text\n * @param {string} [props.turns[].timeRange] - Time range (e.g., \"00:03–00:07\")\n * @param {boolean} [props.turns[].isHighlighted] - Whether this turn is highlighted\n * @param {string} [props.turns[].highlightColor] - Color for the right highlight rail\n * @param {Array} [props.turns[].toolBadges] - Tool badge data [{name, success, pending}]\n * @param {string} [props.audioUrl] - Audio URL for segment playback\n * @param {number} [props.activeTurnIndex=-1] - Index of the externally active turn\n * @param {boolean} [props.autoScrollActiveTurn=false] - Auto-scroll to active turn\n * @param {boolean} [props.isExternalPlaying=false] - External playback state\n * @param {Function} [props.onTurnPlayPause] - External playback handler (turn, index) => void\n */\nexport default function TranscriptCard({\n turns,\n audioUrl,\n activeTurnIndex = -1,\n autoScrollActiveTurn = false,\n isExternalPlaying = false,\n onTurnPlayPause,\n}) {\n const [playingSegment, setPlayingSegment] = useState(null);\n const [isPlaying, setIsPlaying] = useState(false);\n const audioRef = useRef(null);\n const endTimeListenerRef = useRef(null);\n const turnRefs = useRef([]);\n const containerRef = useRef(null);\n const lastAutoScrolledIndexRef = useRef(-1);\n const useExternalPlaybackControl = typeof onTurnPlayPause === \"function\";\n const hasExternalPlaybackState = isExternalPlaying !== undefined;\n\n // Initialize audio element\n useEffect(() => {\n if (audioUrl) {\n audioRef.current = new Audio(audioUrl);\n audioRef.current.preload = \"auto\";\n return () => {\n if (audioRef.current) {\n audioRef.current.pause();\n audioRef.current = null;\n }\n };\n }\n }, [audioUrl]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n if (audioRef.current) {\n audioRef.current.pause();\n if (endTimeListenerRef.current) {\n audioRef.current.removeEventListener(\"timeupdate\", endTimeListenerRef.current);\n }\n }\n };\n }, []);\n\n // Auto-scroll to active turn\n useEffect(() => {\n if (!autoScrollActiveTurn || activeTurnIndex < 0) return;\n const container = containerRef.current;\n const activeNode = turnRefs.current[activeTurnIndex];\n if (!activeNode || !container) return;\n\n const containerRect = container.getBoundingClientRect();\n const activeRect = activeNode.getBoundingClientRect();\n const topPadding = 12;\n const isFullyVisible =\n activeRect.top >= containerRect.top + topPadding &&\n activeRect.bottom <= containerRect.bottom - 8;\n const didScrollForThisTurn = lastAutoScrolledIndexRef.current === activeTurnIndex;\n\n if (!didScrollForThisTurn || !isFullyVisible) {\n const activeTopInContainer = activeRect.top - containerRect.top + container.scrollTop;\n container.scrollTop = Math.max(activeTopInContainer - topPadding, 0);\n }\n lastAutoScrolledIndexRef.current = activeTurnIndex;\n }, [activeTurnIndex, autoScrollActiveTurn]);\n\n const handlePlayPause = (timeRange, index) => {\n if (useExternalPlaybackControl) {\n onTurnPlayPause(turns[index], index);\n return;\n }\n\n if (playingSegment === index && isPlaying) {\n // Pause current segment\n if (audioRef.current) {\n audioRef.current.pause();\n if (endTimeListenerRef.current) {\n audioRef.current.removeEventListener(\"timeupdate\", endTimeListenerRef.current);\n endTimeListenerRef.current = null;\n }\n }\n setIsPlaying(false);\n } else {\n // Start/switch segment\n const previousSegment = playingSegment;\n setPlayingSegment(index);\n\n if (audioUrl && audioRef.current) {\n const { start, end } = parseTimeRange(timeRange);\n\n if (previousSegment !== null && previousSegment !== index) {\n audioRef.current.pause();\n if (endTimeListenerRef.current) {\n audioRef.current.removeEventListener(\"timeupdate\", endTimeListenerRef.current);\n endTimeListenerRef.current = null;\n }\n }\n\n const playSegment = () => {\n if (!audioRef.current) return;\n audioRef.current.currentTime = start;\n\n if (end) {\n const checkEndTime = () => {\n if (audioRef.current && audioRef.current.currentTime >= end) {\n audioRef.current.pause();\n setIsPlaying(false);\n setPlayingSegment(null);\n if (endTimeListenerRef.current) {\n audioRef.current.removeEventListener(\"timeupdate\", endTimeListenerRef.current);\n endTimeListenerRef.current = null;\n }\n }\n };\n endTimeListenerRef.current = checkEndTime;\n audioRef.current.addEventListener(\"timeupdate\", checkEndTime);\n }\n\n audioRef.current.play()\n .then(() => setIsPlaying(true))\n .catch((err) => {\n // Ignore AbortError which occurs when play() is interrupted by pause()\n if (err && err.name === \"AbortError\") {\n return;\n }\n setIsPlaying(false);\n setPlayingSegment(null);\n });\n };\n\n if (audioRef.current.readyState >= 2) {\n playSegment();\n } else {\n audioRef.current.addEventListener(\"loadedmetadata\", playSegment, { once: true });\n audioRef.current.load();\n }\n } else {\n setIsPlaying(true);\n }\n }\n };\n\n return (\n <div\n ref={containerRef}\n className=\"custom-thin-scrollbar-library\"\n style={{\n maxHeight: 560,\n overflowY: \"auto\",\n scrollBehavior: \"smooth\",\n border: \"1px solid var(--border, rgba(52,58,64,0.12))\",\n // borderRadius: \"var(--radius-lg, 12px)\",\n borderRadius: \"12px 0px 0px 12px\",\n background: \"var(--paper-elevated, rgba(255,255,255,0.82))\",\n padding: 16,\n }}\n >\n {/* Section label */}\n <div\n style={{\n fontSize: \"var(--text-xs-plus, 10.5px)\",\n fontWeight: 650,\n textTransform: \"uppercase\",\n letterSpacing: \"var(--tracking-label, 0.16em)\",\n color: \"var(--text-faint, rgba(30,33,37,0.36))\",\n marginBottom: 12,\n }}\n >\n Transcript\n </div>\n\n {/* Turns */}\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 8 }}>\n {turns.map((turn, index) => {\n const isTurnPlaying = (useExternalPlaybackControl || hasExternalPlaybackState)\n ? Boolean(isExternalPlaying) && activeTurnIndex === index\n : playingSegment === index && isPlaying;\n const isTurnHighlighted = Boolean(turn.isHighlighted) || isTurnPlaying;\n const role = mapActorTypeToRole(turn.actorType);\n\n return (\n <div\n key={index}\n ref={(el) => { turnRefs.current[index] = el; }}\n >\n <ConversationTurn\n role={role}\n text={turn.text}\n actorLabel={turn.actor}\n actorRailColor={turn.actorColor}\n timeRange={turn.timeRange}\n isHighlighted={isTurnHighlighted}\n highlightRailColor={isTurnPlaying \n ? (turn.highlightColor || (role === 'agent' ? 'var(--rail-outcome)' : 'var(--rail-discovery)'))\n : turn.highlightColor}\n toolBadges={turn.toolBadges}\n observations={turn.observations}\n onObservationClick={turn.onObservationClick}\n >\n {/* Play/pause button — rendered inline left of time range */}\n {turn.timeRange ? (\n <button\n onClick={() => handlePlayPause(turn.timeRange, index)}\n style={{\n width: 24,\n height: 24,\n borderRadius: \"50%\",\n border: \"1px solid var(--border, rgba(52,58,64,0.12))\",\n background: isTurnPlaying\n ? \"var(--rail-discovery, #5E88B0)\"\n : \"var(--paper, rgba(255,255,255,0.78))\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n padding: 0,\n transition: \"all 0.15s\",\n }}\n aria-label={isTurnPlaying ? `Pause segment ${turn.timeRange}` : `Play segment ${turn.timeRange}`}\n >\n {isTurnPlaying ? (\n <Pause\n style={{ width: 12, height: 12, color: \"var(--paper, #fff)\", fill: \"var(--paper, #fff)\" }}\n strokeWidth={0}\n />\n ) : (\n <Play\n style={{ width: 12, height: 12, color: \"var(--text-muted, rgba(30,33,37,0.56))\", fill: \"var(--text-muted, rgba(30,33,37,0.56))\", marginLeft: 1 }}\n strokeWidth={0}\n />\n )}\n </button>\n ) : null}\n </ConversationTurn>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport { Play, Pause, RotateCcw, RotateCw } from \"lucide-react\";\n\nexport default function Timeline({\n segments = [],\n durationSeconds = 0,\n actorRows = [],\n currentTimeSeconds = 0,\n onSeek,\n showControls = false,\n hasRecording = false,\n timelinePlaying = false,\n playbackRate = 1,\n speedOptions = [1, 1.25, 1.5, 2],\n onTogglePlay,\n onSeekBack,\n onSeekForward,\n onSetPlaybackRate,\n totalDurationLabel,\n}) {\n const [activeControl, setActiveControl] = useState(null);\n\n useEffect(() => {\n if (!activeControl) return;\n const timer = setTimeout(() => setActiveControl(null), 220);\n return () => clearTimeout(timer);\n }, [activeControl]);\n\n const timelineDuration = Math.max(\n Number(durationSeconds) || 0,\n ...segments.map((segment) => Number(segment.endTime) || 0),\n 1\n );\n const clampedCurrent = Math.max(0, Math.min(Number(currentTimeSeconds) || 0, timelineDuration));\n const playheadPercent = timelineDuration > 0 ? (clampedCurrent / timelineDuration) * 100 : 0;\n const playheadLeft = `calc(${playheadPercent}% + ${(5 * (1 - playheadPercent / 100)).toFixed(4)}rem)`;\n\n const formatTime = (seconds) => {\n const mins = Math.floor(seconds / 60);\n const secs = Math.floor(seconds % 60);\n return `${mins.toString().padStart(2, \"0\")}:${secs.toString().padStart(2, \"0\")}`;\n };\n\n const rows = useMemo(() => {\n if (actorRows.length) {\n return actorRows.map((actor) => ({\n ...actor,\n segments: segments.filter((segment) => segment.actor === actor.key),\n }));\n }\n const actors = Array.from(new Set(segments.map((segment) => segment.actor)));\n const actorColors = new Map(segments.map((segment) => [segment.actor, segment.actorColor]));\n return actors.map((actor) => ({\n key: actor,\n label: actor,\n color: actorColors.get(actor) || \"#6B7C93\",\n segments: segments.filter((segment) => segment.actor === actor),\n }));\n }, [actorRows, segments]);\n\n const timeMarkers = [];\n const interval = 120;\n for (let marker = 0; marker <= timelineDuration; marker += interval) {\n timeMarkers.push(marker);\n }\n if (!timeMarkers.length || timeMarkers[timeMarkers.length - 1] < timelineDuration) {\n timeMarkers.push(timelineDuration);\n }\n\n const handleSeekClick = (event) => {\n if (!onSeek) return;\n const rect = event.currentTarget.getBoundingClientRect();\n if (!rect.width) return;\n const ratio = Math.max(0, Math.min((event.clientX - rect.left) / rect.width, 1));\n onSeek(ratio * timelineDuration);\n };\n\n return (\n <div style={{\n padding: \"10px 0\",\n }}>\n {showControls && (\n <div style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"space-between\", marginBottom: 8 }}>\n <div style={{\n fontSize: \"var(--text-sm, 11px)\",\n fontFamily: \"var(--font-mono, monospace)\",\n color: \"var(--text-muted, rgba(30,33,37,0.56))\",\n fontWeight: 500,\n minWidth: 70,\n }}>\n {formatTime(clampedCurrent)} <span style={{ color: \"var(--text-faint, rgba(30,33,37,0.36))\" }}>/ {formatTime(timelineDuration)}</span>\n </div>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 6 }}>\n <button\n type=\"button\"\n onClick={() => { setActiveControl(\"rewind\"); onSeekBack?.(); }}\n disabled={!hasRecording}\n title=\"Rewind 15s\"\n style={{\n display: \"inline-flex\", alignItems: \"center\", justifyContent: \"center\",\n width: 28, height: 28, borderRadius: \"50%\",\n border: `1px solid ${activeControl === \"rewind\" ? \"var(--rail-discovery, #5E88B0)\" : \"var(--border, rgba(52,58,64,0.12))\"}`,\n background: \"var(--paper, rgba(255,255,255,0.78))\", cursor: \"pointer\", padding: 0,\n }}\n >\n <RotateCcw size={13} stroke=\"var(--rail-discovery, #5E88B0)\" />\n </button>\n\n <button\n type=\"button\"\n onClick={onTogglePlay}\n disabled={!hasRecording}\n style={{\n display: \"inline-flex\", alignItems: \"center\", justifyContent: \"center\",\n width: 32, height: 32, borderRadius: \"50%\",\n background: \"var(--rail-discovery, #5E88B0)\", color: \"#fff\",\n border: \"none\", cursor: \"pointer\", padding: 0,\n }}\n aria-label={timelinePlaying ? \"Pause recording\" : \"Play recording\"}\n >\n {timelinePlaying ? <Pause size={14} /> : <Play size={14} style={{ marginLeft: 1 }} />}\n </button>\n\n <button\n type=\"button\"\n onClick={() => { setActiveControl(\"forward\"); onSeekForward?.(); }}\n disabled={!hasRecording}\n title=\"Forward 15s\"\n style={{\n display: \"inline-flex\", alignItems: \"center\", justifyContent: \"center\",\n width: 28, height: 28, borderRadius: \"50%\",\n border: `1px solid ${activeControl === \"forward\" ? \"var(--rail-discovery, #5E88B0)\" : \"var(--border, rgba(52,58,64,0.12))\"}`,\n background: \"var(--paper, rgba(255,255,255,0.78))\", cursor: \"pointer\", padding: 0,\n }}\n >\n <RotateCw size={13} stroke=\"var(--rail-discovery, #5E88B0)\" />\n </button>\n\n <div style={{ display: \"inline-flex\", alignItems: \"center\", gap: 4, borderRadius: 999, border: \"1px solid var(--border, rgba(52,58,64,0.12))\", padding: \"2px 3px\", background: \"var(--paper, rgba(255,255,255,0.78))\", marginLeft: 4 }}>\n {speedOptions.map((speed) => {\n const isActive = playbackRate === speed;\n return (\n <button\n key={speed}\n type=\"button\"\n onClick={() => onSetPlaybackRate?.(speed)}\n disabled={!hasRecording}\n title={`Speed: ${speed}x`}\n style={{\n display: \"inline-flex\", alignItems: \"center\", justifyContent: \"center\",\n height: 24, minWidth: 38, padding: \"0 6px\", borderRadius: 999,\n border: `1px solid ${isActive ? \"var(--rail-discovery, #5E88B0)\" : \"transparent\"}`,\n background: isActive ? \"var(--rail-discovery, #5E88B0)\" : \"transparent\",\n color: isActive ? \"#fff\" : \"var(--text-muted, rgba(30,33,37,0.56))\",\n fontSize: \"var(--text-xs, 10px)\", fontWeight: 600, cursor: \"pointer\",\n }}\n >\n {speed === 1.5 ? \"1.50x\" : `${speed}x`}\n </button>\n );\n })}\n </div>\n </div>\n </div>\n )}\n\n <div style={{\n background: \"var(--paper, rgba(255,255,255,0.78))\",\n border: \"1px solid var(--border, rgba(52,58,64,0.12))\",\n borderRadius: 10,\n padding: \"12px 16px 10px\",\n }}>\n <div style={{ position: \"relative\" }}>\n {/* Time markers row */}\n <div style={{ display: \"flex\", alignItems: \"center\", marginBottom: 6, height: 16 }}>\n <div style={{ width: \"5rem\", flexShrink: 0 }} />\n <div style={{ position: \"relative\", flex: 1 }}>\n {timeMarkers.map((time) => {\n const percentage = timelineDuration > 0 ? (time / timelineDuration) * 100 : 0;\n return (\n <div\n key={time}\n style={{\n position: \"absolute\",\n fontSize: \"var(--text-xs, 10px)\",\n color: \"var(--text-faint, rgba(30,33,37,0.36))\",\n left: `${percentage}%`,\n transform: \"translateX(-50%)\",\n fontFamily: \"var(--font-mono, monospace)\",\n whiteSpace: \"nowrap\",\n }}\n >\n {formatTime(time)}\n </div>\n );\n })}\n </div>\n </div>\n\n {/* Vertical gridlines */}\n <div\n style={{\n position: \"absolute\",\n pointerEvents: \"none\",\n top: 0,\n bottom: 0,\n left: \"5rem\",\n width: \"calc(100% - 5rem)\",\n zIndex: 20,\n }}\n >\n {timeMarkers.map((time) => {\n const percentage = timelineDuration > 0 ? (time / timelineDuration) * 100 : 0;\n return (\n <div\n key={time}\n style={{\n position: \"absolute\",\n top: 0,\n bottom: 0,\n left: `${percentage}%`,\n borderLeft: \"1px dashed var(--border, rgba(52,58,64,0.12))\",\n transform: \"translateX(-1px)\",\n }}\n />\n );\n })}\n </div>\n\n {/* Swim lanes */}\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 10, marginTop: 8 }}>\n {rows.map((row) => {\n const isSystem = row.key === \"system\" || row.label === \"System\";\n return (\n <div key={row.key} style={{ display: \"flex\", alignItems: \"center\" }}>\n <div\n style={{\n width: \"5rem\",\n flexShrink: 0,\n fontSize: \"var(--text-sm, 11px)\",\n fontWeight: 600,\n color: \"var(--text-muted, rgba(30,33,37,0.56))\",\n fontFamily: \"var(--font-sans, system-ui, sans-serif)\",\n paddingRight: 8,\n }}\n >\n {row.label}\n </div>\n\n <div\n style={{\n position: \"relative\",\n borderRadius: 4,\n flex: 1,\n height: 18,\n backgroundColor: \"var(--paper-secondary, rgba(244,241,230,0.6))\",\n border: \"1px solid var(--border-subtle, rgba(52,58,64,0.08))\",\n }}\n >\n {row.segments.map((segment, idx) => {\n let leftPercent = timelineDuration > 0 ? (segment.startTime / timelineDuration) * 100 : 0;\n let widthPercent =\n timelineDuration > 0\n ? ((segment.endTime - segment.startTime) / timelineDuration) * 100\n : 0;\n leftPercent = Math.max(0, Math.min(100, leftPercent));\n const rightPercent = leftPercent + widthPercent;\n if (rightPercent > 100) widthPercent = 100 - leftPercent;\n widthPercent = Math.max(0, widthPercent);\n const segmentDuration = segment.endTime - segment.startTime;\n\n if (isSystem && segmentDuration <= 5) {\n return (\n <div\n key={idx}\n style={{\n position: \"absolute\",\n cursor: \"pointer\",\n left: `${leftPercent}%`,\n top: \"50%\",\n transform: \"translateY(-50%)\",\n width: 10,\n height: 10,\n borderRadius: \"50%\",\n backgroundColor: row.color,\n opacity: 0.85,\n }}\n title={`${row.label}: ${formatTime(segment.startTime)}-${formatTime(segment.endTime)}`}\n />\n );\n }\n\n return (\n <div\n key={idx}\n style={{\n position: \"absolute\",\n top: 0,\n bottom: 0,\n left: `${leftPercent}%`,\n width: `${Math.max(widthPercent, 0.7)}%`,\n maxWidth: `${100 - leftPercent}%`,\n backgroundColor: row.color,\n opacity: 0.85,\n borderRadius: 2,\n cursor: \"pointer\",\n transition: \"opacity 0.15s\",\n }}\n title={`${row.label}: ${formatTime(segment.startTime)}-${formatTime(segment.endTime)}`}\n />\n );\n })}\n </div>\n </div>\n );\n })}\n </div>\n\n {/* Playhead */}\n <div\n style={{\n pointerEvents: \"none\",\n position: \"absolute\",\n top: 0,\n bottom: 0,\n width: 2,\n borderRadius: 1,\n backgroundColor: \"var(--rail-discovery, #5E88B0)\",\n opacity: 0.55,\n boxShadow: \"0 0 0 1px rgba(94,136,176,0.10)\",\n left: playheadLeft,\n transform: \"translateX(-50%)\",\n }}\n />\n\n {/* Seek overlay */}\n {onSeek ? (\n <button\n type=\"button\"\n onClick={handleSeekClick}\n style={{\n position: \"absolute\",\n cursor: \"pointer\",\n background: \"transparent\",\n border: \"none\",\n padding: 0,\n margin: 0,\n appearance: \"none\",\n top: 0,\n bottom: 0,\n left: \"5rem\",\n width: \"calc(100% - 5rem)\",\n zIndex: 25,\n }}\n title=\"Click timeline to play from that point\"\n aria-label=\"Click timeline to play from that point\"\n />\n ) : null}\n </div>\n </div>\n </div>\n );\n}\n"],"names":["ACTOR_DEFAULTS","KEYFRAMES_ID","ensureKeyframes","style","ConversationTurn","role","text","actorLabel","actorRailColor","actionKicker","toolBadges","streaming","meta","timeRange","isHighlighted","highlightRailColor","observations","onObservationClick","children","useEffect","actor","label","railColor","highlighted","jsx","jsxs","i","isPending","isError","dotColor","obs","parseTimeRange","start","end","time","minutes","seconds","mapActorTypeToRole","actorType","TranscriptCard","turns","audioUrl","activeTurnIndex","autoScrollActiveTurn","isExternalPlaying","onTurnPlayPause","playingSegment","setPlayingSegment","useState","isPlaying","setIsPlaying","audioRef","useRef","endTimeListenerRef","turnRefs","containerRef","lastAutoScrolledIndexRef","useExternalPlaybackControl","hasExternalPlaybackState","container","activeNode","containerRect","activeRect","topPadding","isFullyVisible","activeTopInContainer","handlePlayPause","index","previousSegment","playSegment","checkEndTime","err","turn","isTurnPlaying","isTurnHighlighted","el","Pause","Play","Timeline","segments","durationSeconds","actorRows","currentTimeSeconds","onSeek","showControls","hasRecording","timelinePlaying","playbackRate","speedOptions","onTogglePlay","onSeekBack","onSeekForward","onSetPlaybackRate","totalDurationLabel","activeControl","setActiveControl","timer","timelineDuration","segment","clampedCurrent","playheadPercent","playheadLeft","formatTime","mins","secs","rows","useMemo","actors","actorColors","timeMarkers","interval","marker","handleSeekClick","event","rect","ratio","RotateCcw","RotateCw","speed","isActive","percentage","row","isSystem","idx","leftPercent","widthPercent","segmentDuration"],"mappings":"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"}
|