import { StreamlitComponentBase, withStreamlitConnection, } from "streamlit-component-lib"; type HighlightedTextState = { activeIndex: number | null, hoverIndex: number | null, isFrozen: boolean }; /** * This is a React-based component template. The `render()` function is called * automatically when your component should be re-rendered. */ class HighlightedText extends StreamlitComponentBase { public state = {activeIndex: null, hoverIndex: null, isFrozen: false}; render() { const tokens: string[] = this.props.args["tokens"]; const scores: number[] = this.getScores(); console.log(scores); let className = "highlighted-text"; if (this.state.isFrozen) { className += " frozen"; } const onClick = () => { this.setState({ isFrozen: false }); }; return <>
target: { this.state.activeIndex != null ? {tokens[this.state.activeIndex]} : <> }
{ tokens.map((t: string, i: number) => { let className = "token"; if (this.state) { if (this.state.activeIndex == i) { className += " active"; } } const style = { backgroundColor: scores[i] > 0 ? `rgba(255, 32, 32, ${scores[i]})` : `rgba(32, 255, 32, ${-scores[i]})` }; const onMouseOver = () => { if (!this.state.isFrozen) { this.setState({ activeIndex: i }); } this.setState({ hoverIndex: i }); }; return {t}; }) }
; } private getScores() { const tokens = this.props.args["tokens"]; if (!this.state || this.state.activeIndex == null || this.state.activeIndex < 1) { return tokens.map(() => 0); } const allScores: number[][] = this.props.args["scores"]; const i = this.state.activeIndex - 1; const hi = Math.min(Math.max(0, i), allScores[i].length); const row = allScores[i].slice(0, hi); row.reverse(); let result = [ ...Array(Math.max(0, i - 1 - row.length)).fill(0), ...row.map((x) => x == undefined || isNaN(x) ? 0 : x) ]; result = [...result, ...Array(tokens.length - result.length).fill(0)]; return result; } } export default withStreamlitConnection(HighlightedText);