# All files / src/FileSelect/FileExplorer FileExplorerSidebar.tsx

60.41% Statements 29/48
25% Branches 4/16
50% Functions 6/12
57.14% Lines 24/42

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
    1124x

    4x

    4x

    4x
    40x
    40x
    40x
    40x

    40x
    40x
    40x

    40x
    35x

    40x

    40x
    8x

    40x
    8x

    40x
    16x

    40x

    40x

    35x

    35x

     import React from 'react'
    import { FileExplorerSidebarProps } from './FileExplorer.types'
    import {
      StyledNavigation,
      StyledSidebar,
      StyledSourceItem,
    } from './FileExplorerSidebar.styles'
    import { useSidebarNavigation } from './useSidebarNavigation'

    export function FileExplorerSidebar({
      value: selectedSource,
      onChange,
      sources,
      isOpen,
    }: FileExplorerSidebarProps) {
      const [isNavFocused, setIsNavFocused] = React.useState(false)
      const [isFocusVisible, setIsFocusVisible] = React.useState(true)
      const focusedSourceRef = React.useRef<HTMLDivElement>(null)

      const selectedSourceIndex = sources.findIndex(
        ({ sourceId }) => sourceId === selectedSource
      )

      const sidebarNavigation = useSidebarNavigation({
        initialIndex: selectedSourceIndex,
        size: sources.length,
        selectedIndex: selectedSourceIndex,
      })

      React.useEffect(() => {
        sidebarNavigation.set(selectedSourceIndex)
      }, [selectedSourceIndex])

      React.useEffect(() => {
        Iif (focusedSourceRef.current && isOpen) {
          focusedSourceRef.current.focus()
        }
      }, [sidebarNavigation.index, isOpen])

      React.useEffect(() => {
        sidebarNavigation.setSize(sources.length)
      }, [sources.length])

      const onKeyDown = (e: React.KeyboardEvent) => {
        Iif (!isNavFocused) return

        switch (e.nativeEvent.key) {
          case 'Enter':
            e.preventDefault()
            onChange(sources[sidebarNavigation.index].sourceId)
            break

          case 'ArrowUp':
          case 'Up':
            e.preventDefault()

            sidebarNavigation.up()
            break

          case 'ArrowDown':
          case 'Down':
            e.preventDefault()
            sidebarNavigation.down()
            break
        }
      }

      return (
        <StyledSidebar>
          <StyledNavigation>
            {sources.map((source, idx) => {
              const isFocused = idx === sidebarNavigation.index

              return (
                <StyledSourceItem
                  key={source.sourceId}
                  loading={source.isUploading}
                  error={source.hasError}
                  icon={source.icon}
                  selected={selectedSource === source.sourceId}
                  focused={isNavFocused && isFocusVisible && isFocused}
                  tabIndex={isFocused ? 0 : -1}
                  ref={isFocused ? focusedSourceRef : null}
                  onMouseDown={() => {
                    // prevent focus blink on the latest focused item
                    setIsFocusVisible(false)
                  }}
                  onMouseUp={() => {
                    setIsFocusVisible(true)
                  }}
                  count={source.value.length}
                  onFocus={() => {
                    setIsNavFocused(true)
                  }}
                  onBlur={() => {
                    setIsNavFocused(false)
                  }}
                  onKeyDown={onKeyDown}
                  onClick={() => {
                    sidebarNavigation.set(idx)
                    onChange(source.sourceId)
                  }}
                >
                  {source.title}
                </StyledSourceItem>
              )
            })}
          </StyledNavigation>
        </StyledSidebar>
      )
    }