import figures from 'figures';
import * as React from 'react';
import { useContext } from 'react';
import { useQueuedMessage } from '../../context/QueuedMessageContext.js';
import { Box, Text } from '@anthropic/ink';
import { formatBriefTimestamp } from '../../utils/formatBriefTimestamp.js';
import { findThinkingTriggerPositions, getRainbowColor, isUltrathinkEnabled } from '../../utils/thinking.js';
import { MessageActionsSelectedContext } from '../messageActions.js';
type Props = {
text: string;
useBriefLayout?: boolean;
timestamp?: string;
};
export function HighlightedThinkingText({ text, useBriefLayout, timestamp }: Props): React.ReactNode {
// Brief/assistant mode: chat-style "You" label instead of the ❯ highlight.
// Parent drops its backgroundColor when this is true, so no grey shows
// through. No manual wrap needed — Ink wraps inside the parent Box.
const isQueued = useQueuedMessage()?.isQueued ?? false;
const isSelected = useContext(MessageActionsSelectedContext);
const pointerColor = isSelected ? 'suggestion' : 'subtle';
if (useBriefLayout) {
const ts = timestamp ? formatBriefTimestamp(timestamp) : '';
return (
You
{ts ? {ts} : null}
{text}
);
}
const triggers = isUltrathinkEnabled() ? findThinkingTriggerPositions(text) : [];
if (triggers.length === 0) {
return (
{figures.pointer}
{text}
);
}
// Static rainbow (no shimmer — transcript messages don't animate)
const parts: React.ReactNode[] = [];
let cursor = 0;
for (const t of triggers) {
if (t.start > cursor) {
parts.push(
{text.slice(cursor, t.start)}
,
);
}
for (let i = t.start; i < t.end; i++) {
parts.push(
{text[i]}
,
);
}
cursor = t.end;
}
if (cursor < text.length) {
parts.push(
{text.slice(cursor)}
,
);
}
return (
{figures.pointer}
{parts}
);
}