chordia-ui 3.3.8 → 3.3.9
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/AgentLiftCard.cjs.js.map +1 -1
- package/dist/AgentLiftCard.es.js +5 -3
- package/dist/AgentLiftCard.es.js.map +1 -1
- package/dist/CustomFilterChips.cjs.js.map +1 -1
- package/dist/CustomFilterChips.es.js +2 -1
- package/dist/CustomFilterChips.es.js.map +1 -1
- package/dist/FileUploadingState.cjs.js.map +1 -1
- package/dist/FileUploadingState.es.js +16 -10
- package/dist/FileUploadingState.es.js.map +1 -1
- package/dist/IntegrationCard.cjs.js.map +1 -1
- package/dist/IntegrationCard.es.js +3 -3
- package/dist/IntegrationCard.es.js.map +1 -1
- package/dist/SectionLabel.cjs.js.map +1 -1
- package/dist/SectionLabel.es.js.map +1 -1
- package/dist/SmallButton.cjs.js.map +1 -1
- package/dist/SmallButton.es.js +16 -16
- package/dist/SmallButton.es.js.map +1 -1
- package/dist/SummarySection.cjs.js.map +1 -1
- package/dist/SummarySection.es.js +11 -9
- package/dist/SummarySection.es.js.map +1 -1
- package/dist/TextInput.cjs.js.map +1 -1
- package/dist/TextInput.es.js.map +1 -1
- package/dist/Timeline.cjs.js.map +1 -1
- package/dist/Timeline.es.js +14 -8
- package/dist/Timeline.es.js.map +1 -1
- package/dist/Tooltip.cjs.js +1 -1
- package/dist/Tooltip.cjs.js.map +1 -1
- package/dist/Tooltip.es.js +31 -20
- package/dist/Tooltip.es.js.map +1 -1
- package/dist/TourGuideTooltip.cjs.js.map +1 -1
- package/dist/TourGuideTooltip.es.js +2 -1
- package/dist/TourGuideTooltip.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 +79 -97
- package/dist/UpdatedInteractionRecording.es.js.map +1 -1
- package/dist/UploadInteraction.cjs.js.map +1 -1
- package/dist/UploadInteraction.es.js.map +1 -1
- package/dist/colors.cjs.js +2 -0
- package/dist/colors.cjs.js.map +1 -0
- package/dist/colors.es.js +2 -0
- package/dist/colors.es.js.map +1 -0
- package/dist/components/UpdatedInteractionDetails.cjs.js +10 -1
- package/dist/components/UpdatedInteractionDetails.cjs.js.map +1 -1
- package/dist/components/UpdatedInteractionDetails.es.js +1531 -9
- package/dist/components/UpdatedInteractionDetails.es.js.map +1 -1
- package/dist/components/chat.cjs.js +30 -1
- package/dist/components/chat.cjs.js.map +1 -1
- package/dist/components/chat.es.js +2222 -7
- package/dist/components/chat.es.js.map +1 -1
- package/dist/components/common.cjs.js +1 -1
- package/dist/components/common.es.js +32 -25
- package/dist/components/common.es.js.map +1 -1
- package/dist/components/data.cjs.js +1 -1
- package/dist/components/data.cjs.js.map +1 -1
- package/dist/components/data.es.js +1033 -4
- package/dist/components/data.es.js.map +1 -1
- package/dist/components/layout.cjs.js +3 -1
- package/dist/components/layout.cjs.js.map +1 -1
- package/dist/components/layout.es.js +1533 -8
- package/dist/components/layout.es.js.map +1 -1
- package/dist/components/login.cjs.js +1 -1
- package/dist/components/login.es.js +6 -2
- package/dist/components/login.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 +220 -6
- package/dist/components/media.es.js.map +1 -1
- package/dist/components/models.cjs.js +1 -1
- package/dist/components/models.cjs.js.map +1 -1
- package/dist/components/models.es.js +91 -2
- package/dist/components/models.es.js.map +1 -1
- package/dist/components/navigation.cjs.js +1 -1
- package/dist/components/navigation.cjs.js.map +1 -1
- package/dist/components/navigation.es.js +766 -7
- package/dist/components/navigation.es.js.map +1 -1
- package/dist/components/notifications.cjs.js +1 -1
- package/dist/components/notifications.cjs.js.map +1 -1
- package/dist/components/notifications.es.js +368 -3
- package/dist/components/notifications.es.js.map +1 -1
- package/dist/components/onboarding.cjs.js +1 -1
- package/dist/components/onboarding.cjs.js.map +1 -1
- package/dist/components/onboarding.es.js +985 -7
- package/dist/components/onboarding.es.js.map +1 -1
- package/dist/components/primitives.cjs.js +1 -1
- package/dist/components/primitives.cjs.js.map +1 -1
- package/dist/components/primitives.es.js +635 -25
- package/dist/components/primitives.es.js.map +1 -1
- package/dist/debugger-wc.cjs.js +4 -4
- package/dist/debugger-wc.cjs.js.map +1 -1
- package/dist/debugger-wc.es.js +15 -11
- package/dist/debugger-wc.es.js.map +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs2.js +2 -49
- package/dist/index.cjs2.js.map +1 -1
- package/dist/index.cjs3.js +50 -0
- package/dist/index.cjs3.js.map +1 -0
- package/dist/index.es.js +104 -99
- package/dist/index.es.js.map +1 -1
- package/dist/index.es2.js +2632 -1776
- package/dist/index.es2.js.map +1 -1
- package/dist/index.es3.js +1944 -0
- package/dist/index.es3.js.map +1 -0
- package/dist/pages/interactionDetails.cjs.js +1 -1
- package/dist/pages/interactionDetails.cjs.js.map +1 -1
- package/dist/pages/interactionDetails.es.js +70 -47
- package/dist/pages/interactionDetails.es.js.map +1 -1
- package/dist/sortable.esm.cjs.js +1 -1
- package/dist/sortable.esm.cjs.js.map +1 -1
- package/dist/sortable.esm.es.js +55 -53
- package/dist/sortable.esm.es.js.map +1 -1
- package/dist/{chordia-ui.css → style.css} +1 -1
- package/package.json +1 -1
- package/src/components/UpdatedInteractionDetails/UpdatedInteractionDetails.jsx +318 -77
- package/src/components/UpdatedInteractionDetails/UpdatedInteractionRecording.jsx +7 -17
- package/dist/ChartRenderer.cjs.js +0 -31
- package/dist/ChartRenderer.cjs.js.map +0 -1
- package/dist/ChartRenderer.es.js +0 -2210
- package/dist/ChartRenderer.es.js.map +0 -1
- package/dist/GettingStarted.cjs.js +0 -2
- package/dist/GettingStarted.cjs.js.map +0 -1
- package/dist/GettingStarted.es.js +0 -983
- package/dist/GettingStarted.es.js.map +0 -1
- package/dist/InlineConfirm.cjs.js +0 -2
- package/dist/InlineConfirm.cjs.js.map +0 -1
- package/dist/InlineConfirm.es.js +0 -618
- package/dist/InlineConfirm.es.js.map +0 -1
- package/dist/InteractionSummaryCard.cjs.js +0 -2
- package/dist/InteractionSummaryCard.cjs.js.map +0 -1
- package/dist/InteractionSummaryCard.es.js +0 -216
- package/dist/InteractionSummaryCard.es.js.map +0 -1
- package/dist/LoginPage.cjs.js +0 -3
- package/dist/LoginPage.cjs.js.map +0 -1
- package/dist/LoginPage.es.js +0 -2618
- package/dist/LoginPage.es.js.map +0 -1
- package/dist/NavigationBar.cjs.js +0 -2
- package/dist/NavigationBar.cjs.js.map +0 -1
- package/dist/NavigationBar.es.js +0 -762
- package/dist/NavigationBar.es.js.map +0 -1
- package/dist/NotificationPanel.cjs.js +0 -2
- package/dist/NotificationPanel.cjs.js.map +0 -1
- package/dist/NotificationPanel.es.js +0 -371
- package/dist/NotificationPanel.es.js.map +0 -1
- package/dist/OverlayPanel.cjs.js +0 -2
- package/dist/OverlayPanel.cjs.js.map +0 -1
- package/dist/OverlayPanel.es.js +0 -93
- package/dist/OverlayPanel.es.js.map +0 -1
- package/dist/SplitPane.cjs.js +0 -4
- package/dist/SplitPane.cjs.js.map +0 -1
- package/dist/SplitPane.es.js +0 -1531
- package/dist/SplitPane.es.js.map +0 -1
- package/dist/SummaryStatsPanel.cjs.js +0 -2
- package/dist/SummaryStatsPanel.cjs.js.map +0 -1
- package/dist/SummaryStatsPanel.es.js +0 -1027
- package/dist/SummaryStatsPanel.es.js.map +0 -1
- package/dist/UpdatedInteractionDetails.cjs.js +0 -11
- package/dist/UpdatedInteractionDetails.cjs.js.map +0 -1
- package/dist/UpdatedInteractionDetails.es.js +0 -1310
- package/dist/UpdatedInteractionDetails.es.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextInput.cjs.js","sources":["../src/components/primitives/TextInput.jsx"],"sourcesContent":["\"use client\";\nimport React from 'react';\n\nconst baseStyle = {\n width: '100%',\n padding: 'var(--spacing-2)',\n fontSize: 'var(--text-md)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius)',\n backgroundColor: 'var(--paper)',\n color: 'var(--text-base)',\n fontFamily: 'var(--font-sans)',\n outline: 'none',\n transition: 'border-color 0.15s ease',\n};\n\nexport default function TextInput({\n value,\n onChange,\n placeholder,\n disabled = false,\n mono = false,\n autoFocus = false,\n style,\n ...rest\n}) {\n return (\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange?.(e.target.value)}\n placeholder={placeholder}\n disabled={disabled}\n autoFocus={autoFocus}\n style={{\n ...baseStyle,\n ...(mono ? { fontFamily: 'var(--font-mono)' } : {}),\n ...(disabled ? { opacity: 0.6, cursor: 'not-allowed' } : {}),\n ...style,\n }}\n onFocus={(e) => { e.currentTarget.style.borderColor = 'var(--border-hover)'; }}\n onBlur={(e) => { e.currentTarget.style.borderColor = 'var(--border)'; }}\n {...rest}\n />\n );\n}\n"],"names":["baseStyle","TextInput","value","onChange","placeholder","disabled","mono","autoFocus","style","rest","jsx","e"],"mappings":"mEAGA,MAAMA,EAAY,CAChB,MAAO,OACP,QAAS,mBACT,SAAU,iBACV,OAAQ,0BACR,aAAc,gBACd,gBAAiB,eACjB,MAAO,mBACP,WAAY,mBACZ,QAAS,OACT,WAAY,yBACd,EAEA,SAAwBC,EAAU,CAChC,MAAAC,EACA,SAAAC,EACA,YAAAC,EACA,SAAAC,EAAW,GACX,KAAAC,EAAO,GACP,UAAAC,EAAY,GACZ,MAAAC,EACA,GAAGC,CACL,EAAG,
|
|
1
|
+
{"version":3,"file":"TextInput.cjs.js","sources":["../src/components/primitives/TextInput.jsx"],"sourcesContent":["\"use client\";\nimport React from 'react';\n\nconst baseStyle = {\n width: '100%',\n padding: 'var(--spacing-2)',\n fontSize: 'var(--text-md)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius)',\n backgroundColor: 'var(--paper)',\n color: 'var(--text-base)',\n fontFamily: 'var(--font-sans)',\n outline: 'none',\n transition: 'border-color 0.15s ease',\n};\n\nexport default function TextInput({\n value,\n onChange,\n placeholder,\n disabled = false,\n mono = false,\n autoFocus = false,\n style,\n ...rest\n}) {\n return (\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange?.(e.target.value)}\n placeholder={placeholder}\n disabled={disabled}\n autoFocus={autoFocus}\n style={{\n ...baseStyle,\n ...(mono ? { fontFamily: 'var(--font-mono)' } : {}),\n ...(disabled ? { opacity: 0.6, cursor: 'not-allowed' } : {}),\n ...style,\n }}\n onFocus={(e) => { e.currentTarget.style.borderColor = 'var(--border-hover)'; }}\n onBlur={(e) => { e.currentTarget.style.borderColor = 'var(--border)'; }}\n {...rest}\n />\n );\n}\n"],"names":["baseStyle","TextInput","value","onChange","placeholder","disabled","mono","autoFocus","style","rest","jsx","e"],"mappings":"mEAGA,MAAMA,EAAY,CAChB,MAAO,OACP,QAAS,mBACT,SAAU,iBACV,OAAQ,0BACR,aAAc,gBACd,gBAAiB,eACjB,MAAO,mBACP,WAAY,mBACZ,QAAS,OACT,WAAY,yBACd,EAEA,SAAwBC,EAAU,CAChC,MAAAC,EACA,SAAAC,EACA,YAAAC,EACA,SAAAC,EAAW,GACX,KAAAC,EAAO,GACP,UAAAC,EAAY,GACZ,MAAAC,EACA,GAAGC,CACL,EAAG,CAEC,OAAAC,EAAA,IAAC,QAAA,CACC,KAAK,OACL,MAAAR,EACA,SAAWS,GAAMR,GAAA,YAAAA,EAAWQ,EAAE,OAAO,OACrC,YAAAP,EACA,SAAAC,EACA,UAAAE,EACA,MAAO,CACL,GAAGP,EACH,GAAIM,EAAO,CAAE,WAAY,oBAAuB,CAAC,EACjD,GAAID,EAAW,CAAE,QAAS,GAAK,OAAQ,aAAA,EAAkB,CAAC,EAC1D,GAAGG,CACL,EACA,QAAUG,GAAM,CAAIA,EAAA,cAAc,MAAM,YAAc,qBAAuB,EAC7E,OAASA,GAAM,CAAIA,EAAA,cAAc,MAAM,YAAc,eAAiB,EACrE,GAAGF,CAAA,CAAA,CAGV"}
|
package/dist/TextInput.es.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextInput.es.js","sources":["../src/components/primitives/TextInput.jsx"],"sourcesContent":["\"use client\";\nimport React from 'react';\n\nconst baseStyle = {\n width: '100%',\n padding: 'var(--spacing-2)',\n fontSize: 'var(--text-md)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius)',\n backgroundColor: 'var(--paper)',\n color: 'var(--text-base)',\n fontFamily: 'var(--font-sans)',\n outline: 'none',\n transition: 'border-color 0.15s ease',\n};\n\nexport default function TextInput({\n value,\n onChange,\n placeholder,\n disabled = false,\n mono = false,\n autoFocus = false,\n style,\n ...rest\n}) {\n return (\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange?.(e.target.value)}\n placeholder={placeholder}\n disabled={disabled}\n autoFocus={autoFocus}\n style={{\n ...baseStyle,\n ...(mono ? { fontFamily: 'var(--font-mono)' } : {}),\n ...(disabled ? { opacity: 0.6, cursor: 'not-allowed' } : {}),\n ...style,\n }}\n onFocus={(e) => { e.currentTarget.style.borderColor = 'var(--border-hover)'; }}\n onBlur={(e) => { e.currentTarget.style.borderColor = 'var(--border)'; }}\n {...rest}\n />\n );\n}\n"],"names":["baseStyle","TextInput","value","onChange","placeholder","disabled","mono","autoFocus","style","rest","jsx","e"],"mappings":";;AAGA,MAAMA,IAAY;AAAA,EAChB,OAAO;AAAA,EACP,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,YAAY;AACd;AAEA,SAAwBC,EAAU;AAAA,EAChC,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,aAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,MAAAC,IAAO;AAAA,EACP,WAAAC,IAAY;AAAA,EACZ,OAAAC;AAAA,EACA,GAAGC;AACL,GAAG;
|
|
1
|
+
{"version":3,"file":"TextInput.es.js","sources":["../src/components/primitives/TextInput.jsx"],"sourcesContent":["\"use client\";\nimport React from 'react';\n\nconst baseStyle = {\n width: '100%',\n padding: 'var(--spacing-2)',\n fontSize: 'var(--text-md)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius)',\n backgroundColor: 'var(--paper)',\n color: 'var(--text-base)',\n fontFamily: 'var(--font-sans)',\n outline: 'none',\n transition: 'border-color 0.15s ease',\n};\n\nexport default function TextInput({\n value,\n onChange,\n placeholder,\n disabled = false,\n mono = false,\n autoFocus = false,\n style,\n ...rest\n}) {\n return (\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange?.(e.target.value)}\n placeholder={placeholder}\n disabled={disabled}\n autoFocus={autoFocus}\n style={{\n ...baseStyle,\n ...(mono ? { fontFamily: 'var(--font-mono)' } : {}),\n ...(disabled ? { opacity: 0.6, cursor: 'not-allowed' } : {}),\n ...style,\n }}\n onFocus={(e) => { e.currentTarget.style.borderColor = 'var(--border-hover)'; }}\n onBlur={(e) => { e.currentTarget.style.borderColor = 'var(--border)'; }}\n {...rest}\n />\n );\n}\n"],"names":["baseStyle","TextInput","value","onChange","placeholder","disabled","mono","autoFocus","style","rest","jsx","e"],"mappings":";;AAGA,MAAMA,IAAY;AAAA,EAChB,OAAO;AAAA,EACP,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,YAAY;AACd;AAEA,SAAwBC,EAAU;AAAA,EAChC,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,aAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,MAAAC,IAAO;AAAA,EACP,WAAAC,IAAY;AAAA,EACZ,OAAAC;AAAA,EACA,GAAGC;AACL,GAAG;AAEC,SAAA,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,OAAAR;AAAA,MACA,UAAU,CAACS,MAAMR,KAAA,gBAAAA,EAAWQ,EAAE,OAAO;AAAA,MACrC,aAAAP;AAAA,MACA,UAAAC;AAAA,MACA,WAAAE;AAAA,MACA,OAAO;AAAA,QACL,GAAGP;AAAA,QACH,GAAIM,IAAO,EAAE,YAAY,uBAAuB,CAAC;AAAA,QACjD,GAAID,IAAW,EAAE,SAAS,KAAK,QAAQ,cAAA,IAAkB,CAAC;AAAA,QAC1D,GAAGG;AAAA,MACL;AAAA,MACA,SAAS,CAACG,MAAM;AAAI,QAAAA,EAAA,cAAc,MAAM,cAAc;AAAA,MAAuB;AAAA,MAC7E,QAAQ,CAACA,MAAM;AAAI,QAAAA,EAAA,cAAc,MAAM,cAAc;AAAA,MAAiB;AAAA,MACrE,GAAGF;AAAA,IAAA;AAAA,EAAA;AAGV;"}
|
package/dist/Timeline.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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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"}
|
|
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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"}
|
package/dist/Timeline.es.js
CHANGED
|
@@ -32,7 +32,8 @@ const P = {
|
|
|
32
32
|
}
|
|
33
33
|
}, j = "conversation-turn-keyframes";
|
|
34
34
|
function K() {
|
|
35
|
-
if (typeof document > "u" || document.getElementById(j))
|
|
35
|
+
if (typeof document > "u" || document.getElementById(j))
|
|
36
|
+
return;
|
|
36
37
|
const s = document.createElement("style");
|
|
37
38
|
s.id = j, s.textContent = `
|
|
38
39
|
@keyframes turn-playing-pulse {
|
|
@@ -330,9 +331,11 @@ function U({
|
|
|
330
331
|
}, [h]), A(() => () => {
|
|
331
332
|
n.current && (n.current.pause(), i.current && n.current.removeEventListener("timeupdate", i.current));
|
|
332
333
|
}, []), A(() => {
|
|
333
|
-
if (!B || f < 0)
|
|
334
|
+
if (!B || f < 0)
|
|
335
|
+
return;
|
|
334
336
|
const e = R.current, l = x.current[f];
|
|
335
|
-
if (!l || !e)
|
|
337
|
+
if (!l || !e)
|
|
338
|
+
return;
|
|
336
339
|
const d = e.getBoundingClientRect(), c = l.getBoundingClientRect(), v = 12, m = c.top >= d.top + v && c.bottom <= d.bottom - 8;
|
|
337
340
|
if (!(C.current === f) || !m) {
|
|
338
341
|
const M = c.top - d.top + e.scrollTop;
|
|
@@ -483,7 +486,8 @@ function tt({
|
|
|
483
486
|
}) {
|
|
484
487
|
const [w, k] = H(null);
|
|
485
488
|
A(() => {
|
|
486
|
-
if (!w)
|
|
489
|
+
if (!w)
|
|
490
|
+
return;
|
|
487
491
|
const r = setTimeout(() => k(null), 220);
|
|
488
492
|
return () => clearTimeout(r);
|
|
489
493
|
}, [w]);
|
|
@@ -512,9 +516,11 @@ function tt({
|
|
|
512
516
|
m.push(r);
|
|
513
517
|
(!m.length || m[m.length - 1] < o) && m.push(o);
|
|
514
518
|
const M = (r) => {
|
|
515
|
-
if (!b)
|
|
519
|
+
if (!b)
|
|
520
|
+
return;
|
|
516
521
|
const p = r.currentTarget.getBoundingClientRect();
|
|
517
|
-
if (!p.width)
|
|
522
|
+
if (!p.width)
|
|
523
|
+
return;
|
|
518
524
|
const a = Math.max(0, Math.min((r.clientX - p.left) / p.width, 1));
|
|
519
525
|
b(a * o);
|
|
520
526
|
};
|
|
@@ -820,7 +826,7 @@ function tt({
|
|
|
820
826
|
}
|
|
821
827
|
export {
|
|
822
828
|
O as C,
|
|
823
|
-
|
|
824
|
-
|
|
829
|
+
U as T,
|
|
830
|
+
tt as a
|
|
825
831
|
};
|
|
826
832
|
//# sourceMappingURL=Timeline.es.js.map
|