);
}
+class PlayerWordsRow extends React.Component {
+ constructor(props) {
+ super(props);
+ this._ref = React.createRef();
+ this._observer = null;
+ }
+
+ componentDidMount() {
+ this._updateSpacers();
+ this._observer = new ResizeObserver(() => this._updateSpacers());
+ if (this._ref.current) {
+ this._observer.observe(this._ref.current);
+ }
+ }
+
+ componentDidUpdate() {
+ this._updateSpacers();
+ }
+
+ componentWillUnmount() {
+ if (this._observer) this._observer.disconnect();
+ }
+
+ _updateSpacers() {
+ const el = this._ref.current;
+ if (!el) return;
+ const spacers = el.querySelectorAll(".word-spacer");
+ for (const spacer of spacers) {
+ /* Temporarily unwrap to measure natural position. */
+ spacer.classList.remove("wrapped");
+ }
+ let prevTop = null;
+ for (const child of el.children) {
+ const top = child.offsetTop;
+ if (child.classList.contains("word-spacer")) {
+ if (prevTop !== null && top > prevTop) {
+ child.classList.add("wrapped");
+ }
+ }
+ prevTop = top;
+ }
+ }
+
+ render() {
+ const { words, stealable, onSteal } = this.props;
+ const items = [];
+ words.forEach((w, i) => {
+ if (i > 0) {
+ items.push(<div key={"sp-" + w.id} className="word-spacer" />);
+ }
+ items.push(
+ <WordDisplay key={w.id} word={w}
+ stealable={stealable}
+ onSteal={stealable ? () => onSteal(w) : null}
+ />
+ );
+ });
+
+ return (
+ <div className="player-words-row" ref={this._ref}>
+ {items}
+ </div>
+ );
+ }
+}
+
function VoteModal(props) {
const { word, player_name, my_session, submitter_session,
votes_cast, voters_total, onVote } = props;
{pw.words.length === 0 ? (
<span className="status">No words yet</span>
) : (
- <div className="player-words-row">
- {pw.words.map(w =>
- <WordDisplay key={w.id}
- word={w}
- stealable={claim_active}
- onSteal={claim_active
- ? () => this.steal_word(sid, w) : null}
- />
- )}
- </div>
+ <PlayerWordsRow
+ words={pw.words}
+ stealable={claim_active}
+ onSteal={(w) => this.steal_word(sid, w)}
+ />
)}
</div>
);
{sorted.map(entry => (
<div key={entry.name + "-words"} className="player-word-section">
<h3>{entry.name}</h3>
- <div className="player-words-row">
- {entry.words.map((w, i) =>
- <span key={i} className="word-display">
- {w.split("").map((ch, j) => (
- <Tile key={j} letter={ch} />
- ))}
- </span>
- )}
- </div>
+ <PlayerWordsRow
+ words={entry.words.map((w, i) => ({ id: i, word: w }))}
+ stealable={false}
+ onSteal={null}
+ />
</div>
))}
</div>