From c8ae73b40d064ec1a7570aa20e22854f56874c8e Mon Sep 17 00:00:00 2001 From: hyx131 Date: Tue, 11 Aug 2020 01:16:49 -0400 Subject: [PATCH 1/7] filter - filter component with checkbox select options --- src/filter.js | 95 +++++++++++++++++++++++++++++++ stories/filter.stories.js | 115 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 210 insertions(+) create mode 100644 src/filter.js create mode 100644 stories/filter.stories.js diff --git a/src/filter.js b/src/filter.js new file mode 100644 index 00000000..a0381760 --- /dev/null +++ b/src/filter.js @@ -0,0 +1,95 @@ +import React from 'react' +import PropTypes from 'prop-types' + +import { makeStyles } from '@material-ui/core/styles' +import Grid from '@material-ui/core/Grid' +import FormLabel from '@material-ui/core/FormLabel' +import FormControl from '@material-ui/core/FormControl' +import FormGroup from '@material-ui/core/FormGroup' +import FormControlLabel from '@material-ui/core/FormControlLabel' +import Checkbox from '@material-ui/core/Checkbox' +import Popper from '@material-ui/core/Popper' +import Paper from '@material-ui/core/Paper' + +import DynamicButton from './dynamic-button' + + +const useStyles = makeStyles(() => ({ + popper: { zIndex: 1 }, + formControl: { margin: '15px 15px 5px 15px' }, + formLabel: { fontWeight: 'bolder', marginBottom: '10px' }, + checkboxRoot: { '&:hover': { backgroundColor: 'transparent' }, padding: '0px 5px 5px 10px' }, + select: { paddingLeft: '15px' }, +})) + +const Filter = ({ + options, + anchorEl, + open, + filterVals, + selectedAll, + checkboxOnChange, + selectAllOnClick, + formLabel, +}) => { + const classes = useStyles() + return ( + + + + + {formLabel} + + {options.map((c) => ( +
+ + )} + label={c} + /> +
+ ))} +
+
+ {selectAllOnClick &&
+ + {selectedAll ? 'Unselect All' : 'Select All'} + +
} +
+
+
+ ) +} + +Filter.propTypes = { + options: PropTypes.array.isRequired, + open: PropTypes.bool.isRequired, + checkboxOnChange: PropTypes.func.isRequired, + filterVals: PropTypes.object.isRequired, + anchorEl: PropTypes.any, + selectAllOnClick: PropTypes.func, + selectedAll: PropTypes.bool, + formLabel: PropTypes.string, +} + +Filter.defaultProps = { + anchorEl: '', + selectAllOnClick: null, + selectedAll: false, + formLabel: '', +} + +export default Filter diff --git a/stories/filter.stories.js b/stories/filter.stories.js new file mode 100644 index 00000000..4bcafc14 --- /dev/null +++ b/stories/filter.stories.js @@ -0,0 +1,115 @@ +import React, { useState, useRef } from 'react' +import { Filter, DynamicButton } from '../src' + +import Grid from '@material-ui/core/Grid' +import FilterListIcon from '@material-ui/icons/FilterList' + + +export default { + component: Filter, + title: 'Filter', +} + +export const Default = () => { + const options = ['hello', 'there'] + const [open, setOpen] = useState(false) + const [filterVals, setFilterVals] = useState({ + hello: false, + there: false + }) + const ref = useRef(null) + + return ( + +
+ } + onClick={() => setOpen(!open)} + > + Filter + +
+ setFilterVals({ ...filterVals, [e.target.name]: e.target.checked })} + /> +
+ ) +} + +export const Label = () => { + const options = ['hello', 'there'] + const [open, setOpen] = useState(false) + const [filterVals, setFilterVals] = useState({ + hello: false, + there: false + }) + const ref = useRef(null) + + return ( + +
+ } + onClick={() => setOpen(!open)} + > + Filter + +
+ setFilterVals({ ...filterVals, [e.target.name]: e.target.checked })} + formLabel='Categories' + /> +
+ ) +} + +export const SelectAll = () => { + const options = ['hello', 'there'] + const [open, setOpen] = useState(false) + const [selectAll, setSelectAll] = useState(false) + const [filterVals, setFilterVals] = useState({ + hello: false, + there: false + }) + const ref = useRef(null) + + const handleSelectAll = () => { + const selectedVals = options.reduce((obj, opt) => ({ ...obj, [opt]: !selectAll }), {}) + setSelectAll(!selectAll) + setFilterVals(selectedVals) + } + + return ( + +
+ } + onClick={() => setOpen(!open)} + > + Filter + +
+ setFilterVals({ ...filterVals, [e.target.name]: e.target.checked })} + selectAllOnClick={handleSelectAll} + formLabel='Categories' + /> +
+ ) +} From 0601694b5a7c37ee6245eea6e463bd885119d1af Mon Sep 17 00:00:00 2001 From: hyx131 Date: Wed, 12 Aug 2020 10:50:18 -0400 Subject: [PATCH 2/7] filter - change mui checkbox to StyledCheckbox --- src/filter.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/filter.js b/src/filter.js index a0381760..5c51cf17 100644 --- a/src/filter.js +++ b/src/filter.js @@ -7,18 +7,18 @@ import FormLabel from '@material-ui/core/FormLabel' import FormControl from '@material-ui/core/FormControl' import FormGroup from '@material-ui/core/FormGroup' import FormControlLabel from '@material-ui/core/FormControlLabel' -import Checkbox from '@material-ui/core/Checkbox' import Popper from '@material-ui/core/Popper' import Paper from '@material-ui/core/Paper' import DynamicButton from './dynamic-button' +import StyledCheckbox from './styled-checkbox' const useStyles = makeStyles(() => ({ popper: { zIndex: 1 }, formControl: { margin: '15px 15px 5px 15px' }, formLabel: { fontWeight: 'bolder', marginBottom: '10px' }, - checkboxRoot: { '&:hover': { backgroundColor: 'transparent' }, padding: '0px 5px 5px 10px' }, + checkboxRoot: { padding: '5px 5px 5px 10px' }, select: { paddingLeft: '15px' }, })) @@ -44,13 +44,13 @@ const Filter = ({
)} label={c} From 303b964a23280dce0d50787637ba1069030106e4 Mon Sep 17 00:00:00 2001 From: hyx131 Date: Wed, 12 Aug 2020 22:41:25 -0400 Subject: [PATCH 3/7] filter - move options control and select-all control to be handled by component itself --- src/filter.js | 86 ++++++++++++++++++++++++--------------- src/index.js | 3 ++ stories/filter.stories.js | 45 +++++++------------- 3 files changed, 71 insertions(+), 63 deletions(-) diff --git a/src/filter.js b/src/filter.js index 5c51cf17..4529cb3a 100644 --- a/src/filter.js +++ b/src/filter.js @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useState } from 'react' import PropTypes from 'prop-types' import { makeStyles } from '@material-ui/core/styles' @@ -24,15 +24,39 @@ const useStyles = makeStyles(() => ({ const Filter = ({ options, + hasSelectAll, + formLabel, anchorEl, open, - filterVals, - selectedAll, - checkboxOnChange, - selectAllOnClick, - formLabel, }) => { const classes = useStyles() + const [filterVals, setFilterVals] = useState(options) + const [selectAll, setSelectAll] = useState(true) + + const checkboxOnChange = (e) => { + const newFilterVals = filterVals.map((v) => { + const [ filterName ] = Object.keys(v) + if (filterName === e.target.name) { + return { [e.target.name]: e.target.checked } + } + return v + }) + const optionsState = newFilterVals.filter((v) => !Object.values(v)[0]) + if (optionsState.length === 0) setSelectAll(!selectAll) + if (optionsState.length > 0 && !selectAll) setSelectAll(!selectAll) + setFilterVals(newFilterVals) + } + + const selectAllOnClick = () => { + const newFilterVals = filterVals.reduce((arr, opt) => { + const [ name ] = Object.keys(opt) + arr.push({ [name]: selectAll }) + return arr + }, []) + setFilterVals(newFilterVals) + setSelectAll(!selectAll) + } + return ( @@ -40,32 +64,33 @@ const Filter = ({ {formLabel} - {options.map((c) => ( -
- - )} - label={c} - /> -
- ))} + {filterVals.map((val) => { + const [optionName, optionState] = Object.entries(val)[0] + return ( +
+ + )} + label={optionName} + /> +
+ ) + })}
- {selectAllOnClick &&
+ {hasSelectAll &&
- {selectedAll ? 'Unselect All' : 'Select All'} + {selectAll ? 'Select All' : 'Reset'}
} @@ -76,20 +101,15 @@ const Filter = ({ Filter.propTypes = { options: PropTypes.array.isRequired, + formLabel: PropTypes.string.isRequired, open: PropTypes.bool.isRequired, - checkboxOnChange: PropTypes.func.isRequired, - filterVals: PropTypes.object.isRequired, anchorEl: PropTypes.any, - selectAllOnClick: PropTypes.func, - selectedAll: PropTypes.bool, - formLabel: PropTypes.string, + hasSelectAll: PropTypes.bool, } Filter.defaultProps = { anchorEl: '', - selectAllOnClick: null, - selectedAll: false, - formLabel: '', + hasSelectAll: false, } export default Filter diff --git a/src/index.js b/src/index.js index b273e735..f0a802bf 100644 --- a/src/index.js +++ b/src/index.js @@ -25,6 +25,7 @@ import TextFieldComponent from './text-field' import WidgetStatsComponent from './widget-stats' // export { default as WidgetNumber } from './widget-number' // deprecated by WidgetStats // export { default as WidgetTrend } from './widget-trend' // deprecated by WidgetStats +import FilterComponent from './filter' const wrapTheme = (WrappedComponent, theme = defaultTheme) => { class Wrapper extends React.PureComponent { @@ -57,6 +58,7 @@ const StyledSwitch = wrapTheme(StyledSwitchComponent) const TabPanels = wrapTheme(TabPanelsComponent) const TextField = wrapTheme(TextFieldComponent) const WidgetStats = wrapTheme(WidgetStatsComponent) +const Filter = wrapTheme(FilterComponent) export { Alert, @@ -77,4 +79,5 @@ export { TabPanels, TextField, WidgetStats, + Filter, } diff --git a/stories/filter.stories.js b/stories/filter.stories.js index 4bcafc14..d2af145b 100644 --- a/stories/filter.stories.js +++ b/stories/filter.stories.js @@ -11,12 +11,11 @@ export default { } export const Default = () => { - const options = ['hello', 'there'] const [open, setOpen] = useState(false) - const [filterVals, setFilterVals] = useState({ - hello: false, - there: false - }) + const options = [ + { hello: false }, + { there: false }, + ] const ref = useRef(null) return ( @@ -33,21 +32,18 @@ export const Default = () => { setFilterVals({ ...filterVals, [e.target.name]: e.target.checked })} /> ) } export const Label = () => { - const options = ['hello', 'there'] + const options = [ + { hello: false }, + { there: false }, + ] const [open, setOpen] = useState(false) - const [filterVals, setFilterVals] = useState({ - hello: false, - there: false - }) const ref = useRef(null) return ( @@ -64,9 +60,7 @@ export const Label = () => { setFilterVals({ ...filterVals, [e.target.name]: e.target.checked })} formLabel='Categories' /> @@ -74,21 +68,15 @@ export const Label = () => { } export const SelectAll = () => { - const options = ['hello', 'there'] + const options = [ + { hello: false }, + { there: false }, + { hi: false }, + { bye: false }, + ] const [open, setOpen] = useState(false) - const [selectAll, setSelectAll] = useState(false) - const [filterVals, setFilterVals] = useState({ - hello: false, - there: false - }) const ref = useRef(null) - const handleSelectAll = () => { - const selectedVals = options.reduce((obj, opt) => ({ ...obj, [opt]: !selectAll }), {}) - setSelectAll(!selectAll) - setFilterVals(selectedVals) - } - return (
@@ -103,12 +91,9 @@ export const SelectAll = () => { setFilterVals({ ...filterVals, [e.target.name]: e.target.checked })} - selectAllOnClick={handleSelectAll} formLabel='Categories' + hasSelectAll /> ) From 36d0d74955565546149cb9f7b193e3e8c53b908c Mon Sep 17 00:00:00 2001 From: hyx131 Date: Wed, 12 Aug 2020 22:56:10 -0400 Subject: [PATCH 4/7] filter - move filter button inside component --- src/filter.js | 121 +++++++++++++++++++++++--------------- stories/filter.stories.js | 107 +++++++++------------------------ 2 files changed, 103 insertions(+), 125 deletions(-) diff --git a/src/filter.js b/src/filter.js index 4529cb3a..86c2ad6f 100644 --- a/src/filter.js +++ b/src/filter.js @@ -1,14 +1,14 @@ -import React, { useState } from 'react' +import React, { useState, useRef } from 'react' import PropTypes from 'prop-types' import { makeStyles } from '@material-ui/core/styles' import Grid from '@material-ui/core/Grid' -import FormLabel from '@material-ui/core/FormLabel' import FormControl from '@material-ui/core/FormControl' import FormGroup from '@material-ui/core/FormGroup' import FormControlLabel from '@material-ui/core/FormControlLabel' import Popper from '@material-ui/core/Popper' import Paper from '@material-ui/core/Paper' +import Typography from '@material-ui/core/Typography' import DynamicButton from './dynamic-button' import StyledCheckbox from './styled-checkbox' @@ -16,22 +16,25 @@ import StyledCheckbox from './styled-checkbox' const useStyles = makeStyles(() => ({ popper: { zIndex: 1 }, + paper: { paddingBottom: '10px' }, formControl: { margin: '15px 15px 5px 15px' }, - formLabel: { fontWeight: 'bolder', marginBottom: '10px' }, checkboxRoot: { padding: '5px 5px 5px 10px' }, select: { paddingLeft: '15px' }, })) const Filter = ({ + icon, + label, options, + optionsLabel, hasSelectAll, - formLabel, - anchorEl, - open, + onChange, }) => { const classes = useStyles() + const [open, setOpen] = useState(false) const [filterVals, setFilterVals] = useState(options) const [selectAll, setSelectAll] = useState(true) + const ref = useRef(null) const checkboxOnChange = (e) => { const newFilterVals = filterVals.map((v) => { @@ -45,6 +48,13 @@ const Filter = ({ if (optionsState.length === 0) setSelectAll(!selectAll) if (optionsState.length > 0 && !selectAll) setSelectAll(!selectAll) setFilterVals(newFilterVals) + + const selectedVals = newFilterVals.reduce((arr, val) => { + const [ name, selected ] = Object.entries(val)[0] + if (selected) arr.push(name) + return arr + }, []) + onChange(newFilterVals, selectedVals) } const selectAllOnClick = () => { @@ -55,61 +65,78 @@ const Filter = ({ }, []) setFilterVals(newFilterVals) setSelectAll(!selectAll) + + const selectedVals = newFilterVals.reduce((arr, val) => { + const [ name, selected ] = Object.entries(val)[0] + if (selected) arr.push(name) + return arr + }, []) + onChange(newFilterVals, selectedVals) } return ( - - - - - {formLabel} - - {filterVals.map((val) => { - const [optionName, optionState] = Object.entries(val)[0] - return ( -
- - )} - label={optionName} - /> -
- ) - })} -
-
- {hasSelectAll &&
- - {selectAll ? 'Select All' : 'Reset'} - -
} -
-
-
+ +
+ setOpen(!open)}> + {label} + +
+ + + + + {optionsLabel} + + {filterVals.map((val) => { + const [optionName, optionState] = Object.entries(val)[0] + return ( +
+ + )} + label={optionName} + /> +
+ ) + })} +
+
+ {hasSelectAll &&
+ + {selectAll ? 'Select All' : 'Reset'} + +
} +
+
+
+
) } Filter.propTypes = { options: PropTypes.array.isRequired, - formLabel: PropTypes.string.isRequired, - open: PropTypes.bool.isRequired, - anchorEl: PropTypes.any, + optionsLabel: PropTypes.string.isRequired, + label: PropTypes.string.isRequired, + icon: PropTypes.any, hasSelectAll: PropTypes.bool, + onChange: PropTypes.func, } Filter.defaultProps = { + icon: '', anchorEl: '', hasSelectAll: false, + onChange: () => {}, } export default Filter diff --git a/stories/filter.stories.js b/stories/filter.stories.js index d2af145b..ed4f6fea 100644 --- a/stories/filter.stories.js +++ b/stories/filter.stories.js @@ -1,7 +1,6 @@ -import React, { useState, useRef } from 'react' -import { Filter, DynamicButton } from '../src' +import React from 'react' +import { Filter } from '../src' -import Grid from '@material-ui/core/Grid' import FilterListIcon from '@material-ui/icons/FilterList' @@ -11,90 +10,42 @@ export default { } export const Default = () => { - const [open, setOpen] = useState(false) - const options = [ - { hello: false }, - { there: false }, - ] - const ref = useRef(null) - + const options = [ { hello: false }, { there: false } ] return ( - -
- } - onClick={() => setOpen(!open)} - > - Filter - -
- -
+ ) } -export const Label = () => { - const options = [ - { hello: false }, - { there: false }, - ] - const [open, setOpen] = useState(false) - const ref = useRef(null) - +export const Icon = () => { + const options = [ { hello: false }, { there: false } ] return ( - -
- } - onClick={() => setOpen(!open)} - > - Filter - -
- -
+ } + label='Filter' + options={options} + optionsLabel='Categories' + /> ) } export const SelectAll = () => { - const options = [ - { hello: false }, - { there: false }, - { hi: false }, - { bye: false }, - ] - const [open, setOpen] = useState(false) - const ref = useRef(null) - + const options = [ { hello: false }, { there: false }, { hi: false }, { bye: false } ] + const checkboxOnChange = (newFilterVals, selectedVals) => { + console.log('newFilters: ', newFilterVals) + console.log('selectedVals: ', selectedVals) + } return ( - -
- } - onClick={() => setOpen(!open)} - > - Filter - -
- -
+ } + label='Filter' + options={options} + optionsLabel='Categories' + hasSelectAll + onChange={checkboxOnChange} + /> ) } From 519314539e14dbc5fef01678fb71ed6450deaa27 Mon Sep 17 00:00:00 2001 From: hyx131 Date: Fri, 21 Aug 2020 15:52:44 -0400 Subject: [PATCH 5/7] filter/selectionGroup - change component filter to SelectionGroup - will focus only on select option groups, not filter wrapper --- src/index.js | 6 +- src/{filter.js => selection-group.js} | 97 +++++++++++---------------- stories/filter.stories.js | 17 ++--- 3 files changed, 48 insertions(+), 72 deletions(-) rename src/{filter.js => selection-group.js} (52%) diff --git a/src/index.js b/src/index.js index f0a802bf..d5940de9 100644 --- a/src/index.js +++ b/src/index.js @@ -25,7 +25,7 @@ import TextFieldComponent from './text-field' import WidgetStatsComponent from './widget-stats' // export { default as WidgetNumber } from './widget-number' // deprecated by WidgetStats // export { default as WidgetTrend } from './widget-trend' // deprecated by WidgetStats -import FilterComponent from './filter' +import SelectionGroupComponent from './selection-group' const wrapTheme = (WrappedComponent, theme = defaultTheme) => { class Wrapper extends React.PureComponent { @@ -58,7 +58,7 @@ const StyledSwitch = wrapTheme(StyledSwitchComponent) const TabPanels = wrapTheme(TabPanelsComponent) const TextField = wrapTheme(TextFieldComponent) const WidgetStats = wrapTheme(WidgetStatsComponent) -const Filter = wrapTheme(FilterComponent) +const SelectionGroup = wrapTheme(SelectionGroupComponent) export { Alert, @@ -79,5 +79,5 @@ export { TabPanels, TextField, WidgetStats, - Filter, + SelectionGroup, } diff --git a/src/filter.js b/src/selection-group.js similarity index 52% rename from src/filter.js rename to src/selection-group.js index 86c2ad6f..a37ec271 100644 --- a/src/filter.js +++ b/src/selection-group.js @@ -1,4 +1,4 @@ -import React, { useState, useRef } from 'react' +import React, { useState } from 'react' import PropTypes from 'prop-types' import { makeStyles } from '@material-ui/core/styles' @@ -6,7 +6,6 @@ import Grid from '@material-ui/core/Grid' import FormControl from '@material-ui/core/FormControl' import FormGroup from '@material-ui/core/FormGroup' import FormControlLabel from '@material-ui/core/FormControlLabel' -import Popper from '@material-ui/core/Popper' import Paper from '@material-ui/core/Paper' import Typography from '@material-ui/core/Typography' @@ -22,19 +21,15 @@ const useStyles = makeStyles(() => ({ select: { paddingLeft: '15px' }, })) -const Filter = ({ - icon, - label, +const SelectionGroup = ({ options, optionsLabel, hasSelectAll, onChange, }) => { const classes = useStyles() - const [open, setOpen] = useState(false) const [filterVals, setFilterVals] = useState(options) const [selectAll, setSelectAll] = useState(true) - const ref = useRef(null) const checkboxOnChange = (e) => { const newFilterVals = filterVals.map((v) => { @@ -75,68 +70,56 @@ const Filter = ({ } return ( - -
- setOpen(!open)}> - {label} - -
- - - - - {optionsLabel} - - {filterVals.map((val) => { - const [optionName, optionState] = Object.entries(val)[0] - return ( -
- - )} - label={optionName} + + + + {optionsLabel} + + {filterVals.map((val) => { + const [optionName, optionState] = Object.entries(val)[0] + return ( +
+ -
- ) - })} -
-
- {hasSelectAll &&
- - {selectAll ? 'Select All' : 'Reset'} - -
} -
-
- - + )} + label={optionName} + /> +
+ ) + })} +
+
+ {hasSelectAll &&
+ + {selectAll ? 'Select All' : 'Reset'} + +
} +
+
) } -Filter.propTypes = { +SelectionGroup.propTypes = { options: PropTypes.array.isRequired, optionsLabel: PropTypes.string.isRequired, - label: PropTypes.string.isRequired, - icon: PropTypes.any, hasSelectAll: PropTypes.bool, onChange: PropTypes.func, } -Filter.defaultProps = { - icon: '', +SelectionGroup.defaultProps = { anchorEl: '', hasSelectAll: false, onChange: () => {}, } -export default Filter +export default SelectionGroup diff --git a/stories/filter.stories.js b/stories/filter.stories.js index ed4f6fea..2f2bb4a6 100644 --- a/stories/filter.stories.js +++ b/stories/filter.stories.js @@ -1,19 +1,16 @@ import React from 'react' -import { Filter } from '../src' - -import FilterListIcon from '@material-ui/icons/FilterList' +import { SelectionGroup } from '../src' export default { - component: Filter, + component: SelectionGroup, title: 'Filter', } export const Default = () => { const options = [ { hello: false }, { there: false } ] return ( - @@ -23,9 +20,7 @@ export const Default = () => { export const Icon = () => { const options = [ { hello: false }, { there: false } ] return ( - } - label='Filter' + @@ -39,9 +34,7 @@ export const SelectAll = () => { console.log('selectedVals: ', selectedVals) } return ( - } - label='Filter' + Date: Sat, 22 Aug 2020 00:57:39 -0400 Subject: [PATCH 6/7] filter/SelectionGroup - radioGroup & checkboxGroup with selection controls & row-column view --- src/selection-group/checkbox-group.js | 41 +++++++++++++ .../index.js} | 40 +++++-------- src/selection-group/radio-group.js | 42 ++++++++++++++ stories/filter.stories.js | 44 -------------- stories/selection-group.stories.js | 58 +++++++++++++++++++ 5 files changed, 154 insertions(+), 71 deletions(-) create mode 100644 src/selection-group/checkbox-group.js rename src/{selection-group.js => selection-group/index.js} (73%) create mode 100644 src/selection-group/radio-group.js delete mode 100644 stories/filter.stories.js create mode 100644 stories/selection-group.stories.js diff --git a/src/selection-group/checkbox-group.js b/src/selection-group/checkbox-group.js new file mode 100644 index 00000000..ef5eaf95 --- /dev/null +++ b/src/selection-group/checkbox-group.js @@ -0,0 +1,41 @@ +import React from 'react' +import PropTypes from 'prop-types' + +import FormGroup from '@material-ui/core/FormGroup' +import FormControlLabel from '@material-ui/core/FormControlLabel' +import Grid from '@material-ui/core/Grid' + +import StyledCheckbox from '../styled-checkbox' + + +const CheckboxGroup = ({ filterVals, checkboxOnChange, direction }) => ( + + + {filterVals.map((val) => { + const [optionName, optionState] = Object.entries(val)[0] + return ( +
+ + )} + label={optionName} + /> +
+ ) + })} +
+
+) + +CheckboxGroup.propTypes = { + filterVals: PropTypes.array.isRequired, + checkboxOnChange: PropTypes.func.isRequired, + direction: PropTypes.string.isRequired, +} + +export default CheckboxGroup diff --git a/src/selection-group.js b/src/selection-group/index.js similarity index 73% rename from src/selection-group.js rename to src/selection-group/index.js index a37ec271..f29235a7 100644 --- a/src/selection-group.js +++ b/src/selection-group/index.js @@ -4,28 +4,27 @@ import PropTypes from 'prop-types' import { makeStyles } from '@material-ui/core/styles' import Grid from '@material-ui/core/Grid' import FormControl from '@material-ui/core/FormControl' -import FormGroup from '@material-ui/core/FormGroup' -import FormControlLabel from '@material-ui/core/FormControlLabel' import Paper from '@material-ui/core/Paper' import Typography from '@material-ui/core/Typography' -import DynamicButton from './dynamic-button' -import StyledCheckbox from './styled-checkbox' +import DynamicButton from '../dynamic-button' +import CheckboxGroup from './checkbox-group' +import RadioGroup from './radio-group' const useStyles = makeStyles(() => ({ - popper: { zIndex: 1 }, paper: { paddingBottom: '10px' }, formControl: { margin: '15px 15px 5px 15px' }, - checkboxRoot: { padding: '5px 5px 5px 10px' }, select: { paddingLeft: '15px' }, })) const SelectionGroup = ({ + type, options, optionsLabel, hasSelectAll, onChange, + direction, }) => { const classes = useStyles() const [filterVals, setFilterVals] = useState(options) @@ -74,28 +73,12 @@ const SelectionGroup = ({ {optionsLabel} - - {filterVals.map((val) => { - const [optionName, optionState] = Object.entries(val)[0] - return ( -
- - )} - label={optionName} - /> -
- ) - })} -
+ {type === 'checkbox' && ( + + )} + {type === 'radio' && ()}
- {hasSelectAll &&
+ {hasSelectAll && type === 'checkbox' &&
{}, + direction: 'column', } export default SelectionGroup diff --git a/src/selection-group/radio-group.js b/src/selection-group/radio-group.js new file mode 100644 index 00000000..6154cbe0 --- /dev/null +++ b/src/selection-group/radio-group.js @@ -0,0 +1,42 @@ +import React, { useState } from 'react' +import PropTypes from 'prop-types' + +import MUIRadioGroup from '@material-ui/core/RadioGroup' +import FormControlLabel from '@material-ui/core/FormControlLabel' +import Grid from '@material-ui/core/Grid' + +import StyledRadio from '../styled-radio' + + +const RadioGroup = ({ options, onChange, direction }) => { + const [val, setVal] = useState(options[0]) + + const radioOnChange = (e) => { + setVal(e.target.value) + onChange(e.target.value) + } + + return ( + + + {options.map((o, i) => ( +
+ )} + label={o} + /> +
+ ))} +
+
+ ) +} + +RadioGroup.propTypes = { + options: PropTypes.array.isRequired, + onChange: PropTypes.func.isRequired, + direction: PropTypes.string.isRequired, +} + +export default RadioGroup diff --git a/stories/filter.stories.js b/stories/filter.stories.js deleted file mode 100644 index 2f2bb4a6..00000000 --- a/stories/filter.stories.js +++ /dev/null @@ -1,44 +0,0 @@ -import React from 'react' -import { SelectionGroup } from '../src' - - -export default { - component: SelectionGroup, - title: 'Filter', -} - -export const Default = () => { - const options = [ { hello: false }, { there: false } ] - return ( - - ) -} - -export const Icon = () => { - const options = [ { hello: false }, { there: false } ] - return ( - - ) -} - -export const SelectAll = () => { - const options = [ { hello: false }, { there: false }, { hi: false }, { bye: false } ] - const checkboxOnChange = (newFilterVals, selectedVals) => { - console.log('newFilters: ', newFilterVals) - console.log('selectedVals: ', selectedVals) - } - return ( - - ) -} diff --git a/stories/selection-group.stories.js b/stories/selection-group.stories.js new file mode 100644 index 00000000..13e7ccf8 --- /dev/null +++ b/stories/selection-group.stories.js @@ -0,0 +1,58 @@ +import React from 'react' +import { SelectionGroup } from '../src' + + +export default { + component: SelectionGroup, + title: 'SelectionGroup', +} + +export const Radio = () => { + const options = ['hello', 'there', 'hi', 'bye'] + const radioOnChange = (newVal) => console.log('newVal: ', newVal) + + return ( + <> + + + + ) +} + +export const Checkbox = () => { + const options = [ { hello: false }, { there: false }, { hi: false }, { bye: false } ] + const checkboxOnChange = (newFilterVals, selectedVals) => { + console.log('newFilters: ', newFilterVals) + console.log('selectedVals: ', selectedVals) + } + return ( + <> + + + + ) +} From 65a71f0bba2ec463edf62f7296522d2c411ad4c2 Mon Sep 17 00:00:00 2001 From: hyx131 Date: Sat, 22 Aug 2020 19:17:29 -0400 Subject: [PATCH 7/7] filter/SelectionGroup - switchGroup & sliderGroup with selection controls & row-column view --- src/selection-group/index.js | 41 +++++++---- src/selection-group/slider-group.js | 106 ++++++++++++++++++++++++++++ src/selection-group/switch-group.js | 41 +++++++++++ stories/selection-group.stories.js | 52 ++++++++++++++ 4 files changed, 228 insertions(+), 12 deletions(-) create mode 100644 src/selection-group/slider-group.js create mode 100644 src/selection-group/switch-group.js diff --git a/src/selection-group/index.js b/src/selection-group/index.js index f29235a7..9841cc4d 100644 --- a/src/selection-group/index.js +++ b/src/selection-group/index.js @@ -10,6 +10,8 @@ import Typography from '@material-ui/core/Typography' import DynamicButton from '../dynamic-button' import CheckboxGroup from './checkbox-group' import RadioGroup from './radio-group' +import SwitchGroup from './switch-group' +import SliderGroup from './slider-group' const useStyles = makeStyles(() => ({ @@ -22,9 +24,10 @@ const SelectionGroup = ({ type, options, optionsLabel, - hasSelectAll, onChange, direction, + hasSelectAll, + sliderStep, }) => { const classes = useStyles() const [filterVals, setFilterVals] = useState(options) @@ -77,16 +80,25 @@ const SelectionGroup = ({ )} {type === 'radio' && ()} + {type === 'switch' && ( + + )} + {type === 'slider' && ( + + )} - {hasSelectAll && type === 'checkbox' &&
- - {selectAll ? 'Select All' : 'Reset'} - -
} + {hasSelectAll && + type !== 'radio' && + type !== 'slider' && +
+ + {selectAll ? 'Select All' : 'Reset'} + +
} ) @@ -94,18 +106,23 @@ const SelectionGroup = ({ SelectionGroup.propTypes = { options: PropTypes.array.isRequired, - optionsLabel: PropTypes.string.isRequired, type: PropTypes.string.isRequired, + optionsLabel: PropTypes.string, hasSelectAll: PropTypes.bool, onChange: PropTypes.func, direction: PropTypes.string, + sliderStep: PropTypes.oneOfType([ + PropTypes.number, + PropTypes.string, + ]), } SelectionGroup.defaultProps = { - anchorEl: '', hasSelectAll: false, onChange: () => {}, direction: 'column', + optionsLabel: '', + sliderStep: 1, } export default SelectionGroup diff --git a/src/selection-group/slider-group.js b/src/selection-group/slider-group.js new file mode 100644 index 00000000..655f60e4 --- /dev/null +++ b/src/selection-group/slider-group.js @@ -0,0 +1,106 @@ +import React, { useState } from 'react' +import PropTypes from 'prop-types' + +import { makeStyles } from '@material-ui/core/styles' +import Grid from '@material-ui/core/Grid' +import Slider from '@material-ui/core/Slider' +import FormControl from '@material-ui/core/FormControl' +import Input from '@material-ui/core/Input' + + +const useStyles = makeStyles(() => ({ + sliderInput: { + boxSizing: 'border-box', + marginRight: '4px', + padding: '4px', + border: '1px solid', + borderRadius: '4px', + }, + verHeight: { height: '300px' }, +})) +const SliderGroup = ({ sliderStep, options, direction, onChange }) => { + const classes = useStyles() + const orientation = direction === 'column' ? 'vertical' : 'horizontal' + const gridContainerProps = direction === 'column' + ? { container: true, direction: 'row-reverse', justify: 'center', alignItems:'center' } + : {} + const gridSliderProps = direction === 'column' ? { item: true, xs: 6 } : {} + const gridInputProps = direction === 'column' + ? { + item: true, + container: true, + direction: 'column-reverse', + alignItems: 'center', + justify: 'space-between', + } + : {} + + let [min, max, initialMin = '', initialMax = ''] = options + if (!initialMin && initialMin !== 0) initialMin = min + if (!initialMax) initialMax = max + + const [val, setVal] = useState([initialMin, initialMax]) + const [currentMin, currentMax] = val + + const sliderOnChange = (_, val) => { + setVal(val) + onChange(val) + } + + const minOnChange = (e) => setVal([e.target.value, currentMax]) + const maxOnChange = (e) => setVal([currentMin, e.target.value]) + + return ( + + + + + + + + + + + + + + + + ) +} + +SliderGroup.propTypes = { + onChange: PropTypes.func.isRequired, + options: PropTypes.array.isRequired, + sliderStep: PropTypes.oneOfType([ + PropTypes.number, + PropTypes.string, + ]), + direction: PropTypes.string, +} + +SliderGroup.defaultProps = { + direction: 'row', +} + +export default SliderGroup diff --git a/src/selection-group/switch-group.js b/src/selection-group/switch-group.js new file mode 100644 index 00000000..4de0c32e --- /dev/null +++ b/src/selection-group/switch-group.js @@ -0,0 +1,41 @@ +import React from 'react' +import PropTypes from 'prop-types' + +import FormGroup from '@material-ui/core/FormGroup' +import FormControlLabel from '@material-ui/core/FormControlLabel' +import Grid from '@material-ui/core/Grid' +import Switch from '@material-ui/core/Switch' + + +const SwitchGroup = ({ filterVals, switchOnChange, direction }) => ( + + + {filterVals.map((val) => { + const [optionName, optionState] = Object.entries(val)[0] + return ( +
+ + )} + label={optionName} + /> +
+ ) + })} +
+
+) + +SwitchGroup.propTypes = { + filterVals: PropTypes.array.isRequired, + switchOnChange: PropTypes.func.isRequired, + direction: PropTypes.string.isRequired, +} + +export default SwitchGroup diff --git a/stories/selection-group.stories.js b/stories/selection-group.stories.js index 13e7ccf8..bcde24fe 100644 --- a/stories/selection-group.stories.js +++ b/stories/selection-group.stories.js @@ -56,3 +56,55 @@ export const Checkbox = () => { ) } + +export const Switch = () => { + const options = [ { hello: false }, { there: false }, { hi: false }, { bye: false } ] + const switchOnChange = (newFilterVals, selectedVals) => { + console.log('newFilters: ', newFilterVals) + console.log('selectedVals: ', selectedVals) + } + return ( + <> + + + + ) +} + +export const Slider = () => { + // options format = [min, max, initialMin, initialMax] --> last 2 is optional + const options = [0, 1000, 500, 1000] + const sliderOnChange = (val) => console.log('val: ', val) + + return ( + <> + + + + ) +}