<commit_before>import { select } from 'd3-selection'
import './crosshairs.css'

export function createCrosshairs () {
  let vertical = true
  let horizontal = true
  let highlightedRow
  let highlightedColum

  function crosshairs (s) {
    s.each(crosshairsEach)
  }

  crosshairs.vertical = function (value) {
    if (!arguments.length) return vertical
    vertical = value
    return crosshairs
  }

  crosshairs.horizontal = function (value) {
    if (!arguments.length) return horizontal
    horizontal = value
    return crosshairs
  }

  return crosshairs

  function crosshairsEach ({ rows, dispatcher }, i) {
    const target = select(this)

    updateHeaders()

    dispatcher
          .on('cell-enter.crosshairs-column', vertical ? setColumnListeners : null)
          .on('cell-update.crosshairs-column', vertical ? updateColumnHighlight : null)
          .on('cell-exit.crosshairs-column', vertical ? clearColumnListeners : null)
          .on('row-enter.crosshairs-row', horizontal ? setRowListeners : null)
          .on('row-update.crosshairs-row', horizontal ? updateRowHighlight : null)
          .on('row-exit.crosshairs-row', horizontal ? clearRowListeners : null)

    function updateHeaders () {
      target.selectAll('.zambezi-grid-headers .zambezi-grid-header')
            .on('mouseover.crosshairs-column', vertical ? column => onColumnHover({ column }) : null)
            .each(updateHeaderHighlight)
    }

    function onRowHover ({ row }) {
      highlightedRow = row
      target.selectAll('.zambezi-grid-row')
          .each(updateRowHighlight)
    }

    function onColumnHover ({ column }) {
      highlightedColum = column
      target.selectAll('.zambezi-grid-cell')
          .each(updateColumnHighlight)

      updateHeaders()
    }

    function setRowListeners (d) {
      select(this).on('mouseover.crosshairs-row', onRowHover)
    }

    function updateRowHighlight ({ row }) {
      select(this).classed('is-crosshairs-over', row === highlightedRow)
    }

    function updateColumnHighlight ({ column }) {
      select(this).classed('is-crosshairs-over', column === highlightedColum)
    }

    function setColumnListeners (d) {
      select(this).on('mouseover.crosshairs-row', onColumnHover)
    }

    function clearRowListeners (d) {
      select(this).on('mouseover.crosshairs-row', null)
    }

    function clearColumnListeners (d) {
      select(this).on('mouseover.crosshairs-row', null)
    }

    function updateHeaderHighlight (column) {
      select(this).classed('is-crosshairs-over', column === highlightedColum)
    }
  }
}
<commit_msg>remove crosshairs on mouse leave<commit_after>import { select } from 'd3-selection'
import './crosshairs.css'

export function createCrosshairs () {
  let vertical = true
  let horizontal = true
  let highlightedRow
  let highlightedColum

  function crosshairs (s) {
    s.each(crosshairsEach)
  }

  crosshairs.vertical = function (value) {
    if (!arguments.length) return vertical
    vertical = value
    return crosshairs
  }

  crosshairs.horizontal = function (value) {
    if (!arguments.length) return horizontal
    horizontal = value
    return crosshairs
  }

  return crosshairs

  function crosshairsEach ({ rows, dispatcher }, i) {
    const target = select(this)

    updateHeaders()

    dispatcher
          .on('cell-enter.crosshairs-column', vertical ? setColumnListeners : null)
          .on('cell-update.crosshairs-column', vertical ? updateColumnHighlight : null)
          .on('cell-exit.crosshairs-column', vertical ? clearColumnListeners : null)
          .on('row-enter.crosshairs-row', horizontal ? setRowListeners : null)
          .on('row-update.crosshairs-row', horizontal ? updateRowHighlight : null)
          .on('row-exit.crosshairs-row', horizontal ? clearRowListeners : null)

    target.on('mouseout', removeCrosshairs)

    function removeCrosshairs(){
      onColumnHover({ column: null })
      onRowHover({ row: null })
    }

    function updateHeaders () {
      target.selectAll('.zambezi-grid-headers .zambezi-grid-header')
            .on('mouseover.crosshairs-column', vertical ? column => onColumnHover({ column }) : null)
            .each(updateHeaderHighlight)
    }

    function onRowHover ({ row }) {
      highlightedRow = row
      target.selectAll('.zambezi-grid-row')
          .each(updateRowHighlight)
    }

    function onColumnHover ({ column }) {
      highlightedColum = column
      target.selectAll('.zambezi-grid-cell')
          .each(updateColumnHighlight)

      updateHeaders()
    }

    function setRowListeners (d) {
      select(this).on('mouseover.crosshairs-row', onRowHover)
    }

    function updateRowHighlight ({ row }) {
      select(this).classed('is-crosshairs-over', row === highlightedRow)
    }

    function updateColumnHighlight ({ column }) {
      select(this).classed('is-crosshairs-over', column === highlightedColum)
    }

    function setColumnListeners (d) {
      select(this).on('mouseover.crosshairs-row', onColumnHover)
    }

    function clearRowListeners (d) {
      select(this).on('mouseover.crosshairs-row', null)
    }

    function clearColumnListeners (d) {
      select(this).on('mouseover.crosshairs-row', null)
    }

    function updateHeaderHighlight (column) {
      select(this).classed('is-crosshairs-over', column === highlightedColum)
    }
  }
}

{'fraction_non_alphanumeric': 0.1190919240788984, 'fraction_numerical': 0.0003721622627465575, 'mean_word_length': 3.0627362055933482, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3990936', 'n_tokens_mistral': 1663, 'n_tokens_neox': 1577, 'n_words': 304}