diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 2fe8d1d0d..000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,38 +0,0 @@ - -## 1.0.5 (2018-01-02) - -Fix package.json issue - - -## 1.0.4 (2018-01-01) - -* accessibility fixes + live announce area added to handle announcement of sorting columns and other f ([8dba3f7](https://github.com/gregnb/mui-datatables/commit/8dba3f7)) -* added jsx-a11y to eslint. material-ui upgraded to 1.0.0.beta.26. now injecting MUIPopover with conta ([533a818](https://github.com/gregnb/mui-datatables/commit/533a818)) -* added updatePosition to Popover after table row content updates ([baceb9f](https://github.com/gregnb/mui-datatables/commit/baceb9f)) - - -## 1.0.3 (2017-12-30) - -* additional code coverage. more clean up work ([e857b3f](https://github.com/gregnb/mui-datatables/commit/e857b3f)) -* code coverage now at 91%. ready for first publish ([aedfdba](https://github.com/gregnb/mui-datatables/commit/aedfdba)) -* created a better dataset for example demo. updated README ([edf4ce1](https://github.com/gregnb/mui-datatables/commit/edf4ce1)) -* fix responsive 'stacked' view styling issues ([0debb9b](https://github.com/gregnb/mui-datatables/commit/0debb9b)) - - -## 1.0.2 (2017-12-27) - -* fix rollup issue. move version to 1.0.2 ([880983e](https://github.com/gregnb/mui-datatables/commit/880983e)) -* Initial commit ([e09d24f](https://github.com/gregnb/mui-datatables/commit/e09d24f)) -* keypress document listen event for ESCAPE on toolbar search ([bc6fc8d](https://github.com/gregnb/mui-datatables/commit/bc6fc8d)) -* more unit test coverage. additional code cleanup ([94cad45](https://github.com/gregnb/mui-datatables/commit/94cad45)) -* move to version 1.0.1 ([70b14c4](https://github.com/gregnb/mui-datatables/commit/70b14c4)) -* ran prettier for cleanup ([f6ba65e](https://github.com/gregnb/mui-datatables/commit/f6ba65e)) -* removed withDataStyles. replaced it with a new implementation: ([b08a20b](https://github.com/gregnb/mui-datatables/commit/b08a20b)) -* set prettier on test/ ([7799301](https://github.com/gregnb/mui-datatables/commit/7799301)) -* swap SVG arrows for header columns. aria-labels for pagination ([128d4b3](https://github.com/gregnb/mui-datatables/commit/128d4b3)) -* update codesandbox link ([fa8d33d](https://github.com/gregnb/mui-datatables/commit/fa8d33d)) -* update README. add issue template ([cb7689b](https://github.com/gregnb/mui-datatables/commit/cb7689b)) -* update unit tests to reflect changed caused by withDataStyles removal ([e60a00d](https://github.com/gregnb/mui-datatables/commit/e60a00d)) - - - diff --git a/README.md b/README.md index 813b0e49e..fb215004d 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,9 @@ If your project doesn't already use them, you need to install `@material-ui/core ## Demo -[![Edit react-to-print](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/gregnb/mui-datatables) +[![Edit react-to-print](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/muidatatables-custom-toolbar-rvmcj?file=/index.js) + +Browse live demos of all examples in this repo in [here](https://codesandbox.io/s/github/gregnb/mui-datatables)! ## Usage @@ -154,15 +156,15 @@ The component accepts the following props: |**`caseSensitive `**|boolean|false|Enable/disable case sensitivity for search. |**`confirmFilters`**|boolean|false|Works in conjunction with the **customFilterDialogFooter** option and makes it so filters have to be confirmed before being applied to the table. When this option is true, the customFilterDialogFooter callback will receive an applyFilters function which, when called, will apply the filters to the table. [Example](https://github.com/gregnb/mui-datatables/blob/master/examples/serverside-filters/index.js) |**`count`**|number||User provided override for total number of rows. +|**`customFilterDialogFooter `**|function||Add a custom footer to the filter dialog. `customFilterDialogFooter(curentFilterList: array, applyFilters: function) => React Component` |**`customFooter`**|function||Render a custom table footer. `function(count, page, rowsPerPage, changeRowsPerPage, changePage, `[`textLabels: object`](https://github.com/gregnb/mui-datatables/blob/master/src/textLabels.js)`) => string`|` React Component` [Example](https://github.com/gregnb/mui-datatables/blob/master/examples/customize-footer/index.js) +|**`customRowRender `**|function||Override default row rendering with custom function. `customRowRender(data, dataIndex, rowIndex) => React Component` +|**`customSearch `**|function||Override default search with custom function. `customSearch(searchQuery: string, currentRow: array, columns: array) => boolean` +|**`customSearchRender `**|function||Render a custom table search. `customSearchRender(searchText: string, handleSearch, hideSearch, options) => React Component` |**`customSort`**|function||Override default sorting with custom function. `function(data: array, colIndex: number, order: string) => array` |**`customTableBodyFooterRender`**|function||Render a footer under the table body but above the table's standard footer. This is useful for creating footers for individual columns. [Example](https://github.com/gregnb/mui-datatables/blob/master/examples/customize-footer/index.js) |**`customToolbar`**|function||Render a custom toolbar |**`customToolbarSelect`**|function||Render a custom selected rows toolbar. `function(selectedRows, displayData, setSelectedRows) => void` -|**`customRowRender `**|function||Override default row rendering with custom function. `customRowRender(data, dataIndex, rowIndex) => React Component` -|**`customSearch `**|function||Override default search with custom function. `customSearch(searchQuery: string, currentRow: array, columns: array) => boolean` -|**`customSearchRender `**|function||Render a custom table search. `customSearchRender(searchText: string, handleSearch, hideSearch, options) => React Component` -|**`customFilterDialogFooter `**|function||Add a custom footer to the filter dialog. `customFilterDialogFooter(curentFilterList: array, applyFilters: function) => React Component` |**`download`**|boolean|true|Show/hide download icon from toolbar |**`downloadOptions`**|object|`{filename: 'tableDownload.csv', separator: ','}`|Options to change the output of the CSV file: `filename`: string, `separator`: string, `filterOptions`: object(`useDisplayedColumnsOnly`: boolean, `useDisplayedRowsOnly`: boolean) |**`elevation`**|number|4|Shadow depth applied to Paper component. @@ -201,8 +203,8 @@ The component accepts the following props: |**`renderExpandableRow`**|function||Render expandable row. `function(rowData, rowMeta) => React Component` [Example](https://github.com/gregnb/mui-datatables/blob/master/examples/expandable-rows/index.js) |**`resizableColumns`**|boolean|false|Enable/disable resizable columns. |**`responsive`**|string|'stacked'|Enable/disable responsive table views. Options:

[Example](https://github.com/gregnb/mui-datatables/blob/master/examples/simple/index.js) -|**`rowsExpanded`**|array||User provided expanded rows. |**`rowHover`**|boolean|true|Enable/disable hover style over rows. +|**`rowsExpanded`**|array||User provided expanded rows. |**`rowsPerPage`**|number|10|Number of rows allowed per page. |**`rowsPerPageOptions`**|array|[10,15,100]|Options to provide in pagination for number of rows a user can select. |**`rowsSelected`**|array||User provided selected rows. diff --git a/examples/resizable-columns/index.js b/examples/resizable-columns/index.js index bda5842a5..6ef774901 100644 --- a/examples/resizable-columns/index.js +++ b/examples/resizable-columns/index.js @@ -1,70 +1,95 @@ -import React from "react"; +import React, { useState } from "react"; import ReactDOM from "react-dom"; import MUIDataTable from "../../src/"; -class Example extends React.Component { +import FormControl from '@material-ui/core/FormControl'; +import TextField from '@material-ui/core/TextField'; - constructor(props) { - super(props); +function Example(props) { - this.state = { counter: 1 }; - } + const [marginLeft, setMarginLeft] = useState(10); - // We update an arbitrary value here to test table resizing on state updates - update = () => { - let { counter } = this.state; - counter += 1; - - this.setState({ counter }); + const [counter, setCounter] = useState(1); + const incrCount = () => { // We update an arbitrary value here to test table resizing on state updates + setCounter(counter + 1); }; - render() { - const { counter } = this.state; - - const columns = [ - { - name: "Counter", - options: { - empty: true, - customBodyRender: value => - } - }, - { - name: "Name", - options: { - sort: false, - hint: "?" - } - }, - { - name: "Title", - options: { - hint: "?" + const columns = [ + { + name: "Counter", + options: { + empty: true, + customBodyRender: value => + } + }, + { + name: "Name", + options: { + sort: false, + hint: "?", + setCellProps: () => ({style: {whiteSpace:'nowrap'}}) + } + }, + { + name: "Business Title", + options: { + hint: "?", + customBodyRender: (val) => { + let parentStyle = { + position: 'absolute', + top: 0, + right: 0, + bottom: 0, + left: 0, + boxSizing: 'border-box', + display: 'block', + width: '100%', + }; + let cellStyle = { + boxSizing: 'border-box', + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + }; + return ( +
+
+
+ {val} +
+
+
+ ); } - }, - "Location" - ]; + } + }, + "Location" + ]; - const data = [ - ["Gabby George", "Business Analyst", "Minneapolis"], - ["Aiden Lloyd", "Business Consultant", "Dallas"], - ["Jaden Collins", "Attorney", "Santa Ana"], - ["Franky Rees", "Business Analyst", "St. Petersburg"], - ["Aaren Rose", null, "Toledo"] - ]; + const data = [ + ["Gabby George ", "Business Analyst", "Minneapolis"], + ["Aiden Lloyd", "Business Consultant at Tony's Burger Palace and CEO of Johnny's Blueberry Sundaes", "Dallas"], + ["Jaden Collins", "Attorney", "Santa Ana"], + ["Franky Rees", "Business Analyst", "St. Petersburg"], + ["Aaren Rose", null, "Toledo"] + ]; + const options = { + filter: true, + filterType: 'dropdown', + resizableColumns: true, + }; - const options = { - filter: true, - filterType: 'dropdown', - resizableColumns: true - }; - - return ( - - ); - - } + return ( + <> + + setMarginLeft(e.target.value)} /> + +
+ +
+ + ); } export default Example; diff --git a/package-lock.json b/package-lock.json index 9a0c31670..49a2fd68f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mui-datatables", - "version": "3.0.0-beta.0", + "version": "3.0.0-beta.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d7e30e8d6..75bc9ecea 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mui-datatables", - "version": "3.0.0-beta.2", + "version": "3.0.1", "description": "Datatables for React using Material-UI", "main": "dist/index.js", "files": [ diff --git a/src/MUIDataTable.js b/src/MUIDataTable.js index b8b101737..b32bbde7c 100644 --- a/src/MUIDataTable.js +++ b/src/MUIDataTable.js @@ -209,7 +209,7 @@ class MUIDataTable extends React.Component { tableBodyHeight: PropTypes.string, tableBodyMaxHeight: PropTypes.string, renderExpandableRow: PropTypes.func, - resizableColumns: PropTypes.bool, + resizableColumns: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]), responsive: PropTypes.oneOf(['standard', 'vertical', 'simple']), rowHover: PropTypes.bool, rowsExpanded: PropTypes.array, @@ -321,7 +321,10 @@ class MUIDataTable extends React.Component { this.setState({ page: 0 }); } - if (this.options.resizableColumns) { + if ( + this.options.resizableColumns === true || + (this.options.resizableColumns && this.options.resizableColumns.enabled) + ) { this.setHeadResizeable(this.headCellRefs, this.tableRef); this.updateDividers(); } @@ -894,7 +897,7 @@ class MUIDataTable extends React.Component { const filterType = column.filterType || options.filterType; if (filterVal.length || filterType === 'custom') { if (column.filterOptions && column.filterOptions.logic) { - if (column.filterOptions.logic(columnValue, filterVal)) isFiltered = true; + if (column.filterOptions.logic(columnValue, filterVal, row)) isFiltered = true; } else if (filterType === 'textField' && !this.hasSearchText(columnVal, filterVal, caseSensitive)) { isFiltered = true; } else if ( @@ -1747,7 +1750,8 @@ class MUIDataTable extends React.Component { columnNames={columnNames} />
- {this.options.resizableColumns && ( + {(this.options.resizableColumns === true || + (this.options.resizableColumns && this.options.resizableColumns.enabled)) && ( (this.updateDividers = fn)} diff --git a/src/components/Popover.js b/src/components/Popover.js index 6cf655659..d408c0a0c 100644 --- a/src/components/Popover.js +++ b/src/components/Popover.js @@ -1,110 +1,87 @@ -import React from 'react'; +import React, { useState, useRef, useEffect } from 'react'; import PropTypes from 'prop-types'; import MuiPopover from '@material-ui/core/Popover'; import IconButton from '@material-ui/core/IconButton'; -import { findDOMNode } from 'react-dom'; import CloseIcon from '@material-ui/icons/Close'; -class Popover extends React.Component { - state = { - open: false, - }; - - UNSAFE_componentWillMount() { - this.anchorEl = null; - } - - componentDidMount() { - if (this.props.refClose) { - this.props.refClose(this.handleRequestClose); - } - } +const Popover = ({ className, trigger, refExit, hide, content, ...providedProps }) => { + const [isOpen, open] = useState(false); + const anchorEl = useRef(null); - componentDidUpdate(prevProps, prevState) { - /* - * Update Popover position if a filter removes data from the table because - * it affects the window height which would cause the Popover to in the wrong place - */ - if (this.state.open === true) { - this.anchorEl = findDOMNode(this.anchorEl); - if (this.popoverActions) { - this.popoverActions.updatePosition(); - } - const shouldHide = typeof this.props.hide === 'boolean' ? this.props.hide : false; + useEffect(() => { + if (isOpen) { + const shouldHide = typeof hide === 'boolean' ? hide : false; if (shouldHide) { - this.handleRequestClose(); + open(false); } } - } + }, [hide, isOpen, open]); - handleClick = () => { - this.anchorEl = findDOMNode(this.anchorEl); - this.setState({ open: true }); + const handleClick = event => { + anchorEl.current = event.currentTarget; + open(true); }; - handleRequestClose = cb => { - this.setState({ open: false }, cb && typeof cb === 'function' ? cb() : () => {}); + const handleRequestClose = () => { + open(false); }; - handleOnExit = () => { - if (this.props.refExit) { - this.props.refExit(); - } + const closeIconClass = providedProps.classes.closeIcon; + + const transformOriginSpecs = { + vertical: 'top', + horizontal: 'center', }; - render() { - const { className, placement, trigger, refExit, content, hide, ...providedProps } = this.props; - let closeIconClass; - if (providedProps.classes && providedProps.classes.closeIcon) { - closeIconClass = providedProps.classes.closeIcon; - delete providedProps.classes.closeIcon; - } + const anchorOriginSpecs = { + vertical: 'bottom', + horizontal: 'center', + }; - const transformOriginSpecs = { - vertical: 'top', - horizontal: 'center', - }; + const handleOnExit = () => { + if (refExit) { + refExit(); + } + }; - const anchorOriginSpecs = { - vertical: 'bottom', - horizontal: 'center', - }; + const triggerProps = { + key: 'content', + onClick: event => { + if (trigger.props.onClick) trigger.props.onClick(); + handleClick(event); + }, + }; - const triggerEl = React.cloneElement({trigger}, { - key: 'content', - ref: el => (this.anchorEl = el), - onClick: () => { - if (trigger.props.onClick) trigger.props.onClick(); - this.handleClick(); - }, - }); + return ( + <> + {trigger} + + + + + {content} + + + ); +}; - return ( - - (this.popoverActions = actions)} - elevation={2} - open={this.state.open} - onClose={this.handleRequestClose} - onExited={this.handleOnExit} - anchorEl={this.anchorEl} - ref={el => this.popoverEl} - anchorOrigin={anchorOriginSpecs} - transformOrigin={transformOriginSpecs} - {...providedProps}> - - - - {content} - - {triggerEl} - - ); - } -} +Popover.propTypes = { + refExit: PropTypes.func, + trigger: PropTypes.node.isRequired, + content: PropTypes.node.isRequired, + hide: PropTypes.bool, +}; export default Popover; diff --git a/src/components/TableHead.js b/src/components/TableHead.js index 2ced3e167..0901ed858 100644 --- a/src/components/TableHead.js +++ b/src/components/TableHead.js @@ -50,12 +50,16 @@ class TableHead extends React.Component { const numSelected = (selectedRows && selectedRows.data.length) || 0; let isIndeterminate = numSelected > 0 && numSelected < count; - let isChecked = numSelected > 0 && numSelected === count; + let isChecked = numSelected > 0 && numSelected >= count; // When the disableToolbarSelect option is true, there can be // selected items that aren't visible, so we need to be more // precise when determining if the head checkbox should be checked. - if (options.disableToolbarSelect === true) { + if ( + options.disableToolbarSelect === true || + options.selectToolbarPlacement === 'none' || + options.selectToolbarPlacement === 'above' + ) { if (isChecked) { for (let ii = 0; ii < data.length; ii++) { if (!selectedRows.lookup[data[ii].dataIndex]) { diff --git a/src/components/TableResize.js b/src/components/TableResize.js index 2dfafa465..5384bb03a 100644 --- a/src/components/TableResize.js +++ b/src/components/TableResize.js @@ -1,6 +1,5 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { findDOMNode } from 'react-dom'; import { withStyles } from '@material-ui/core/styles'; const defaultResizeStyles = { @@ -17,6 +16,22 @@ const defaultResizeStyles = { }, }; +function getParentOffsetLeft(tableEl) { + let ii = 0, + parentOffsetLeft = 0, + offsetParent = tableEl.offsetParent; + while (offsetParent) { + parentOffsetLeft = parentOffsetLeft + (offsetParent.offsetLeft || 0); + offsetParent = offsetParent.offsetParent; + ii++; + if (ii > 1000) { + console.warn('Table nested within 1000 divs. Maybe an error.'); + break; + } + } + return parentOffsetLeft; +} + class TableResize extends React.Component { static propTypes = { /** Extend the style applied to components */ @@ -38,6 +53,7 @@ class TableResize extends React.Component { }; componentDidMount() { + this.minWidths = []; this.windowWidth = null; this.props.setResizeable(this.setCellRefs); this.props.updateDividers(() => this.setState({ updateCoords: true }, () => this.updateWidths)); @@ -55,20 +71,22 @@ class TableResize extends React.Component { }; setDividers = () => { - const tableEl = findDOMNode(this.tableRef); + const tableEl = this.tableRef; const { width: tableWidth, height: tableHeight } = tableEl.getBoundingClientRect(); const { resizeCoords } = this.state; + let parentOffsetLeft = getParentOffsetLeft(tableEl); let finalCells = Object.entries(this.cellsRef); finalCells.pop(); - finalCells.forEach(([key, item]) => { + finalCells.forEach(([key, item], idx) => { if (!item) return; - const elRect = item.getBoundingClientRect(); + let elRect = item.getBoundingClientRect(); + let left = elRect.left; + left = (left || 0) - parentOffsetLeft; const elStyle = window.getComputedStyle(item, null); - resizeCoords[key] = { left: elRect.left + item.offsetWidth - parseInt(elStyle.paddingLeft) / 2 }; + resizeCoords[key] = { left: left + item.offsetWidth }; }); - this.setState({ tableWidth, tableHeight, resizeCoords }, this.updateWidths); }; @@ -77,7 +95,18 @@ class TableResize extends React.Component { const { resizeCoords, tableWidth } = this.state; Object.entries(resizeCoords).forEach(([key, item]) => { - let newWidth = Number(((item.left - lastPosition) / tableWidth) * 100).toFixed(2); + let newWidth = Number(((item.left - lastPosition) / tableWidth) * 100); + + /* + Using .toFixed(2) causes the columns to jitter when resized. On all browsers I (patrojk) have tested, + a width with a floating point decimal works fine. It's unclear to me why the numbers were being rouned. + However, I'm putting in an undocumented escape hatch to use toFixed in case the change introduces a bug. + The below code will be removed in a later release if no problems with non-rounded widths are reported. + */ + if (typeof this.props.resizableColumns === 'object' && this.props.resizableColumns.roundWidthPercentages) { + newWidth = newWidth.toFixed(2); + } + lastPosition = item.left; const thCell = this.cellsRef[key]; @@ -86,20 +115,34 @@ class TableResize extends React.Component { }; onResizeStart = (id, e) => { + const tableEl = this.tableRef; + const originalWidth = tableEl.style.width; + tableEl.style.width = '1px'; + + let finalCells = Object.entries(this.cellsRef); + finalCells.forEach(([key, item], idx) => { + let elRect = item.getBoundingClientRect(); + this.minWidths[idx] = elRect.width; + }); + tableEl.style.width = originalWidth; + this.setState({ isResize: true, id }); }; onResizeMove = (id, e) => { const { isResize, resizeCoords } = this.state; - const fixedMinWidth = 100; + const fixedMinWidth1 = this.minWidths[id]; + const fixedMinWidth2 = this.minWidths[parseInt(id, 10) + 1] || this.minWidths[id]; const idNumber = parseInt(id, 10); const finalCells = Object.entries(this.cellsRef); - const tableEl = findDOMNode(this.tableRef); - const { width: tableWidth } = tableEl.getBoundingClientRect(); + const tableEl = this.tableRef; + const { width: tableWidth, height: tableHeight } = tableEl.getBoundingClientRect(); const { selectableRows } = this.props.options; + let parentOffsetLeft = getParentOffsetLeft(tableEl); + if (isResize) { - let leftPos = e.clientX; + let leftPos = e.clientX - parentOffsetLeft; const handleMoveRightmostBoundary = (leftPos, tableWidth, fixedMinWidth) => { if (leftPos > tableWidth - fixedMinWidth) { @@ -138,22 +181,22 @@ class TableResize extends React.Component { }; if (isFirstColumn(selectableRows, idNumber) && isLastColumn(idNumber, finalCells)) { - leftPos = handleMoveLeftmostBoundary(leftPos, fixedMinWidth); - leftPos = handleMoveRightmostBoundary(leftPos, tableWidth, fixedMinWidth); + leftPos = handleMoveLeftmostBoundary(leftPos, fixedMinWidth1); + leftPos = handleMoveRightmostBoundary(leftPos, tableWidth, fixedMinWidth2); } else if (!isFirstColumn(selectableRows, idNumber) && isLastColumn(idNumber, finalCells)) { - leftPos = handleMoveRightmostBoundary(leftPos, tableWidth, fixedMinWidth); - leftPos = handleMoveLeft(leftPos, resizeCoords, idNumber, fixedMinWidth); + leftPos = handleMoveRightmostBoundary(leftPos, tableWidth, fixedMinWidth2); + leftPos = handleMoveLeft(leftPos, resizeCoords, idNumber, fixedMinWidth1); } else if (isFirstColumn(selectableRows, idNumber) && !isLastColumn(idNumber, finalCells)) { - leftPos = handleMoveLeftmostBoundary(leftPos, fixedMinWidth); - leftPos = handleMoveRight(leftPos, resizeCoords, idNumber, fixedMinWidth); + leftPos = handleMoveLeftmostBoundary(leftPos, fixedMinWidth1); + leftPos = handleMoveRight(leftPos, resizeCoords, idNumber, fixedMinWidth2); } else if (!isFirstColumn(selectableRows, idNumber) && !isLastColumn(idNumber, finalCells)) { - leftPos = handleMoveLeft(leftPos, resizeCoords, idNumber, fixedMinWidth); - leftPos = handleMoveRight(leftPos, resizeCoords, idNumber, fixedMinWidth); + leftPos = handleMoveLeft(leftPos, resizeCoords, idNumber, fixedMinWidth1); + leftPos = handleMoveRight(leftPos, resizeCoords, idNumber, fixedMinWidth2); } const curCoord = { ...resizeCoords[id], left: leftPos }; const newResizeCoords = { ...resizeCoords, [id]: curCoord }; - this.setState({ resizeCoords: newResizeCoords }, this.updateWidths); + this.setState({ resizeCoords: newResizeCoords, tableHeight }, this.updateWidths); } }; @@ -177,7 +220,8 @@ class TableResize extends React.Component { style={{ width: isResize && id == key ? tableWidth : 'auto', position: 'absolute', - height: tableHeight, + height: tableHeight - 2, + cursor: 'ew-resize', zIndex: 1000, }}>
_.display === 'true'); + columnsToDownload = columns.filter(_ => _.display === 'true'); dataToDownload = dataToDownload.map(row => { row.data = row.data.filter((_, index) => columns[index].display === 'true'); @@ -258,7 +258,6 @@ class TableToolbar extends React.Component { resetFilters, toggleViewColumn, title, - tableRef, components = {}, updateFilterByType, } = this.props; @@ -353,6 +352,7 @@ class TableToolbar extends React.Component { {options.viewColumns && ( ({ }, title: { marginLeft: '-7px', + marginRight: '24px', fontSize: '14px', color: theme.palette.text.secondary, textAlign: 'left', diff --git a/test/TableResize.test.js b/test/TableResize.test.js new file mode 100644 index 000000000..b1a09d986 --- /dev/null +++ b/test/TableResize.test.js @@ -0,0 +1,51 @@ +import React from 'react'; +import { spy, stub } from 'sinon'; +import { mount, shallow } from 'enzyme'; +import { assert, expect, should } from 'chai'; +import TableResize from '../src/components/TableResize'; +import MUIDataTable from '../src/MUIDataTable'; + +describe('', function() { + let options; + + before(() => { + options = { + resizableColumns: true, + tableBodyHeight: '500px', + }; + }); + + it('should render a table resize component', () => { + const updateDividers = spy(); + const setResizeable = spy(); + + const mountWrapper = mount( + , + ); + + const actualResult = mountWrapper.find(TableResize); + assert.strictEqual(actualResult.length, 1); + + assert.strictEqual(updateDividers.callCount, 1); + assert.strictEqual(setResizeable.callCount, 1); + }); + + it('should create a coordinate map for each column', () => { + const columns = ['Name', 'Age', 'Location', 'Phone']; + const data = [['Joe', 26, 'Chile', '555-5555']]; + + const shallowWrapper = mount(); + + var state = shallowWrapper + .find(TableResize) + .childAt(0) + .state(); + + var colCoordCount = 0; + for (let prop in state.resizeCoords) { + colCoordCount++; + } + + assert.strictEqual(colCoordCount, 4); + }); +}); diff --git a/test/setup-mocha-env.js b/test/setup-mocha-env.js index 4cf7850f0..da07eae92 100644 --- a/test/setup-mocha-env.js +++ b/test/setup-mocha-env.js @@ -56,6 +56,8 @@ function setupDom() { global.getComputedStyle = global.window.getComputedStyle; global.HTMLInputElement = global.window.HTMLInputElement; global.Element = global.window.Element; + global.Event = global.window.Event; + global.dispatchEvent = global.window.dispatchEvent; Object.defineProperty(global.window.URL, 'createObjectURL', { value: () => {} }); global.Blob = () => '';