# All files / src/ThumbnailGrid ThumbnailGrid.hooks.ts

100% Statements 70/70
100% Branches 16/16
100% Functions 14/14
100% Lines 62/62

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    1245x

    5x
    23x

    23x
    23x
    23x

    23x
    4x

    23x
    5x

    23x

    23x
    5x

    5x
    5x
    9x

    5x

    5x
    2x

    3x
    3x
    8x

    3x

    3x

    5x

    5x

    5x

    23x
    5x

    5x
    5x
    10x

    5x
    5x

    5x
    2x

    2x

    3x
    3x
    5x

    3x

    3x

    5x

    5x

    5x

    23x
    4x
    1x

    3x

    3x

    3x
    3x

    3x

    23x
    3x
    1x

    2x

    2x

    2x
    2x

    2x

    23x

     import React from 'react'

    export const useGridNavigation = ({
      indicesRows: initialIndicesRows,
    }: {
      indicesRows: number[][]
    }) => {
      const [index, setIndex] = React.useState(0)
      const [indicesRows, setIndicesRows] = React.useState(initialIndicesRows)
      const [gridSize, setGridSize] = React.useState(0)

      React.useEffect(() => {
        setGridSize(indicesRows.flat().length)
      }, [indicesRows])

      React.useEffect(() => {
        setIndex((prev) => (prev < gridSize ? prev : 0))
      }, [gridSize])

      const finalIndex = gridSize - 1

      const up = (e: React.KeyboardEvent) => {
        e.preventDefault()

        const getNextIndex = () => {
          const rowIndex = indicesRows.findIndex((rowCells) =>
            rowCells.includes(index)
          )
          const nextRowIndex = rowIndex - 1

          if (nextRowIndex < 0) {
            return indicesRows[rowIndex][0]
          }

          const nextRow = indicesRows[nextRowIndex]
          const nextCellIndex = indicesRows[rowIndex].findIndex(
            (navigationIndex) => navigationIndex === index
          )
          const nextNavigationIndex = nextRow[nextCellIndex]

          return nextNavigationIndex ?? nextRow[nextRow.length - 1]
        }

        const nextIndex = getNextIndex()

        setIndex(nextIndex)

        return nextIndex
      }

      const down = (e: React.KeyboardEvent) => {
        e.preventDefault()

        const getNextIndex = () => {
          const rowIndex = indicesRows.findIndex((rowCells) =>
            rowCells.includes(index)
          )
          const nextRowIndex = rowIndex + 1
          const finalRowIndex = indicesRows.length - 1

          if (nextRowIndex > finalRowIndex) {
            const row = indicesRows[rowIndex]

            return row[row.length - 1]
          }

          const nextRow = indicesRows[nextRowIndex]
          const nextCellIndex = indicesRows[rowIndex].findIndex(
            (navigationIndex) => navigationIndex === index
          )
          const nextNavigationIndex = nextRow[nextCellIndex]

          return nextNavigationIndex ?? nextRow[nextRow.length - 1]
        }
        const nextIndex = getNextIndex()

        setIndex(nextIndex)

        return nextIndex
      }

      const right = (e: React.KeyboardEvent) => {
        if (index === finalIndex) {
          return index
        }

        e.preventDefault()

        const nextIndex = index + 1

        if (nextIndex <= finalIndex) {
          setIndex(nextIndex)
        }

        return nextIndex
      }

      const left = (e: React.KeyboardEvent) => {
        if (index === 0) {
          return index
        }

        e.preventDefault()

        const nextIndex = index - 1

        if (nextIndex >= 0) {
          setIndex(nextIndex)
        }

        return nextIndex
      }

      return {
        index,
        setIndex,
        setIndicesRows,
        up,
        down,
        left,
        right,
      }
    }