From 934b626e9ee188322786000d434b602de29d79e9 Mon Sep 17 00:00:00 2001 From: ES Date: Wed, 27 Mar 2019 16:35:39 +0530 Subject: [PATCH 01/12] Removed redundant code --- src/css/table.css | 196 ---------------------------------------------- src/index.js | 1 - 2 files changed, 197 deletions(-) delete mode 100755 src/css/table.css diff --git a/src/css/table.css b/src/css/table.css deleted file mode 100755 index 2ac28d4..0000000 --- a/src/css/table.css +++ /dev/null @@ -1,196 +0,0 @@ -/* - flutter-react-data-table -*/ - -label.limiter { - display: inline-flex; - line-height: 30px; -} - -label.limiter select { - width: 50%; - margin-right: 10px; -} -.flutter-table-loader { - position: absolute; - top: 0; - bottom: 0; - height: 100%; - width: 100%; - opacity: 0.7; - background: #fff; - display: none; -} - -.flutter-table-loader.show { - display: block; -} - -.flutter-table-container { - position: relative; - display: block; - width: 100%; - overflow: auto; - border: 0; -} - - -/**** new table css ******/ -.flutter-table { - overflow: hidden; - table-layout: fixed; - width: 100%; - /* max-width: 100%; */ - background-color: transparent; - border-collapse: collapse; -} - -.flutter-table-head-container-inner { - border-bottom: 1px solid #ddd; -} - -.flutter-table-head-container { - overflow: hidden; - background: #f4f5f8; -} - -.flutter-table-body-container { - overflow: auto; - position: relative; -} - -.flutter-table-head-row, -.flutter-table-body-row, -.flutter-table-body-container.col-xs-12 { - clear: both; -} - -.flutter-table-body-row { - position: absolute; - left: 0; - border-bottom: 1px solid #ddd; -} - -.flutter-table-row-item { - float: left; - padding: 10px 5px; - overflow: hidden; - text-align: left; - text-overflow: ellipsis; - white-space: nowrap; - vertical-align: middle; -} - -.flutter-table-body-row .flutter-table-row-item { - height: 40px; -} - -.flutter-table-head-row.headers .flutter-table-row-item { - font-weight: bold; - text-align: center; - border-bottom: none !important; - cursor: pointer; - color: #167495; - border-top: none; - vertical-align: bottom; -} - -.flutter-table-header-item.sortable a { - white-space: nowrap; - cursor: pointer; - text-decoration: none; -} - -.flutter-table-head-row.headers .flutter-table-row-item button { - display: block; - border: none; - background: none; - padding: 0; -} - -.flutter-table.table-striped .flutter-table-body-row.odd { - background-color: #f9f9f9; -} - -.flutter-table .sort-caret { - display: inline-block; - width: 0; - height: 0; - margin-left: 0.3em; - border: 0; - content: ""; - border-right: 4px solid transparent; - border-left: 4px solid transparent; -} - -.flutter-table .asc .sort-caret { - vertical-align: baseline; - border-top: none; - border-bottom: 4px solid #000000; -} - -.flutter-table .desc .sort-caret { - vertical-align: super; - border-top: 4px solid #000000; - border-bottom: none; -} - -.flutter-table .string-cell, -.flutter-table .uri-cell, -.flutter-table .email-cell { - text-align: left; -} - -.flutter-table .date-cell, -.flutter-table .time-cell, -.flutter-table .datetime-cell, -.flutter-table .number-cell, -.flutter-table .integer-cell, -.flutter-table .percent-cell { - text-align: right; -} - -.flutter-table .boolean-cell { - text-align: center; -} - -.flutter-table .select-cell { - text-align: center; -} - -.flutter-table .flutter-table-body-row .flutter-table-row-item .badge { - width: 100% -} - -/* .flutter-table .flutter-table-row-item > input { - min-width: 100px; -} */ - -.flutter-table-body thead .headers { - visibility: collapse; -} - -/* .flutter-table-body { - overflow-y: scroll; -} */ - -.flutter-table-body-inner { - position: relative; -} - -.flutter-table-body-inner > table { - position: absolute; -} - -.flutter-table-outer-container .active-columns .dropdown-menu .dropdown-item { - padding: 5px 10px; -} - -.flutter-table-outer-container .active-columns .dropdown-menu .dropdown-item > input { - margin-right: 10px; -} - -.page-item.active .page-link { - background-color: #167495; - border-color: #167495; -} diff --git a/src/index.js b/src/index.js index cb84270..5026327 100755 --- a/src/index.js +++ b/src/index.js @@ -4,7 +4,6 @@ import * as epics from './epics'; import TableProvider, { TableConsumer, withTableConfig } from './TableProvider'; import * as actions from './actions'; import * as utils from './utils'; -import './css/table.css'; export { TableProvider, TableConsumer, withTableConfig, actions, utils, reducer, epics } export default ReduxDatatable; From b98f1c4b2ade30e72ca8683e66920d7978cd3e5a Mon Sep 17 00:00:00 2001 From: ES Date: Wed, 27 Mar 2019 16:45:12 +0530 Subject: [PATCH 02/12] Fixed styled-components generating several classes. --- src/Datatable/Styles/Table/Body.js | 5 +++-- src/Datatable/Styles/Table/Cell.js | 5 +++-- src/Datatable/Styles/Table/Header.js | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Datatable/Styles/Table/Body.js b/src/Datatable/Styles/Table/Body.js index dcd04be..612d4fa 100644 --- a/src/Datatable/Styles/Table/Body.js +++ b/src/Datatable/Styles/Table/Body.js @@ -11,9 +11,10 @@ const TableBody = styled.div ` overflow-y: scroll; ` -export const TableBodyInner = styled.div ` +export const TableBodyInner = styled.div.attrs(({ width = '100%' }) => ({ + style: { width } +})) ` position: relative; - width: ${props => props.width || '100%'}; border-bottom: ${props => props.borderBottom || '1px solid #ddd'}; ${props => props.height && css ` height: ${props.height} diff --git a/src/Datatable/Styles/Table/Cell.js b/src/Datatable/Styles/Table/Cell.js index 81fdd92..a1234b4 100644 --- a/src/Datatable/Styles/Table/Cell.js +++ b/src/Datatable/Styles/Table/Cell.js @@ -1,7 +1,9 @@ import React from 'react'; import styled, { css } from 'styled-components'; -const TableCell = styled.div ` +const TableCell = styled.div.attrs(({ width }) => ({ + style: { width } +})) ` float: left; padding: 10px 5px; overflow: hidden; @@ -9,7 +11,6 @@ const TableCell = styled.div ` text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; - width: ${props => props.width || '0px'}; font-size: ${props => props.fontSize || '14px'}; ${props => props.header && css ` diff --git a/src/Datatable/Styles/Table/Header.js b/src/Datatable/Styles/Table/Header.js index 1af96a1..3604103 100644 --- a/src/Datatable/Styles/Table/Header.js +++ b/src/Datatable/Styles/Table/Header.js @@ -8,8 +8,9 @@ const TableHeader = styled.div ` overflow: hidden; ` -export const TableHeaderInner = styled.div ` - width: ${props => props.width || '100%'}; +export const TableHeaderInner = styled.div.attrs(({ width = '100%' }) => ({ + style: { width } +})) ` border-bottom: ${props => props.borderBottom || '1px solid #ddd'}; ` From 0396fb35ab339b5d6d0b89e340737cae50b49e8a Mon Sep 17 00:00:00 2001 From: ES Date: Wed, 27 Mar 2019 19:25:48 +0530 Subject: [PATCH 03/12] Table styling --- src/Datatable/Pagination/Limiter.js | 13 +++--- src/Datatable/Renderer/Filter/Date.js | 4 +- src/Datatable/Renderer/Filter/Number.js | 4 +- src/Datatable/Renderer/Filter/String.js | 2 +- src/Datatable/Styles/Container.js | 5 +++ src/Datatable/Styles/Elements.js | 55 +++++++++++++++++++++++++ src/Datatable/Styles/Pagination.js | 2 +- src/Datatable/Styles/Row.js | 1 + src/Datatable/Styles/Table/Cell.js | 23 +++-------- src/Datatable/Styles/Toolbar.js | 2 +- src/Datatable/Styles/index.js | 4 +- src/Datatable/Table.js | 33 ++++----------- src/createTable.js | 12 +++++- 13 files changed, 101 insertions(+), 59 deletions(-) create mode 100644 src/Datatable/Styles/Elements.js diff --git a/src/Datatable/Pagination/Limiter.js b/src/Datatable/Pagination/Limiter.js index 41f820f..4e77892 100644 --- a/src/Datatable/Pagination/Limiter.js +++ b/src/Datatable/Pagination/Limiter.js @@ -1,23 +1,24 @@ import React from 'react'; import PropTypes from "prop-types"; import { SET_LIMIT } from '../../actions'; +import Styles from '../Styles'; export const TYPE_LIMITER = 'limiter'; -const Limiter = ({ options, limit, action, default: defaultLimit }) => { +const Limiter = ({ options, limit, action, style, default: defaultLimit }) => { const setLimit = ( limit ) => action(SET_LIMIT)({ limit }); return ( - + per page + ); } diff --git a/src/Datatable/Renderer/Filter/Date.js b/src/Datatable/Renderer/Filter/Date.js index c06d783..6370c63 100644 --- a/src/Datatable/Renderer/Filter/Date.js +++ b/src/Datatable/Renderer/Filter/Date.js @@ -31,7 +31,7 @@ const applyFilter = ( key, filterer, event ) => { const Date = ({ name, value = [], filterer }) => - placeholder="From" /> - { const Number = ({ name, value = [], filterer }) => - placeholder="From" /> - { }; const String = ({ name, value = '', filterer }) => - diff --git a/src/Datatable/Styles/Container.js b/src/Datatable/Styles/Container.js index f2002b5..19dccae 100644 --- a/src/Datatable/Styles/Container.js +++ b/src/Datatable/Styles/Container.js @@ -5,6 +5,11 @@ const Container = styled.div ` width: 100%; margin-right: auto; margin-left: auto; + font-family: ${props => + props.fontFamily || + `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, + sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"` + }; ` export default Container; diff --git a/src/Datatable/Styles/Elements.js b/src/Datatable/Styles/Elements.js new file mode 100644 index 0000000..9ab0ccc --- /dev/null +++ b/src/Datatable/Styles/Elements.js @@ -0,0 +1,55 @@ +import React from 'react'; +import styled, { css } from 'styled-components'; + +const formControl = ({ + backgroundColor, + border, + borderRadius, + fontSize, + color, + padding, + focusShadow, + focusBorderColor +}) => css ` + display: block; + width: 100%; + font-weight: 400; + line-height: 1.5; + background-color: ${backgroundColor || '#fff'}; + background-clip: padding-box; + border: ${border || '1px solid #ebebeb'}; + border-radius: ${borderRadius || 0}; + font-size: ${fontSize || '14px'}; + color: ${color || '#495057'}; + padding: ${padding || '10px 14px'}; + + &:focus { + box-shadow: ${focusShadow || 'none'}; + border-color: ${focusBorderColor || '#80bdff'} + } +` + +const Input = styled.input ` + ${props => formControl(props)} +` + +const Select = styled.select ` + ${props => formControl(props)} + width: ${props => props.width || '100%'}; +` + +const Label = styled.label ` + display: inline-block; + margin-bottom: 0.5rem; + + ${({ flex, noWrap}) => css ` + ${flex && `display: flex`}; + ${noWrap && `white-space: nowrap`}; + `} +` + +export default { + Input, + Select, + Label +}; diff --git a/src/Datatable/Styles/Pagination.js b/src/Datatable/Styles/Pagination.js index 114bcc9..ef9afca 100644 --- a/src/Datatable/Styles/Pagination.js +++ b/src/Datatable/Styles/Pagination.js @@ -6,7 +6,7 @@ export const PaginationItem = styled.div ` min-width: ${props => props.width || '200px'}; float: ${props => props.right ? 'right' : 'left'}; text-align: ${props => props.textAlign || 'left'}; - font-size: ${props => props.fontSize || '14px'}; + font-size: ${props => props.fontSize || '15px'}; ` export const PaginationList = styled.div ` diff --git a/src/Datatable/Styles/Row.js b/src/Datatable/Styles/Row.js index 89d37ac..13751ef 100644 --- a/src/Datatable/Styles/Row.js +++ b/src/Datatable/Styles/Row.js @@ -9,6 +9,7 @@ const Row = styled.div.attrs(({ top }) => ({ flex: 1 0 auto; flex-direction: row; flex-wrap: wrap; + width: 100%; padding: ${props => props.padding || 0}; height: ${props => props.height || 'auto'}; position: ${props => props.position || 'relative'}; diff --git a/src/Datatable/Styles/Table/Cell.js b/src/Datatable/Styles/Table/Cell.js index a1234b4..8f29e27 100644 --- a/src/Datatable/Styles/Table/Cell.js +++ b/src/Datatable/Styles/Table/Cell.js @@ -1,9 +1,11 @@ import React from 'react'; import styled, { css } from 'styled-components'; -const TableCell = styled.div.attrs(({ width }) => ({ - style: { width } +const TableCell = styled.div.attrs(({ width: maxWidth }) => ({ + style: { maxWidth } })) ` + box-sizing: border-box; + margin: auto; float: left; padding: 10px 5px; overflow: hidden; @@ -11,6 +13,8 @@ const TableCell = styled.div.attrs(({ width }) => ({ text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; + width: 100%; + position: relative; font-size: ${props => props.fontSize || '14px'}; ${props => props.header && css ` @@ -22,21 +26,6 @@ const TableCell = styled.div.attrs(({ width }) => ({ ${props => props.sortable && css ` cursor: pointer; `} - - ${props => props.search && css ` - & input { - border-radius: ${props => props.inputRadius || 0}; - color: ${props => props.inputColor || '#495057'}; - border: ${props => props.inputBorder || '1px solid #ebebeb'}; - padding: ${props => props.inputPadding || '10px 14px'}; - width: ${props => props.inputWidth || '100%'}; - - &:focus { - box-shadow: ${props => props.inputFocusShadow || 'none'}; - border-color: ${props => props.inputFocusBorderColor || '#80bdff'} - } - } - `} ` export default TableCell; diff --git a/src/Datatable/Styles/Toolbar.js b/src/Datatable/Styles/Toolbar.js index cbc2f94..8a1fa63 100644 --- a/src/Datatable/Styles/Toolbar.js +++ b/src/Datatable/Styles/Toolbar.js @@ -10,7 +10,7 @@ export const ToolbarItem = styled.div ` display: block; width: ${props => props.width || '100px'}; float: ${props => props.right ? 'right' : 'left'}; - font-size: ${props => props.fontSize || '14px'}; + font-size: ${props => props.fontSize || '15px'}; ` const Toolbar = styled.div ` diff --git a/src/Datatable/Styles/index.js b/src/Datatable/Styles/index.js index aadbb96..3f8f6ae 100644 --- a/src/Datatable/Styles/index.js +++ b/src/Datatable/Styles/index.js @@ -7,6 +7,7 @@ import TableHeader, { TableHeaderInner } from './Table/Header'; import TableBody, { TableBodyInner } from './Table/Body'; import TableCell from './Table/Cell'; import SortCaret from './SortCaret'; +import Elements from './Elements'; export default { Container, @@ -24,5 +25,6 @@ export default { TableCell, TableBody, TableBodyInner, - SortCaret + SortCaret, + Elements } diff --git a/src/Datatable/Table.js b/src/Datatable/Table.js index 908b7f6..f650b16 100644 --- a/src/Datatable/Table.js +++ b/src/Datatable/Table.js @@ -14,9 +14,9 @@ class Table extends Component { constructor(props) { super(props); - this.width = this.calculateWidth(this.props.config.columns); + this.width = this.calculateWidth(this.props.columns); this.minWidth = this.width; - this.rowHeight = this.props.config.rowHeight || 39; + this.rowHeight = this.props.rowHeight || 39; this.state = { top: 0 }; this.handleScroll = this.handleScroll.bind(this); this.updateTableDimensions = this.updateTableDimensions.bind(this); @@ -56,8 +56,7 @@ class Table extends Component { this.computedTableWidth = this.minWidth > tableBodyEl.clientWidth ? this.minWidth : tableBodyEl.clientWidth; - - const { columns, allColumns, checkedColumns, stateUpdater } = this.props.config; + const { columns, allColumns, checkedColumns, stateUpdater } = this.props; const totalColumnsWidth = checkedColumns.reduce((result, columnIndex) => ( result + (allColumns[columnIndex].width || 0) ), 0); @@ -89,7 +88,7 @@ class Table extends Component { } componentDidUpdate(prevProps) { - this.updateTableOnColumnVisibilityChange(prevProps.config.columns, this.props.config.columns) + this.updateTableOnColumnVisibilityChange(prevProps.columns, this.props.columns) } componentWillUnmount() { @@ -100,7 +99,7 @@ class Table extends Component { getExtraBodyRowProps() { const { data, - config: { columns } + columns } = this.props; return columns.reduce((result = {}, { name, extraData }) => { result[name] = extraData @@ -121,15 +120,7 @@ class Table extends Component { } render() { - const { - children, - action, - thunk, - data, - filterable, - headers, - config: { columns, height }, - } = this.props; + const { children, action, thunk, data, filterable, headers, columns, height } = this.props; const { items = [], query = {} } = data; const { pointerEvents, top } = this.state; const bodyExtraData = this.getExtraBodyRowProps(); @@ -202,14 +193,4 @@ class Table extends Component { } } -export default withTableConfig({ - name: 'name', - height: 'height', - columns: 'columns', - minWidth: 'minWidth', - rowHeight: 'rowHeight', - allColumns: 'allColumns', - checkedColumns: 'checkedColumns', - reducerName: 'reducerName', - stateUpdater: 'updateTableState' -})(Table); +export default Table; diff --git a/src/createTable.js b/src/createTable.js index ef3680c..fa97e63 100755 --- a/src/createTable.js +++ b/src/createTable.js @@ -60,7 +60,7 @@ class ReduxDatatable extends Component { render() { const { name, config, tableData, reducerName, action, thunk } = this.props; const { columns: allColumns, ...otherConfig } = config; - const { toolbar = [], pagination = {}, filterable, headers } = config; + const { toolbar = [], pagination = {}, filterable, headers, height, rowHeight, style } = config; const tableConfig = { ...otherConfig, allColumns, @@ -82,7 +82,7 @@ class ReduxDatatable extends Component { const { query } = tableData; return ( - + Date: Thu, 28 Mar 2019 18:22:48 +0530 Subject: [PATCH 04/12] Updated styles --- demo/src/schema/basic.js | 13 ++- src/Datatable/Pagination/Limiter.js | 4 +- src/Datatable/Pagination/Pages.js | 20 ++-- src/Datatable/Renderer/Filter/Date.js | 4 +- src/Datatable/Renderer/Filter/Number.js | 4 +- src/Datatable/Renderer/Filter/String.js | 2 +- src/Datatable/Styles/Elements/Button.js | 58 ++++++++++++ src/Datatable/Styles/Elements/Dropdown.js | 94 +++++++++++++++++++ .../Styles/{Elements.js => Elements/Field.js} | 15 +-- src/Datatable/Styles/Elements/Label.js | 14 +++ src/Datatable/Styles/Elements/index.js | 13 +++ src/Datatable/Styles/Row.js | 4 - src/Datatable/Styles/Table/Cell.js | 9 +- src/Datatable/Toolbar/Columns.js | 13 ++- src/Datatable/Toolbar/MassActions.js | 23 +++-- src/Datatable/Toolbar/ResetFilters.js | 6 +- 16 files changed, 237 insertions(+), 59 deletions(-) create mode 100644 src/Datatable/Styles/Elements/Button.js create mode 100644 src/Datatable/Styles/Elements/Dropdown.js rename src/Datatable/Styles/{Elements.js => Elements/Field.js} (80%) create mode 100644 src/Datatable/Styles/Elements/Label.js create mode 100644 src/Datatable/Styles/Elements/index.js diff --git a/demo/src/schema/basic.js b/demo/src/schema/basic.js index d6dedb7..8c1d849 100644 --- a/demo/src/schema/basic.js +++ b/demo/src/schema/basic.js @@ -69,7 +69,11 @@ export default { visible: true, style: { right: false, - width: '100px' + width: '100px', + button: { + background: '#fff', + color: '#6c757d' + } } }, { type: 'reset-filters', @@ -82,7 +86,11 @@ export default { visible: true, state: false, style: { - right: true + right: true, + button: { + background: '#fff', + color: '#6c757d' + } } }/*, { label: 'NACTIONS', @@ -184,7 +192,6 @@ export default { label: 'ID', type: 'number', name: 'pageId', - sortable: true, width: 150, filterable: true, sortable: true, diff --git a/src/Datatable/Pagination/Limiter.js b/src/Datatable/Pagination/Limiter.js index 4e77892..1b9c695 100644 --- a/src/Datatable/Pagination/Limiter.js +++ b/src/Datatable/Pagination/Limiter.js @@ -9,7 +9,7 @@ const Limiter = ({ options, limit, action, style, default: defaultLimit }) => { const setLimit = ( limit ) => action(SET_LIMIT)({ limit }); return ( - { { options.map( (option, index) => ) } - per page + per page ); } diff --git a/src/Datatable/Pagination/Pages.js b/src/Datatable/Pagination/Pages.js index 7fa93dd..ffbcccd 100644 --- a/src/Datatable/Pagination/Pages.js +++ b/src/Datatable/Pagination/Pages.js @@ -24,22 +24,22 @@ const Pages = ({ page, total, action }) => { const setPage = ( page ) => action(SET_PAGE)({ page }); return ( - First - Previous + First + Previous { getPages(page, total).map( (link, index) => - { link } + >{ link } ) } - = total }>Next - Last + = total }>Next + Last ); } diff --git a/src/Datatable/Renderer/Filter/Date.js b/src/Datatable/Renderer/Filter/Date.js index 6370c63..138c2f0 100644 --- a/src/Datatable/Renderer/Filter/Date.js +++ b/src/Datatable/Renderer/Filter/Date.js @@ -31,7 +31,7 @@ const applyFilter = ( key, filterer, event ) => { const Date = ({ name, value = [], filterer }) => - placeholder="From" /> - { const Number = ({ name, value = [], filterer }) => - placeholder="From" /> - { }; const String = ({ name, value = '', filterer }) => - diff --git a/src/Datatable/Styles/Elements/Button.js b/src/Datatable/Styles/Elements/Button.js new file mode 100644 index 0000000..2427f47 --- /dev/null +++ b/src/Datatable/Styles/Elements/Button.js @@ -0,0 +1,58 @@ +import React from 'react'; +import styled, { css } from 'styled-components'; + +const Button = styled.button ` + display: inline-block; + transition: color 0.15s ease-in-out, + background-color 0.15s ease-in-out, + border-color 0.15s ease-in-out, + box-shadow 0.15s ease-in-out; + vertical-align: middle; + white-space: nowrap; + cursor: pointer; + + ${({ + background = '#6c757d', + border = '1px solid #6c757d', + fontWeight = 400, + lineHeight = 1.5, + fontSize = '14px', + borderRadius = 0, + color = '#fff', + padding = '0.375rem 0.75rem', + dropdownToggle = false, + hover + }) => css ` + background: ${background}; + border: ${border}; + font-weight: ${fontWeight}; + line-height: ${lineHeight}; + font-size: ${fontSize}; + border-radius: ${borderRadius}; + color: ${color}; + padding: ${padding}; + + ${dropdownToggle && ` + &::after { + display: inline-block; + width: 0; + height: 0; + vertical-align: middle; + content: ''; + border-top: 0.3em solid; + border-right: 0.3rem solid transparent; + border-bottom: 0; + border-left: 0.3rem solid transparent; + margin-left: 0.255rem; + } + `} + + ${hover && ` + &:hover { + + } + `} + `} +`; + +export default Button; diff --git a/src/Datatable/Styles/Elements/Dropdown.js b/src/Datatable/Styles/Elements/Dropdown.js new file mode 100644 index 0000000..06d6088 --- /dev/null +++ b/src/Datatable/Styles/Elements/Dropdown.js @@ -0,0 +1,94 @@ +import React from 'react'; +import styled, { css } from 'styled-components'; + +const Container = styled.div ` + position: relative; +` + +export const Menu = styled.div ` + position: absolute; + top: 100%; + z-index: 1000; + float: left; + min-width: 10rem; + text-align: left; + list-style: none; + background-clip: padding-box; + + ${({ + padding = '0.375rem 0.75rem', + margin, + fontSize = '14px', + color = '#6c757d', + border = '1px solid #6c757d', + right = false, + backgroundColor = '#fff', + borderRadius, + hidden + }) => css ` + padding: ${padding}; + margin: ${margin}; + font-size: ${fontSize}; + color: ${color}; + background-color: ${backgroundColor}; + border: ${border}; + border-radius: ${borderRadius}; + ${hidden + ? `display: none` + : `display: block` + } + ${right + ? `right: 0` + : `left: 0` + } + `} +`; + +export const Item = styled.div ` + clear: both; + text-align: inherit; + white-space: nowrap; + background-color: transparent; + border: 0; + + ${({ + padding = '0.375rem 0.75rem', + color, + fontWeight, + hover, + isActive, + active, + isDisabled, + disabled + }) => css ` + padding: ${padding}; + color: ${color}; + font-weight: ${fontWeight}; + + ${hover && ` + &:hover, &:focus { + color: ${hover.color}; + text-decoration: none; + background-color: ${hover.backgroundColor}; + } + `} + + ${isActive && active && ` + text-decoration: none; + color: ${active.color}; + background-color: ${active.backgroundColor}; + `} + + ${isDisabled && disabled && ` + color: ${disabled.color}; + background-color: transparent; + `} + `} +`; + + +export default { + Container, + Menu, + Item +}; diff --git a/src/Datatable/Styles/Elements.js b/src/Datatable/Styles/Elements/Field.js similarity index 80% rename from src/Datatable/Styles/Elements.js rename to src/Datatable/Styles/Elements/Field.js index 9ab0ccc..6e99eb9 100644 --- a/src/Datatable/Styles/Elements.js +++ b/src/Datatable/Styles/Elements/Field.js @@ -38,18 +38,7 @@ const Select = styled.select ` width: ${props => props.width || '100%'}; ` -const Label = styled.label ` - display: inline-block; - margin-bottom: 0.5rem; - - ${({ flex, noWrap}) => css ` - ${flex && `display: flex`}; - ${noWrap && `white-space: nowrap`}; - `} -` - export default { - Input, Select, - Label -}; + Input +} diff --git a/src/Datatable/Styles/Elements/Label.js b/src/Datatable/Styles/Elements/Label.js new file mode 100644 index 0000000..c4853f9 --- /dev/null +++ b/src/Datatable/Styles/Elements/Label.js @@ -0,0 +1,14 @@ +import React from 'react'; +import styled, { css } from 'styled-components'; + +const Label = styled.label ` + display: inline-block; + margin-bottom: 0.5rem; + + ${({ flex, noWrap }) => css ` + ${flex && `display: flex`}; + ${noWrap && `white-space: nowrap`}; + `} +` + +export default Label; diff --git a/src/Datatable/Styles/Elements/index.js b/src/Datatable/Styles/Elements/index.js new file mode 100644 index 0000000..fefb81f --- /dev/null +++ b/src/Datatable/Styles/Elements/index.js @@ -0,0 +1,13 @@ +import React from 'react'; +import styled, { css } from 'styled-components'; +import Label from './Label'; +import Button from './Button'; +import Dropdown from './Dropdown'; +import Field from './Field'; + +export default { + Label, + Button, + Dropdown, + Field +}; diff --git a/src/Datatable/Styles/Row.js b/src/Datatable/Styles/Row.js index 13751ef..815de64 100644 --- a/src/Datatable/Styles/Row.js +++ b/src/Datatable/Styles/Row.js @@ -4,11 +4,7 @@ import styled, { css } from 'styled-components'; const Row = styled.div.attrs(({ top }) => ({ style: { top } })) ` - box-sizing: border-box; display: flex; - flex: 1 0 auto; - flex-direction: row; - flex-wrap: wrap; width: 100%; padding: ${props => props.padding || 0}; height: ${props => props.height || 'auto'}; diff --git a/src/Datatable/Styles/Table/Cell.js b/src/Datatable/Styles/Table/Cell.js index 8f29e27..d82b01c 100644 --- a/src/Datatable/Styles/Table/Cell.js +++ b/src/Datatable/Styles/Table/Cell.js @@ -4,17 +4,18 @@ import styled, { css } from 'styled-components'; const TableCell = styled.div.attrs(({ width: maxWidth }) => ({ style: { maxWidth } })) ` - box-sizing: border-box; - margin: auto; - float: left; + flex-direction: column; + justify-content: center; + flex: 1; + display: flex; padding: 10px 5px; - overflow: hidden; text-align: ${props => props.textAlign || 'center'}; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; width: 100%; position: relative; + overflow: hidden; font-size: ${props => props.fontSize || '14px'}; ${props => props.header && css ` diff --git a/src/Datatable/Toolbar/Columns.js b/src/Datatable/Toolbar/Columns.js index 5dbda90..1c4f2fe 100644 --- a/src/Datatable/Toolbar/Columns.js +++ b/src/Datatable/Toolbar/Columns.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import ReactDOM from 'react-dom'; -import { Button } from 'styled-button-component'; import { Dropdown, DropdownItem, DropdownMenu } from 'styled-dropdown-component'; +import Styles from '../Styles'; class Columns extends Component { constructor(props) { @@ -55,7 +55,7 @@ class Columns extends Component { manageEvents(remove = false) { var eventUpdater = remove ? document.removeEventListener : document.addEventListener; - + ['click', 'touchstart', 'keyup'].forEach( event => eventUpdater(event, this.handleDocumentClick, true) ); @@ -79,14 +79,17 @@ class Columns extends Component { } render() { - const { config: { allColumns, checkedColumns }} = this.props; + const { + itemConfig: { style }, + config: { allColumns, checkedColumns } + } = this.props; const { open } = this.state; return ( - + - + + ); } } diff --git a/src/Datatable/Toolbar/MassActions.js b/src/Datatable/Toolbar/MassActions.js index 0f9dc76..df3e3af 100644 --- a/src/Datatable/Toolbar/MassActions.js +++ b/src/Datatable/Toolbar/MassActions.js @@ -61,7 +61,7 @@ class MassActions extends Component { render() { const { itemConfig, thunk } = this.props; - const { label, options, style } = itemConfig; + const { label, options, style = {} } = itemConfig; const { open } = this.state; return ( @@ -69,7 +69,7 @@ class MassActions extends Component { - +); export default Date; diff --git a/src/Datatable/Renderer/Filter/Number.js b/src/Datatable/Renderer/Filter/Number.js index f8502e1..8b44dce 100644 --- a/src/Datatable/Renderer/Filter/Number.js +++ b/src/Datatable/Renderer/Filter/Number.js @@ -1,7 +1,7 @@ -import PropTypes from "prop-types"; import React, { Fragment } from 'react'; -import { OPERATOR } from '../Filter'; -import Styles from '../../Styles'; +import { OPERATOR } from '../../../constants'; +import Row from '../../components/Row'; +import Field from '../../components/Field'; var valFrom = null; var valTo = null; @@ -9,13 +9,13 @@ var valTo = null; const applyFilter = ( key, filterer, event ) => { let filter = {}; - if(key == 0) { + if (key == 0) { valFrom = event.target.value; } else { valTo = event.target.value; } - if( valFrom || valTo ) { + if ( valFrom || valTo ) { filter = { operator: OPERATOR.BETWEEN, field: event.target.name, @@ -28,24 +28,27 @@ const applyFilter = ( key, filterer, event ) => { filterer(event.target.name, filter); }; -const Number = ({ name, value = [], filterer }) => +const Number = ({ name, value = [], filterer }) => ( - - + - - - + + + - + placeholder="To" + /> + +); export default Number; diff --git a/src/Datatable/Renderer/Filter/String.js b/src/Datatable/Renderer/Filter/String.js index e156149..d9438ea 100644 --- a/src/Datatable/Renderer/Filter/String.js +++ b/src/Datatable/Renderer/Filter/String.js @@ -1,10 +1,10 @@ -import PropTypes from "prop-types"; import React from 'react'; -import { OPERATOR } from '../Filter'; +import { OPERATOR } from '../../../constants'; +import Field from '../../components/Field'; const applyFilter = ( filterer, event ) => { let filter = {}; - if(event.target.value) { + if (event.target.value) { filter = { operator: OPERATOR.CONTAINS, field: event.target.name, @@ -16,11 +16,12 @@ const applyFilter = ( filterer, event ) => { filterer(event.target.name, filter); }; -const String = ({ name, value = '', filterer }) => - ( + - + onChange={ applyFilter.bind(this, filterer) } + /> +); export default String; diff --git a/src/Datatable/Renderer/Header.js b/src/Datatable/Renderer/Header.js deleted file mode 100644 index 568dcfa..0000000 --- a/src/Datatable/Renderer/Header.js +++ /dev/null @@ -1,40 +0,0 @@ -import React from 'react'; -import Styles from '../Styles'; -import { SET_SORT } from '../../actions'; - -const changeSortOrder = ( query, colName, sorter ) => { - let dir = null; - if( query.sort != colName ) { - dir = 'asc'; - } else { - if(query.dir == 'asc') { - dir = 'desc'; - } else if(query.dir == 'desc') { - colName = ''; - dir = ''; - } else { - dir = 'asc'; - } - } - - sorter({ sort: colName, dir }); -} - -const Header = ({ name, label, sortable, action, width, textAlign, query }) => { - const { sort, dir } = query; - return sortable ? - - { label } - { name === sort && } - : - { label } -} - -export default Header; diff --git a/src/Datatable/Pagination/Limiter.js b/src/Datatable/Renderer/Pagination/Limiter.js similarity index 63% rename from src/Datatable/Pagination/Limiter.js rename to src/Datatable/Renderer/Pagination/Limiter.js index 1b9c695..8dc5d15 100644 --- a/src/Datatable/Pagination/Limiter.js +++ b/src/Datatable/Renderer/Pagination/Limiter.js @@ -1,15 +1,13 @@ import React from 'react'; -import PropTypes from "prop-types"; -import { SET_LIMIT } from '../../actions'; -import Styles from '../Styles'; - -export const TYPE_LIMITER = 'limiter'; +import { SET_LIMIT } from '../../../actions'; +import Field from '../../components/Field'; +import Label from '../../components/Label'; const Limiter = ({ options, limit, action, style, default: defaultLimit }) => { const setLimit = ( limit ) => action(SET_LIMIT)({ limit }); return ( - - + { { options.map( (option, index) => ) } - per page - + per page + ); } diff --git a/src/Datatable/Renderer/Pagination/Pages.js b/src/Datatable/Renderer/Pagination/Pages.js new file mode 100644 index 0000000..e60dc13 --- /dev/null +++ b/src/Datatable/Renderer/Pagination/Pages.js @@ -0,0 +1,54 @@ +import React from 'react'; +import { SET_PAGE } from '../../../actions'; +import styled from 'styled-components'; +import Button from '../../components/Button'; + +export const List = styled.div ` + display: inline-flex; + vertical-align: middle; + background: ${props => props.background || '#fff'}; + border: ${props => props.border || '1px solid rgba(34,36,38,.15)'}; + border-radius: ${props => props.borderRadius || 'none'}; + height: ${props => props.height || '40px'} +` + +const NUM_LINKS = 5; + +const fillRange = ( start, end ) => { + return Array(end - start + 1).fill().map((item, index) => start + index); +}; + +const getPages = ( currentPage, total ) => { + var padding = Math.floor(NUM_LINKS / 2); + var left = (currentPage - padding < padding) ? 1 : currentPage - padding; + var right = (left + NUM_LINKS - 1 > total) ? total : left + NUM_LINKS - 1; + + left = (right == total) ? + (right - NUM_LINKS < 1) ? 1 : right - NUM_LINKS + 1 + : left; + + return fillRange(left, right); +} + +const Pages = ({ page, total, action, style }) => { + const setPage = ( page ) => action(SET_PAGE)({ page }); + return ( + + + + { getPages(page, total).map( (link, index) => + + ) } + + + + ); +} + +export default Pages diff --git a/src/Datatable/Pagination/ResultCount.js b/src/Datatable/Renderer/Pagination/ResultCount.js similarity index 100% rename from src/Datatable/Pagination/ResultCount.js rename to src/Datatable/Renderer/Pagination/ResultCount.js diff --git a/src/Datatable/Toolbar/Columns.js b/src/Datatable/Renderer/Toolbar/Columns.js similarity index 74% rename from src/Datatable/Toolbar/Columns.js rename to src/Datatable/Renderer/Toolbar/Columns.js index 85f689c..3bd6efc 100644 --- a/src/Datatable/Toolbar/Columns.js +++ b/src/Datatable/Renderer/Toolbar/Columns.js @@ -1,10 +1,7 @@ -import React, { Component } from 'react'; import ReactDOM from 'react-dom'; -import Styles from '../Styles'; - -const { - Elements: { Dropdown, Button } -} = Styles; +import React, { Component } from 'react'; +import Button from '../../components/Button'; +import Dropdown from '../../components/Dropdown'; class Columns extends Component { constructor(props) { @@ -18,23 +15,13 @@ class Columns extends Component { } updateColumns( index, event ) { - const { checkedColumns, allColumns, updateTableState } = this.props.config; + const { columnUpdater } = this.props; - var activeColumns = []; if(event.target.checked) { - activeColumns = [ ...checkedColumns, index ]; + columnUpdater({ type: 'add', action: { index } }) } else { - const itemIndex = checkedColumns.indexOf(index); - activeColumns = [ ...checkedColumns ]; - activeColumns.splice(itemIndex, 1); + columnUpdater({ type: 'remove', action: { index } }) } - activeColumns.sort(); - - const columns = activeColumns.reduce((result, currentIndex) => ( - result.concat([allColumns[currentIndex]]) - ), []); - - updateTableState({ columns, checkedColumns: activeColumns }); } componentWillUnmount() { @@ -84,7 +71,8 @@ class Columns extends Component { render() { const { itemConfig: { style = {} }, - config: { allColumns, checkedColumns } + columns = [], + visibleColumns = [] } = this.props; const { open } = this.state; @@ -94,11 +82,11 @@ class Columns extends Component { Columns