All files / atom/table/src index.js

77.77% Statements 14/18
60% Branches 9/15
42.85% Functions 3/7
82.35% Lines 14/17

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 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152          1x                     3x 3x 3x 3x     3x       3x   3x                               6x                           6x 6x           6x                                                 1x   1x                                                                                                                      
import cx from 'classnames'
import PropTypes from 'prop-types'
 
import {BASE_CLASS, CELL_BASE_CLASS, ROW_BASE_CLASS, TABLE_CELL_PADDING, TABLE_CELL_TYPE} from './settings.js'
 
const AtomTable = ({
  head = [],
  body,
  rowClass,
  foot = [],
  fullWidth,
  cellPadding,
  borderBottom,
  onRowClick,
  zebraStriped
}) => {
  const hasHead = Boolean(head.length)
  const hasFoot = Boolean(foot.length)
  const isRowActionable = Boolean(onRowClick)
  const tableClass = cx(`${BASE_CLASS}`, {
    [`${BASE_CLASS}--fullWidth`]: Boolean(fullWidth)
  })
  const headerClass = cx(`${CELL_BASE_CLASS}`, `${BASE_CLASS}-headerCell`, {
    [`${CELL_BASE_CLASS}--${cellPadding}`]: Boolean(cellPadding)
  })
 
  const handleOnRowClick = index => onRowClick(index)
 
  return (
    <table className={tableClass}>
      {hasHead && (
        <thead>
          <tr>
            {head.map((element, index) => (
              <th key={index} className={headerClass}>
                {element}
              </th>
            ))}
          </tr>
        </thead>
      )}
 
      <tbody>
        {body.map((row, index) => (
          <tr
            key={index}
            className={cx(
              `${ROW_BASE_CLASS}`,
              {
                [`${ROW_BASE_CLASS}--actionable`]: isRowActionable,
                [`${ROW_BASE_CLASS}--zebraStriped`]: zebraStriped
              },
              typeof rowClass === 'function' && rowClass(row, index),
              typeof rowClass === 'string' && rowClass
            )}
            {...(isRowActionable && {onClick: () => handleOnRowClick(index)})}
          >
            {row.map((cell, index) => {
              const {type: Element = TABLE_CELL_TYPE.data, content = '', isNowrap, colspan = 1} = cell
              const cellClassName = cx(`${CELL_BASE_CLASS}`, {
                [`${CELL_BASE_CLASS}--noWrap`]: isNowrap,
                [`${CELL_BASE_CLASS}--${cellPadding}`]: Boolean(cellPadding),
                [`${CELL_BASE_CLASS}--borderBottom`]: Boolean(borderBottom)
              })
 
              return (
                <Element key={index} className={cellClassName} colSpan={colspan}>
                  {content}
                </Element>
              )
            })}
          </tr>
        ))}
      </tbody>
 
      {hasFoot && (
        <tfoot>
          <tr>
            {foot.map((element, index) => (
              <td key={index} className={`${CELL_BASE_CLASS}`}>
                {element}
              </td>
            ))}
          </tr>
        </tfoot>
      )}
    </table>
  )
}
 
AtomTable.displayName = 'AtomTable'
 
AtomTable.propTypes = {
  /**
   * Table head content
   */
  head: PropTypes.array,
  /**
   * Table body content.
   * You can define per row:
   *  - colspan: as a number
   *  - content: as a string or React component
   *  - type: of cell (th,td)
   *  - isNowrap: to add no-wrap behavior to the cell
   */
  body: PropTypes.arrayOf(
    PropTypes.arrayOf(
      PropTypes.shape({
        colspan: PropTypes.number,
        content: PropTypes.string.isRequired,
        type: PropTypes.oneOf(Object.values(TABLE_CELL_TYPE)),
        isNowrap: PropTypes.bool
      })
    )
  ).isRequired,
  /**
   * Specifies the class name(s) or a function to dynamically assign class names for a row.
   *
   * @typedef {(string|function)} rowClass
   * @property {string} [optional] Static class name(s) to be applied to the row.
   * @property {function} [optional] A function that returns a class name string, based on dynamic conditions.
   */
  rowClass: PropTypes.oneOf(PropTypes.string, PropTypes.func),
  /**
   * Cell padding size (xs,x,m,l,xl)
   */
  cellPadding: PropTypes.oneOf(Object.values(TABLE_CELL_PADDING)),
  /**
   * Table foot conntent
   */
  foot: PropTypes.array,
  /**
   * With fullWith you have a full width behavior
   */
  fullWidth: PropTypes.bool,
  /**
   * Add a default border bootom to all cells
   */
  borderBottom: PropTypes.bool,
  /**
   * Trigger callback with row index clicked
   */
  onRowClick: PropTypes.func,
  /**
   * Add interspersed stripes to rows
   */
  zebraStriped: PropTypes.bool
}
 
export {TABLE_CELL_TYPE as atomTableCellTypes, TABLE_CELL_PADDING as atomTableCellPadding}
export default AtomTable