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

Code before:
      {
        tags.map(({ name, color, label }) => {
          const style = stylesheet({
            tag: {
              background: cssVar(color),
              color: getContrast(color),
            },
            activeTag: {
              border: border(2, cssVar('$themePrimary')),
              borderRadius: 6
            }
          })
          return (
            <div key={name} data-test={name} className={clas(css.tagWrapper, activeTag === name ? style.activeTag : '')}>
              <div className={clas(css.tag, style.tag, 'wave-s12')} onClick={activateTag(name)}>{label}</div>
            </div>
          )
        })
      }
    </div>
  ),
  XTextAnnotator = ({ model: { name, title, tags, items, trigger, readonly, smart_selection = true } }: { model: TextAnnotator }) => {
    const
      [activeTag, setActiveTag] = React.useState<S | undefined>(readonly ? undefined : tags[0]?.name),
      [hoveredTagIdx, setHoveredTagIdx] = React.useState<U | null>(),
      tagColorMap = tags.reduce((map, t) => {
        map.set(t.name, t.color)
        return map
      }, new Map<S, S>()),
      [tokens, setTokens] = React.useState(items.reduce((arr, { text, tag }) => {
        // If the smart_selection is True, split by any non-letter character.
        text.split(smart_selection ? /(?=[^a-z0-9])/ig : "").forEach((textItem) => {
          const
            start = arr.length === 0 ? 0 : arr[arr.length - 1].end + 1,
            end = arr.length === 0 ? textItem.length - 1 : arr[arr.length - 1].end + textItem.length
          if (/[^a-z]/i.test(textItem)) {
            arr.push({ text: textItem.substring(0, 1), tag, start, end: start })
            if (textItem.substring(1) !== '') arr.push({ text: textItem.substring(1), tag, start: start + 1, end: end + 1 })
          } else {
            arr.push({ text: textItem, tag, start, end })
          }
        })
        return arr
      }, [] as (TextAnnotatorItem & { start: number, end: number })[])),
      submitWaveArgs = () => {
        let currentText = ''
        let currentTag: S | undefined
        wave.args[name] = tokens.reduce((arr, { text, tag }, idx, tokens) => {
          if (idx === tokens.length - 1) {
            if (tag !== currentTag) {
              arr.push({ text: currentText, tag: currentTag })

Review comment (suggestion):
Let's use map instead of reduce: `tagColorMap = new Map(tags.map(t => [t.name, t.color]))` - more elegant.

Code after:
      top: -3,
      background: cssVar('$card'),
    },
    readonly: { pointerEvents: 'none' }
  }),
  annotateNumbersAroundToken = (tokenIdx: U, tokens: TokenProps[], activeTag?: S) => {
    let charRightIdx = tokenIdx + 1, charLeftIdx = tokenIdx - 1
    while (charRightIdx <= tokens.length - 1 && !isNaN(+tokens[charRightIdx].text)) {
      tokens[charRightIdx].tag = activeTag
      charRightIdx++
    }
    while (charLeftIdx >= 0 && !isNaN(+tokens[charLeftIdx].text)) {
      tokens[charLeftIdx].tag = activeTag
      charLeftIdx--
    }
  }

export
  const AnnotatorTags = ({ tags, activateTag, activeTag }: AnnotatorTagsProps) => (
    <div className={css.tags}>
      {
        tags.map(({ name, color, label }) => {
          const style = stylesheet({
            tag: {
              background: cssVar(color),
              color: getContrast(color),
            },
            activeTag: {
              border: border(2, cssVar('$themePrimary')),
              borderRadius: 6
            }
          })
          return (
            <div key={name} data-test={name} className={clas(css.tagWrapper, activeTag === name ? style.activeTag : '')}>
              <div className={clas(css.tag, style.tag, 'wave-s12')} onClick={activateTag(name)}>{label}</div>
            </div>
          )
        })
      }
    </div>
  ),
  XTextAnnotator = ({ model: { name, title, tags, items, trigger, readonly } }: { model: TextAnnotator }) => {
    const
      [activeTag, setActiveTag] = React.useState<S | undefined>(readonly ? undefined : tags[0]?.name),
      [hoveredTagIdx, setHoveredTagIdx] = React.useState<U | null>(),
      [smartSelection, setSmartSelection] = React.useState(true),
      startElPropsRef = React.useRef<TokenMouseEventProps>(),
      tagColorMap = new Map(tags.map(t => [t.name, t.color])),
      [tokens, setTokens] = React.useState(items.reduce((tokenArr, { text, tag }) => {
        // Split by any non-letter.
        text.split(/([^a-z])/ig).filter(word => word !== '').forEach(textItem => {