fk-react-ui-components
Version:
Step 1 : Create a file in [ Seeds / Plants / Trees ] <br> Step 2 : It should export an Object with component name and story Component [Refer other components] <br> Step 3 : Story Component should return a react component <br> Step 3 : Created file should
300 lines (279 loc) • 10.2 kB
JavaScript
/**
* Created by manoraj.k on 17/08/17.
*/
import React from 'react';
import _ from 'lodash';
import PropTypes from 'prop-types';
import {
CheckboxTreeFilterContainer,
Chip,
ChipContainer,
Filter
} from './styles/CheckboxTreeFilter';
import ToggleComponent from '../ToggleComponent';
import Card from '../Card';
import CheckboxTree from '../CheckboxTree';
import SimpleSearch from '../SimpleSearch';
import { colors } from './../colorCodes';
const snakeCaseCapitalize = function snakeCaseCapitalize(strn) {
if (strn) {
const str = strn.toLowerCase();
const newStrArr = str.split('_');
const isUnderscorePresent = str.indexOf('_') > -1;
let newStr = '';
for (let i = 0; i < newStrArr.length; i++) {
newStr +=
newStrArr[i].charAt(0).toUpperCase() +
newStrArr[i].substring(1) +
(isUnderscorePresent ? ' ' : '');
}
return newStr;
}
return '';
};
const filterNodes = function filterNodes(nodes, value, root, expanded) {
_.each(nodes, node => {
const nodeName = node.value
.replace(/_+?/g, '')
.toLowerCase()
.indexOf(value.trim().toLowerCase());
if (Object.prototype.hasOwnProperty.call(node, 'children')) {
filterNodes(node.children, value, false, expanded);
node.children = _.filter(node.children, child => child.search);
if (node.children.length > 0) {
node.search = true;
expanded.push(node.value);
} else {
node.search = false;
}
} else if (nodeName > -1) {
node.search = true;
} else {
node.search = false;
}
});
if (root) {
return _.filter(nodes, node => node.search);
}
};
class CheckboxTreeFilter extends React.Component {
constructor(props) {
super();
this.state = {
checked: props.checked || [],
expanded: props.expanded || [],
search: props.searchValue || '',
nodes: props.nodes,
showAllFilters: false
};
this.nodes = _.cloneDeep(props.nodes);
this.searchThreshold = props.searchThreshold || 2;
_.bindAll(
this,
'onSearchType',
'isFilterActive',
'resetFilters',
'clearFilter',
'onFilterChange',
'onFilterExpand',
'toggleFilter',
'showFilters'
);
}
componentWillReceiveProps(nextProps) {
if (
!_.isEqual(this.state.nodes, nextProps.nodes) ||
(nextProps.checked &&
!_.isEqual(this.state.checked, nextProps.checked))
) {
this.nodes = _.cloneDeep(nextProps.nodes);
this.setState({
nodes: nextProps.nodes,
checked: nextProps.checked
});
}
}
componentDidUpdate(prevProps, prevState) {
if (this.state.checked.length !== prevState.checked.length) {
if (this.props.onChange) {
this.props.onChange(this.state.checked, this.props.name);
}
}
}
onFilterChange(checked) {
this.setState({ checked });
}
onSearchType(value) {
if (value.length <= 0) {
this.setState({ nodes: this.nodes });
} else if (value.length > this.searchThreshold) {
const expanded = [];
this.expanded = this.state.expanded;
this.checked = this.state.checked;
const newNodes = filterNodes(
_.cloneDeep(this.nodes),
value,
true,
expanded
);
this.setState({ nodes: newNodes, expanded });
}
}
onFilterExpand(expanded) {
this.setState({ expanded });
}
clearFilter(index) {
const checked = _.cloneDeep(this.state).checked;
checked.splice(index, 1);
this.setState({
checked,
showAllFilters:
checked.length <= this.props.showFilterOption
? false
: this.state.showAllFilters
});
}
resetFilters() {
this.setState({ checked: [], showAllFilters: false });
}
isFilterActive() {
return this.state.checked.length > 0;
}
toggleFilter() {
this.setState(prevState => ({
showAllFilters: !prevState.showAllFilters
}));
}
showFilters(initShowFilters) {
const countCheckItems = this.state.checked.length;
if (countCheckItems) {
let filters = null;
if (countCheckItems > initShowFilters) {
filters = (
<Filter onClick={this.toggleFilter}>
{this.state.showAllFilters
? 'Show Less'
: `Show More (${countCheckItems -
initShowFilters})`}
</Filter>
);
}
return (
<ChipContainer className="selected-values-container">
{this.state.checked.map((filter, index) => {
const display =
index < initShowFilters
? 'inline-block'
: this.state.showAllFilters
? 'inline-block'
: 'none';
return (
<div>
<Chip
key={filter}
style={{
display,
whiteSpace: 'nowrap'
}}
onClick={() => {
this.clearFilter(index);
}}
>
<span style={{ paddingRight: '5px' }}>
{snakeCaseCapitalize(filter)}
</span>
<i
className="fa fa-times"
aria-hidden="true"
/>
</Chip>
</div>
);
})}
{filters}
</ChipContainer>
);
}
return null;
}
render() {
return (
<CheckboxTreeFilterContainer className={this.props.className}>
<ToggleComponent
label={this.props.label}
name={this.props.name}
resetFilters={this.resetFilters}
activeFilter={this.isFilterActive()}
default={this.props.defaultShow}
>
{this.props.type === 'checkbox' && (
<Card
width="auto"
position="absolute"
padding="10px"
boxShadow="rgba(208, 208, 208, 0.5) 1px 0px 6px 0px"
zIndex="1"
className="checkbox-toggle-content"
>
{this.showFilters(this.props.showFilterOption)}
{this.props.includeSearch && (
<SimpleSearch
width="100%"
height="23px"
padding="0px"
className={this.props.searchClassName}
placeholder={this.props.placeholder}
backgroundColor={colors.whiteText}
value={this.state.search}
onChange={this.onSearchType}
fontSize="12px"
/>
)}
<CheckboxTree
nodes={this.state.nodes}
showNodeIcon={false}
expanded={this.state.expanded}
checked={this.state.checked}
onCheck={this.onFilterChange}
onExpand={this.onFilterExpand}
height={this.props.treeHeight}
className="check-box-tree-container"
/>
</Card>
)}
</ToggleComponent>
</CheckboxTreeFilterContainer>
);
}
}
export default CheckboxTreeFilter;
CheckboxTreeFilter.propTypes = {
checked: PropTypes.arrayOf(PropTypes.string).isRequired,
expanded: PropTypes.arrayOf(PropTypes.string).isRequired,
searchValue: PropTypes.string.isRequired,
nodes: PropTypes.arrayOf(
PropTypes.shape({
label: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
className: PropTypes.string,
children: PropTypes.array
})
).isRequired,
searchThreshold: PropTypes.number,
name: PropTypes.string.isRequired,
showFilterOption: PropTypes.number,
className: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
defaultShow: PropTypes.bool.isRequired,
type: PropTypes.string.isRequired,
includeSearch: PropTypes.bool.isRequired,
searchClassName: PropTypes.string.isRequired,
placeholder: PropTypes.string.isRequired,
treeHeight: PropTypes.string.isRequired,
onChange: PropTypes.func
};
CheckboxTreeFilter.defaultProps = {
onChange: undefined,
searchThreshold: 2,
showFilterOption: 2
};