Repository: h2oai/wave
File: ui/src/text_annotator.tsx (TypeScript)

Code before:
      text = tokens.map((token, idx) => {
        return <Token
          key={idx}
          idx={idx}
          tokenProps={token}
          handleMouseDown={handleMouseDown}
          handleMouseUp={handleMouseUp}
          handleMouseLeave={handleMouseLeave}
          getMark={getMark}
          activeColor={activeTag ? tagColorMap.get(activeTag)! : undefined}
        />
      }, [] as React.ReactElement[])

    // eslint-disable-next-line react-hooks/exhaustive-deps
    React.useEffect(() => { wave.args[name] = items as unknown as Rec[] }, [])


    return (
      <div data-test={name} className={readonly ? css.readonly : ''}>
        <div className={clas('wave-s16 wave-w6', css.title)}>{title}</div>
        <AnnotatorTags tags={tags} activateTag={activateTag} activeTag={activeTag} />
        <Fluent.Toggle
          data-test={'toggle'}
          label={'Smart selection'}
          defaultChecked={smartSelection}
          onChange={() => setSmartSelection(!smartSelection)}
          onText="On"
          offText="Off"
          inlineLabel
        />
        <div className={clas(css.content, 'wave-s16 wave-t7 wave-w3')}>{text}</div>
      </div>
    )
  }

Review comment (suggestion):
Make sure to always get the most recent value.
```suggestion
          onChange={() => setSmartSelection(prevSelection => !prevSelection)}
```

Code after:
      handleMouseUp = (endElProps: TokenMouseEventProps) => () => annotate(endElProps),
      handleMouseLeave = (endElProps: TokenMouseEventProps) => (ev: React.MouseEvent<HTMLSpanElement>) => {
        const nodeName = (ev.relatedTarget as any)?.nodeName
        if (startElPropsRef.current !== undefined && nodeName !== 'P' && nodeName !== 'MARK') annotate(endElProps) // nodeName prop is not typed yet
      }

    // eslint-disable-next-line react-hooks/exhaustive-deps
    React.useEffect(() => { wave.args[name] = items as unknown as Rec[] }, [])

    return (
      <div data-test={name} className={readonly ? css.readonly : ''}>
        <div className={clas('wave-s16 wave-w6', css.title)}>{title}</div>
        <AnnotatorTags tags={tags} activateTag={activateTag} activeTag={activeTag} />
        <Fluent.Toggle
          data-test='smart-selection'
          label='Smart selection'
          defaultChecked={smartSelection}
          onChange={() => setSmartSelection(prevSelection => !prevSelection)}
          onText="On"
          offText="Off"
          inlineLabel
        />
        <div className={clas(css.content, 'wave-s16 wave-t7 wave-w3')}>{
          tokens.map(({ start, end, text, tag }, idx) => {
            const activeColor = activeTag ? tagColorMap.get(activeTag) : undefined
            return (
              // Use paragraph instead of span to support text highlight.
              <p
                key={idx}
                onMouseDown={handleMouseDown({ key: idx, start, end })}
                onMouseUp={handleMouseUp({ key: idx, start, end })}
                onMouseLeave={handleMouseLeave({ key: idx, start, end })}
                style={{ display: 'inline' }}
                className={activeColor ? style({ $nest: { '&::selection': { background: activeColor, color: getContrast(activeColor) } } }) : undefined}
              >
                {tag ? getMark(text, idx, tag) : text}
              </p>
            )
          })
        }</div>
      </div>
    )
  }