Start sharing components as a team!Share components as a team!Join Bit to build your applications faster.Get Started Free

table

v0.1.5arrow_drop_down
v0.1.5
v0.1.4
v0.1.3
v0.1.2
v0.1.0
STATUS
Passing
DOWNLOADS
53
LICENSE
MIT
VISIBILITY
Public
PUBLISHED
6 months ago
SIZE
31 KB
1 contributor
Use table in your project ?
Copied
npm i @bit/ans.base-ui.table
Set Bit as a scoped registryLearn more
npm config set '@bit:registry' https://node.bit.dev
Files
index.js
110 Lines(81 sloc)
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
import React, { useState, useEffect } from 'react'
import propTypes from 'prop-types'
import xor from 'lodash/xor'
import Checkbox from '@bit/ans.base-ui.checkbox'
import orderBy from 'lodash/orderBy'
import HeaderCell from './HeaderCell'
import BodyRow from './BodyRow'
import LoadingRow from './LoadingRow'
import tableStyles from './table.module.scss'

const Table = ({ columns, data, onSort, onSelect, sortable, loading, loadingBars, defaultSortIndex, ...otherProps }) => {
  const [sortBy, setSortBy] = useState(defaultSortIndex || columns[0].dataIndex)
  const [sortDirection, setSortDirection] = useState('asc')
  const [selectedItems, setSelected] = useState([])
  const sortedData = orderBy(data, sortBy, sortDirection)

  if (onSelect) {
    useEffect(() => {
      onSelect(selectedItems, data.filter(item => selectedItems.includes(item.key)))
    }, [selectedItems])
  }

  const handleTableHeaderClick = dataIndex => () => {
    const newSortDir = sortDirection === 'asc' ? 'desc' : 'asc'
    setSortBy(dataIndex)
    setSortDirection(newSortDir)
    if (onSort) {
      onSort(dataIndex, newSortDir)
    }
  }

  const handleSelectAll = e => {
    if (selectedItems.length === data.length) {
      setSelected([])
    } else {
      setSelected(data.map(item => item.key))
    }
  }

  const handleTableRowSelect = key => () => {
    setSelected(xor(selectedItems, [key]))
  }

  const tableHeader = columns.map(column => (
    <HeaderCell
      column={column}
      key={column.key}
      currentSortIndex={sortBy}
      currentSortDirection={sortDirection}
      sortable={!loading && sortable}
      onClick={handleTableHeaderClick} />
  ))

  const rows = loading
    ? new Array(loadingBars).fill(0).map((__, i) => <LoadingRow key={i} columnCount={columns.length} />)
    : sortedData.map(row => (
      <BodyRow key={row.key || row.id || row._id || i} row={row} columns={columns} onSelect={onSelect && handleTableRowSelect} selected={selectedItems.includes(row.key)} />
    ))

  return (
    <table className={tableStyles.root} {...otherProps}>
      <thead className={tableStyles.headerRow}>
        <tr>
          {!loading && onSelect && (
            <th className={tableStyles.headerCell}>
              <Checkbox partial={selectedItems.length > 0} checked={selectedItems.length === data.length} onChange={handleSelectAll}/>
            </th>
          )}
          {tableHeader}
        </tr>
      </thead>
      <tbody className={tableStyles.body}>
        {rows}
      </tbody>
    </table>
  )
}

Table.defaultProps = {
  sortable: true,
  loadingBars: 10
}

Table.propTypes = {
  // TODO: work out why this isn't working on storybook
  /** The columns to use in the table */
  // columns: propTypes.arrayOf(propTypes.shape({
  // title: propTypes.string.isRequired
  // dataIndex: propTypes.string,
  // render: propTypes.func
  // key: propTypes.string.isRequired
  // })),
  /** The data to display in the table */
  // data: propTypes.arrayOf(propTypes.shape({
  // key: propTypes.oneOfType([propTypes.string, propTypes.number]).isRequired
  // email: propTypes.string.isRequired
  // })),
  /** whether to show the loading state */
  loading: propTypes.bool,
  /** the number of loading bars (default: 10) */
  loadingBars: propTypes.number,
  /** callback when table is sorted */
  onSort: propTypes.func,
  /** callback when row(s) are selected - enables selection when defined */
  onSelect: propTypes.func,
  /** whether to make the table sortable */
  sortable: propTypes.bool
}

export default Table