Skip to content
This repository has been archived by the owner on Aug 21, 2023. It is now read-only.

Commit

Permalink
Merge 303f0ce into 30033d2
Browse files Browse the repository at this point in the history
  • Loading branch information
plbabin committed May 22, 2019
2 parents 30033d2 + 303f0ce commit 7027c86
Show file tree
Hide file tree
Showing 9 changed files with 408 additions and 135 deletions.
195 changes: 102 additions & 93 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@helpscout/hsds-react",
"version": "2.43.8",
"version": "2.44.0-table.0",
"private": false,
"main": "dist/index.js",
"module": "dist/index.es.js",
Expand Down Expand Up @@ -154,6 +154,7 @@
"@types/react-dom": "^16.0.8",
"@types/react-transition-group": "^2.0.14",
"@types/storybook__react": "^4.0.1",
"@welldone-software/why-did-you-render": "^3.0.9",
"autoprefixer": "7.1.1",
"awesome-typescript-loader": "^5.2.0",
"babel-eslint": "^9.0.0",
Expand All @@ -178,6 +179,7 @@
"eslint-plugin-jsx-a11y": "5.1.1",
"eslint-plugin-react": "7.9.1",
"eslint-scope": "3.7.1",
"fast-deep-equal": "^2.0.1",
"fs-extra": "^3.0.1",
"glob": "^7.1.3",
"hoek": "5.0.3",
Expand Down
88 changes: 88 additions & 0 deletions src/components/Table/Table.Body.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import * as React from 'react'

import * as equal from 'fast-deep-equal'

import Row from './Table.Row'

import { BodyProps, BodyState } from './Table.types'

export default class Body extends React.Component<BodyProps, BodyState> {
columnsCache = []
state: BodyState = { rows: [] }

constructor(props) {
super(props)
this.columnsCache = this.getColumnsCache(this.props.columns)

this.state.rows = this.getRows(props)
}

getRows(props: any = {}) {
const { isTableCollapsed, rows, maxRowsToDisplay } = props

if (!rows) {
return []
}

return isTableCollapsed ? rows.slice(0, maxRowsToDisplay) : [...rows]
}

getColumnsCache(columns) {
return columns.map(c => {
let key = c.columnKey
if (Array.isArray(key)) {
key = key.join(',')
}
return key
})
}

componentWillReceiveProps(nextProps) {
const { rows } = this.props

this.setState({
rows: this.getRows(nextProps),
})
}

shouldComponentUpdate(nextProps, nextState) {
const { maxRowsToDisplay, isTableCollapsed } = this.props
const { rows } = this.state

if (!equal(this.getColumnsCache(nextProps.columns), this.columnsCache)) {
this.columnsCache = this.getColumnsCache(nextProps.columns)
return true
}

if (
isTableCollapsed !== nextProps.isTableCollapsed ||
maxRowsToDisplay !== nextProps.maxRowsToDisplay
) {
return true
}

if (!equal(rows, nextState.rows)) {
return true
}

return false
}

render() {
const { columns, onRowClick } = this.props
const { rows } = this.state

return (
<tbody>
{rows.map(row => (
<Row
row={row}
columns={columns}
key={`row_${row.id}`}
onRowClick={onRowClick}
/>
))}
</tbody>
)
}
}
43 changes: 43 additions & 0 deletions src/components/Table/Table.Head.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as React from 'react'

import * as equal from 'fast-deep-equal'

import HeaderCell from './Table.HeaderCell'
import { TABLE_CLASSNAME } from './Table'
import { generateCellKey } from './Table.utils'

import { HeadProps } from './Table.types'

export default class Head extends React.Component<HeadProps> {
shouldComponentUpdate(nextProps) {
const { columns, sortedInfo } = this.props

if (!equal(sortedInfo, nextProps.sortedInfo)) {
return true
}

if (!equal(columns, nextProps.columns)) {
return true
}

return false
}

render() {
const { isLoading, columns, sortedInfo } = this.props
return (
<thead>
<tr className={`${TABLE_CLASSNAME}__HeaderRow`}>
{columns.map(column => (
<HeaderCell
key={generateCellKey('headercell', column)}
column={column}
isLoading={isLoading}
sortedInfo={sortedInfo}
/>
))}
</tr>
</thead>
)
}
}
84 changes: 48 additions & 36 deletions src/components/Table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,26 @@ import * as React from 'react'
import { ThemeProvider } from '../styled'
import { classNames } from '../../utilities/classNames'
import { noop } from '../../utilities/other'

import * as equal from 'fast-deep-equal'

import getValidProps from '@helpscout/react-utils/dist/getValidProps'
import propConnect from '../PropProvider/propConnect'
import Button from '../Button'
import Scrollable from '../Scrollable'
import { COMPONENT_KEY, generateCellKey } from './Table.utils'
import { COMPONENT_KEY } from './Table.utils'

import { TableWrapperUI, TableUI } from './styles/Table.css'
import { TableWrapperUI, TableUI, LoadingUI } from './styles/Table.css'
import { defaultTheme, chooseTheme } from './styles/themes'

import Row from './Table.Row'
import HeaderCell from './Table.HeaderCell'
import Body from './Table.Body'
import Head from './Table.Head'

import { TableProps, TableState } from './Table.types'

export const TABLE_CLASSNAME = 'c-Table'

export class Table extends React.PureComponent<TableProps, TableState> {
export class Table extends React.Component<TableProps, TableState> {
constructor(props) {
super(props)

Expand Down Expand Up @@ -63,18 +66,16 @@ export class Table extends React.PureComponent<TableProps, TableState> {
}

getComponentClassNames = () => {
const { className, tableClassName, isLoading, onRowClick } = this.props
const { className, tableClassName, onRowClick } = this.props
const { isTableCollapsed } = this.state

const tableWrapperClassNames = classNames(
`${TABLE_CLASSNAME}__Wrapper`,
isLoading && 'is-loading',
isTableCollapsed && 'is-collapsed',
className
)
const tableClassNames = classNames(
TABLE_CLASSNAME,
isLoading && 'is-loading',
Boolean(onRowClick) && 'with-clickable-rows',
tableClassName
)
Expand All @@ -93,6 +94,30 @@ export class Table extends React.PureComponent<TableProps, TableState> {
)
}

shouldComponentUpdate(nextProps: TableProps, nextState: TableState) {
if (
nextState &&
nextState.isTableCollapsed !== this.state.isTableCollapsed
) {
return true
}

const { columns, data, ...rest } = this.props
const { columns: columnsNext, data: dataNext, ...restNext } = nextProps
if (!equal(rest, restNext)) {
return true
}
if (!equal(columnsNext, columns)) {
return true
}

if (!equal(dataNext, data)) {
return true
}

return false
}

render() {
const {
className,
Expand All @@ -117,16 +142,11 @@ export class Table extends React.PureComponent<TableProps, TableState> {
tableClassNames,
} = this.getComponentClassNames()

const rowsToDisplay = isTableCollapsed
? data.slice(0, maxRowsToDisplay)
: [...data]

return (
<ThemeProvider theme={chooseTheme(theme)}>
<TableWrapperUI
className={tableWrapperClassNames}
innerRef={this.setWrapperNode}
isLoading={isLoading}
containerWidth={containerWidth}
{...getValidProps(rest)}
>
Expand All @@ -141,32 +161,24 @@ export class Table extends React.PureComponent<TableProps, TableState> {
className={tableClassNames}
innerRef={this.setTableNode}
>
<thead>
<tr className={`${TABLE_CLASSNAME}__HeaderRow`}>
{columns.map(column => (
<HeaderCell
key={generateCellKey('headercell', column)}
column={column}
isLoading={isLoading}
sortedInfo={sortedInfo}
/>
))}
</tr>
</thead>

<tbody>
{rowsToDisplay.map(row => (
<Row
row={row}
columns={columns}
key={`row_${row.id}`}
onRowClick={onRowClick}
/>
))}
</tbody>
<Head
columns={columns}
isLoading={isLoading}
sortedInfo={sortedInfo}
/>

<Body
rows={data}
columns={columns}
isTableCollapsed={isTableCollapsed}
maxRowsToDisplay={maxRowsToDisplay}
onRowClick={onRowClick}
/>
</TableUI>
</Scrollable>

{isLoading && <LoadingUI className={`${TABLE_CLASSNAME}__Loading`} />}

{isTableCollapsed ? (
<Button
version={2}
Expand Down
18 changes: 18 additions & 0 deletions src/components/Table/Table.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,30 @@ export interface TableState {
isTableCollapsed?: boolean
}

export interface BodyProps {
columns: Column[]
isTableCollapsed?: boolean
maxRowsToDisplay?: number
rows: Data[]
onRowClick?: (event: Event, row: Data) => void
}

export interface BodyState {
rows: Data[]
}

export interface RowProps {
columns: Column[]
row: Data
onRowClick?: (event: Event, row: Data) => void
}

export interface HeadProps {
columns: Column[]
isLoading?: boolean
sortedInfo?: SortedInfo
}

export interface HeaderCellProps {
column: Column
isLoading?: boolean
Expand Down

0 comments on commit 7027c86

Please sign in to comment.