# All files / react/SelectBox SelectBoxWithFixedOptions.jsx

77.27% Statements 17/22
60% Branches 6/10
83.33% Functions 5/6
77.27% Lines 17/22

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

    1x

    1x

    1x
    1x

    1x
    1x
    1x
    1x
    1x

    1x
    1x
    1x
    1x

    1x

    1x
    1x

    2x

     import { components } from 'react-select'
    import React from 'react'
    import groupBy from 'lodash/groupBy'

    import SelectBox from './SelectBox'
    import { silver } from '../../stylus/settings/palette.json'

    const optionPadding = 0.25

    const fixedOptionsStyle = {
      borderBottomLeftRadius: '4px',
      borderBottomRightRadius: '4px',
      paddingTop: optionPadding + 'rem',
      paddingBottom: optionPadding + 'rem',
      borderTop: `1px solid ${silver}`,
      background: 'white',
      position: 'relative'
    }

    const FixedOptions = props => (
      <div style={fixedOptionsStyle}>{props.children}</div>
    )

    /*
      This is the hacky part, where fixed options vnodes are manually spliced
      from the options vnodes. Fixed options vnodes are returned along with
      the menuUi where fixed vnodes have been removed.

      We rely on react-select internal structure `menu > scroll captor > menu list > options`.
      This code should be updated if react-select's internal structure changes.

      https://github.com/cozy/cozy-ui/pull/501
    */
    const extractFixed = children => {
      const newChildren = React.cloneElement(children)
      const menuList = newChildren.children ? newChildren.children[0] : null
      Eif (!menuList) {
        return { fixed: [], newChildren }
      }
      const options = menuList.children
      const { fixed, normal } = groupBy(
        options,
        vnode => (vnode.attributes.data.fixed === true ? 'fixed' : 'normal')
      )
      newChildren.children[0].children = normal
      return { fixed, newChildren }
    }

    const MenuWithFixedOptions = props => {
      const { children } = props
      const { fixed, newChildren: menuUi } = extractFixed(children)
      return (
        <div>
          <components.Menu {...props}>
            {menuUi}
            <FixedOptions>{fixed}</FixedOptions>
          </components.Menu>
        </div>
      )
    }

    const fixedMenuStyle = {
      zIndex: 10,
      overflow: 'hidden',
      // the space at the end is important otherwise the property gets autoprefixed (by what, I
      // don't know) and is no longer understood by the browser
      display: 'flex ',
      flexDirection: 'column'
    }

    const SelectBoxWithFixedOptions = props => (
      <SelectBox
        {...props}
        styles={{
          menu: base => ({
            ...base,
            ...fixedMenuStyle
          }),
          ...(props.styles || {})
        }}
        components={{
          Menu: MenuWithFixedOptions,
          ...(props.components || {})
        }}
      />
    )

    export default SelectBoxWithFixedOptions