mebubo's picture
Working probs in UI
308bca9
import React, { useState, useEffect, useRef } from "react"
import { Replacement } from "../interfaces";
interface WordChipProps {
word: string;
logprob: number;
threshold: number;
replacements: Replacement[];
onReplace: (newWord: string) => Promise<void>;
}
export function WordChip({
word,
logprob,
threshold,
replacements,
onReplace
}: WordChipProps) {
const [isExpanded, setIsExpanded] = useState(false);
const [selectedIndex, setSelectedIndex] = useState(-1);
const dropdownRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
setIsExpanded(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, []);
const handleClick = () => {
if (logprob < threshold && replacements.length > 0) {
setIsExpanded(true);
}
}
const handleReplacement = async (newWord: string) => {
console.log("handleReplacement", newWord);
await onReplace(newWord);
setIsExpanded(false); // Close the dropdown
};
console.log(`word: ->${word}<-`);
let w1;
let w2;
let w3;
// if word contains a newline, render a <br />
if (word.includes("\n")) {
[w1, w3] = word.split("\n");
w2 = "\n";
console.log(`split: ${w1} | ${w2} | ${w3}`);
} else {
w1 = word;
w2 = "";
w3 = "";
}
// sort replacements by logprob (make sure not to mutate the original array)
const sortedReplacements = [...replacements].sort((a, b) => b.logprob - a.logprob)
// convert logprobs to probabilities
const withProbabilities = sortedReplacements.map(r => ({ ...r, probability: Math.exp(r.logprob)*100 }))
return (
<span
title={logprob.toFixed(2)}
className={`word-chip ${logprob < threshold ? "flagged" : ""}`}
style={{ position: "relative", cursor: logprob < threshold ? "pointer" : "default" }}
onClick={handleClick}
>
{w1}
{w2 && <br />}
{w3}
{isExpanded && (
<div
ref={dropdownRef}
style={{
position: "absolute",
top: "100%",
left: 0,
zIndex: 100,
maxHeight: "400px",
overflowY: "auto",
backgroundColor: "white",
border: "1px solid #ccc",
borderRadius: "4px",
boxShadow: "0 2px 4px rgba(0,0,0,0.1)"
}}
>
{withProbabilities.map((option, index) => (
<div
key={index}
onClick={() => handleReplacement(option.text)}
onMouseEnter={() => setSelectedIndex(index)}
style={{
padding: "5px 10px",
cursor: "pointer",
color: "black",
backgroundColor: selectedIndex === index ? "#f0f0f0" : "white",
whiteSpace: "nowrap"
}}
>
{option.text} <small style={{ fontSize: "0.7em", color: "#666" }}>{option.probability.toFixed(1)}%</small>
</div>
))}
</div>
)}
</span>
)
}