Spaces:
Sleeping
Sleeping
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<HighlightedTextState> { | |
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 <> | |
<div className="status-bar" key="status-bar"> | |
<span className={this.state.isFrozen ? "" : " d-none"} key="lock-icon"><i className="fa fa-lock"></i> </span> | |
<strong key="target-label">target:</strong> | |
{ | |
this.state.activeIndex != null | |
? <span className="token" key="target">{tokens[this.state.activeIndex]}</span> | |
: <></> | |
} | |
</div> | |
<div className={className} onClick={onClick} key="text"> | |
{ | |
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 <span key={i} className={className} style={style} | |
onMouseOver={onMouseOver} onClick={onClick}>{t}</span>; | |
}) | |
} | |
</div> | |
</>; | |
} | |
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); | |