diff --git a/packages/patternfly-4/react-docs/package.json b/packages/patternfly-4/react-docs/package.json index 335d38c297a..367d124e78a 100644 --- a/packages/patternfly-4/react-docs/package.json +++ b/packages/patternfly-4/react-docs/package.json @@ -38,8 +38,8 @@ "gatsby" ], "scripts": { - "docbuild": "node build/copyDocs.js && gatsby build", - "pr-build": "node build/copyDocs.js && gatsby build --prefix-paths", + "docbuild": "node build/copyDocs.js && node --max_old_space_size=4096 ./node_modules/.bin/gatsby build", + "pr-build": "node build/copyDocs.js && node --max_old_space_size=4096 ./node_modules/.bin/gatsby build --prefix-paths", "develop": "gatsby develop" }, "browserslist": [ diff --git a/packages/patternfly-4/react-table/src/components/Table/Body.js b/packages/patternfly-4/react-table/src/components/Table/Body.js index 26dddbfbf0b..a1021548831 100644 --- a/packages/patternfly-4/react-table/src/components/Table/Body.js +++ b/packages/patternfly-4/react-table/src/components/Table/Body.js @@ -25,13 +25,18 @@ class ContextBody extends React.Component { onRow = (row, props) => { const { onRowClick, onRow } = this.props; - // if we have a parent onRow, call it to retrieve the resulting props - const parentRowProps = onRow ? onRow(row, props) : {}; + // if we have an extended onRow, call it to retrieve the resulting props + const extendedRowProps = onRow ? onRow(row, props) : {}; + const rowProps = { + ...props, + ...row.props, + ...extendedRowProps + }; return { isExpanded: row.isExpanded, isOpen: row.isOpen, onClick: event => onRowClick(event, row, props), - ...parentRowProps + ...rowProps }; }; diff --git a/packages/patternfly-4/react-table/src/components/Table/RowWrapper.js b/packages/patternfly-4/react-table/src/components/Table/RowWrapper.js index 68134f08bd4..97ddeb5ab14 100644 --- a/packages/patternfly-4/react-table/src/components/Table/RowWrapper.js +++ b/packages/patternfly-4/react-table/src/components/Table/RowWrapper.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import { tableExpandableRow, modifiers } from '@patternfly/patternfly-next/components/Table/table.css'; import { css } from '@patternfly/react-styles'; -const RowWrapper = ({ isOpen, isExpanded, trRef, ...props }) => ( +const RowWrapper = ({ isOpen, isExpanded, trRef, rowIndex, rowKey, ...props }) => ( ( ); RowWrapper.propTypes = { - trRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.instanceOf(Element) })]), + trRef: PropTypes.object, + rowIndex: PropTypes.number, + rowKey: PropTypes.string, isOpen: PropTypes.bool, isExpanded: PropTypes.bool }; RowWrapper.defaultProps = { trRef: undefined, + rowIndex: undefined, + rowKey: undefined, isOpen: undefined, isExpanded: undefined }; diff --git a/packages/patternfly-4/react-table/src/components/Table/__snapshots__/Table.test.js.snap b/packages/patternfly-4/react-table/src/components/Table/__snapshots__/Table.test.js.snap index 2cc9282db12..bc38ec186a0 100644 --- a/packages/patternfly-4/react-table/src/components/Table/__snapshots__/Table.test.js.snap +++ b/packages/patternfly-4/react-table/src/components/Table/__snapshots__/Table.test.js.snap @@ -2291,6 +2291,8 @@ exports[`Actions table 1`] = ` > measurement - this.ref = null; + + this.ref = React.createRef(); + + this.scrollTo = index => { + const startIndex = parseInt(index, 10); + + if (startIndex >= 0) { + const startHeight = + calculateAverageHeight({ + measuredRows: this.measuredRows, + rows: props.rows, + rowKey: props.rowKey + }) * startIndex; + + this.scrollTop = startHeight; + this.ref.current.scrollTop = startHeight; + + this.setState(this.calculateRows(this.props)); + } + }; + this.scrollTop = 0; this.initialMeasurement = true; this.timeoutId = 0; @@ -58,6 +78,7 @@ class Body extends React.Component { return props.height || props.style.maxHeight; } + // todo: convert `componentWillReceiveProps` to `getDerivedStateFromProps` componentWillReceiveProps(nextProps) { if (!isEqual(this.props.rows, nextProps.rows) || this.getHeight(this.props) !== this.getHeight(nextProps)) { if (process.env.NODE_ENV !== 'production' && typeof window !== 'undefined' && window.LOG_VIRTUALIZED) { @@ -120,16 +141,13 @@ class Body extends React.Component { }; }, rowsToRender, - // todo: revisit passing ref to scrolling container and finding offset - // ref: body => { - // this.ref = body && body.getRef().getRef(); - // }, onScroll: this.onScroll }); return ( { - const startIndex = parseInt(index, 10); + // ref.scrollTo = index => { + // const startIndex = parseInt(index, 10); - if (startIndex >= 0) { - const startHeight = - calculateAverageHeight({ - measuredRows: this.measuredRows, - rows: this.props.rows, - rowKey: this.props.rowKey - }) * startIndex; + // if (startIndex >= 0) { + // const startHeight = + // calculateAverageHeight({ + // measuredRows: this.measuredRows, + // rows: this.props.rows, + // rowKey: this.props.rowKey + // }) * startIndex; - this.scrollTop = startHeight; - this.ref.scrollTop = startHeight; + // this.scrollTop = startHeight; + // this.ref.scrollTop = startHeight; - this.setState(this.calculateRows(this.props)); - } - }; + // this.setState(this.calculateRows(this.props)); + // } + // }; - return ref; - } + // return ref; + // } calculateRows(props) { return calculateRows({ scrollTop: this.scrollTop, @@ -221,9 +239,9 @@ class Body extends React.Component { } } -const VirtualizedBody = props => ( +const VirtualizedBody = ({ tableBody, ...props }) => ( - {({ headerData, rows }) => } + {({ headerData, rows }) => } ); diff --git a/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/BodyWrapper.js b/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/BodyWrapper.js index 5ce15c200de..8ae97e0089a 100644 --- a/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/BodyWrapper.js +++ b/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/BodyWrapper.js @@ -8,10 +8,9 @@ const VirtualizedBodyWrapper = inputRows => { class VirtualizedBody extends Component { constructor(props) { super(props); - this.ref = React.createRef(); } render() { - const { children, startHeight, endHeight, showExtraRow, ...props } = this.props; + const { children, bodyRef, startHeight, endHeight, showExtraRow, ...props } = this.props; const startRow = tr({ key: 'start-row', style: { @@ -43,7 +42,7 @@ const VirtualizedBodyWrapper = inputRows => { 'tbody', { ...props, - ref: this.ref, + ref: bodyRef, className: css( inputRows.some(row => row.isOpen && !row.hasOwnProperty('parent')) && styles.modifiers.expanded ) @@ -52,7 +51,7 @@ const VirtualizedBodyWrapper = inputRows => { ); } getRef() { - return this.ref; + return this.props.tableBodyRef; } } VirtualizedBodyWrapper.contextTypes = bodyWrapperContextTypes; @@ -64,8 +63,14 @@ const VirtualizedBodyWrapper = inputRows => { const VirtualizedBodyWithContext = props => ( - {({ startHeight, endHeight, showExtraRow }) => ( - + {({ bodyRef, startHeight, endHeight, showExtraRow }) => ( + )} ); diff --git a/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/RowWrapper.js b/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/RowWrapper.js index c975e29de0b..81650261395 100644 --- a/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/RowWrapper.js +++ b/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/RowWrapper.js @@ -35,7 +35,8 @@ class VirtualizedRowWrapper extends React.Component { VirtualizedRowWrapper.propTypes = { 'data-rowkey': PropTypes.string.isRequired, updateHeight: PropTypes.func.isRequired, - initialMeasurement: PropTypes.bool.isRequired + initialMeasurement: PropTypes.bool.isRequired, + trRef: PropTypes.object }; VirtualizedRowWrapper.shouldComponentUpdate = function(nextProps) { diff --git a/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/Virtualized.docs.js b/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/Virtualized.docs.js index ee532a459bd..28b99660996 100644 --- a/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/Virtualized.docs.js +++ b/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/Virtualized.docs.js @@ -1,14 +1,24 @@ -import { AutoSizer } from '@patternfly/react-virtualized-extension'; +import { + AutoSizer, + VirtualizedBody, + VirtualizedBodyWrapper, + VirtualizedRowWrapper +} from '@patternfly/react-virtualized-extension'; import AutoSizerExample from './examples/AutoSizerExample'; import VirtualizedExample from './examples/VirtualizedExample'; +import SortableExample from './examples/SortableExample'; export default { title: 'Virtualized', components: { - AutoSizer + AutoSizer, + VirtualizedBody, + VirtualizedBodyWrapper, + VirtualizedRowWrapper }, examples: [ { component: AutoSizerExample, title: 'Simple AutoSizer Example' }, - { component: VirtualizedExample, title: 'Simple Virtualized Example' } + { component: VirtualizedExample, title: 'Simple Virtualized Example' }, + { component: SortableExample, title: 'Sortable Virtualized Example' } ] }; diff --git a/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/examples/SortableExample.js b/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/examples/SortableExample.js new file mode 100644 index 00000000000..7ccd2bd760a --- /dev/null +++ b/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/examples/SortableExample.js @@ -0,0 +1,98 @@ +import React from 'react'; +import { Table, TableHeader, sortable, SortByDirection } from '@patternfly/react-table'; +import { + VirtualizedBody, + VirtualizedBodyWrapper, + VirtualizedRowWrapper +} from '@patternfly/react-virtualized-extension'; +// import './sample.css'; + +class SortableExample extends React.Component { + static title = 'Simple Table'; + constructor(props) { + super(props); + + this.tableBody = React.createRef(); + this.tableStyles = { + table: { + display: 'flex', + flexFlow: 'column' + }, + thead: { + display: 'table', + tableLayout: 'fixed', + width: '100%' + }, + tbody: { + display: 'block', + overflowY: 'scroll' + }, + tr: { + display: 'table', + tableLayout: 'fixed', + width: '100%' + }, + td: { + width: '20%' + } + }; + + const rows = []; + for (let i = 0; i < 100; i++) { + rows.push({ + id: i, + props: { style: this.tableStyles.tr }, + cells: [`one-${i}`, `two-${i}`, `three-${i}`, `four-${i}`, `five-${i}`] + }); + } + this.state = { + columns: [ + { title: 'Repositories', transforms: [sortable], props: { style: this.tableStyles.td } }, + { title: 'Branches', props: { style: this.tableStyles.td } }, + { title: 'Pull requests', transforms: [sortable], props: { style: this.tableStyles.td } }, + { title: 'Workspaces', props: { style: this.tableStyles.td } }, + { title: 'Last Commit', props: { style: this.tableStyles.td } } + ], + rows, + sortBy: {} + }; + this.onSort = this.onSort.bind(this); + } + + onSort(_event, index, direction) { + const sortedRows = this.state.rows.sort( + (a, b) => (a.cells[index] < b.cells[index] ? -1 : a.cells[index] > b.cells[index] ? 1 : 0) + ); + this.tableBody.current.scrollTo(0); + this.setState({ + sortBy: { + index, + direction + }, + rows: direction === SortByDirection.asc ? sortedRows : sortedRows.reverse() + }); + } + + render() { + const { columns, rows, sortBy } = this.state; + + return ( + + + +
+ ); + } +} + +export default SortableExample; diff --git a/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/examples/VirtualizedExample.js b/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/examples/VirtualizedExample.js index bac410ce3d0..4ffeb9c377d 100644 --- a/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/examples/VirtualizedExample.js +++ b/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/examples/VirtualizedExample.js @@ -5,27 +5,52 @@ import { VirtualizedBodyWrapper, VirtualizedRowWrapper } from '@patternfly/react-virtualized-extension'; -import './sample.css'; + +// import './sample.css'; class VirtualizedExample extends React.Component { static title = 'Simple Table'; constructor(props) { super(props); + this.tableStyles = { + table: { + display: 'flex', + flexFlow: 'column' + }, + thead: { + display: 'table', + tableLayout: 'fixed', + width: '100%' + }, + tbody: { + display: 'block', + overflowY: 'scroll' + }, + tr: { + display: 'table', + tableLayout: 'fixed', + width: '100%' + }, + td: { + width: '20%' + } + }; const rows = []; for (let i = 0; i < 100; i++) { rows.push({ id: i, + props: { style: this.tableStyles.tr }, cells: [`one-${i}`, `two-${i}`, `three-${i}`, `four-${i}`, `five-${i}`] }); } this.state = { columns: [ - { title: 'Repositories', props: { style: { width: '20%' } } }, - { title: 'Branches', props: { style: { width: '20%' } } }, - { title: 'Pull requests', props: { style: { width: '20%' } } }, - { title: 'Workspaces', props: { style: { width: '20%' } } }, - { title: 'Last Commit', props: { style: { width: '20%' } } } + { title: 'Repositories', props: { style: this.tableStyles.td } }, + { title: 'Branches', props: { style: this.tableStyles.td } }, + { title: 'Pull requests', props: { style: this.tableStyles.td } }, + { title: 'Workspaces', props: { style: this.tableStyles.td } }, + { title: 'Last Commit', props: { style: this.tableStyles.td } } ], rows }; @@ -36,14 +61,16 @@ class VirtualizedExample extends React.Component { return ( - - + +
); } diff --git a/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/examples/sample.css b/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/examples/sample.css index 20c5a388731..802c1f1a187 100644 --- a/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/examples/sample.css +++ b/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/examples/sample.css @@ -3,35 +3,35 @@ https://reactabular.js.org/#/features/virtualization?a=using-relative-column-widths */ -.pf-c-table { +.pf-c-virtualized.pf-c-table { display: flex; flex-flow: column; } -.pf-c-table thead, -.pf-c-table tbody tr { +.pf-c-virtualized.pf-c-table thead, +.pf-c-virtualized.pf-c-table tbody tr { display: table; table-layout: fixed; } -.pf-c-table thead { +.pf-c-virtualized.pf-c-table thead { /* flex: 0 0 auto; */ width: 100%; } -.pf-c-table thead tr { +.pf-c-virtualized.pf-c-table thead tr { /* 0.9em approximates scrollbar width */ /* width: calc(100% - 0.9em); */ width: 100%; display: table; } -.pf-c-table tbody { +.pf-c-virtualized.pf-c-table tbody { display: block; /* flex: 1 1 auto; */ overflow-y: scroll; } -.pf-c-table tbody tr { +.pf-c-virtualized.pf-c-table tbody tr { width: 100%; } diff --git a/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/types.js b/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/types.js index f6dea8d43c1..38e92301118 100644 --- a/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/types.js +++ b/packages/patternfly-4/react-virtualized-extension/src/components/Virtualized/types.js @@ -4,9 +4,7 @@ const bodyRowContextTypes = { initialMeasurement: PropTypes.bool, updateHeight: PropTypes.func }; -const bodyRowTypes = { - 'data-rowkey': PropTypes.string -}; + const bodyWrapperContextTypes = { startHeight: PropTypes.number, endHeight: PropTypes.number, @@ -20,4 +18,4 @@ const bodyChildContextTypes = { ...bodyWrapperContextTypes }; -export { bodyChildContextTypes, bodyRowContextTypes, bodyRowTypes, bodyWrapperContextTypes, bodyWrapperTypes }; +export { bodyChildContextTypes, bodyRowContextTypes, bodyWrapperContextTypes, bodyWrapperTypes };